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 --- GPLv2 | 340 ++ INSTALL | 35 + LICENSE | 12 + NEWS | 227 + README | 19 + build/bootstrap.make | 54 + build/configuration-rules.make | 18 + build/configuration.make | 54 + build/configure | 160 + build/import/libbackend-elements/LICENSE | 340 ++ .../libbackend-elements/configuration-rules.make | 15 + build/import/libbackend-elements/configure | 55 + build/import/libbackend-elements/stub.make | 32 + build/import/libboost/LICENSE | 340 ++ build/import/libboost/configuration-rules.make | 15 + build/import/libboost/configure | 83 + build/import/libboost/date-time/rules.make | 39 + build/import/libboost/date-time/stub.make | 32 + build/import/libboost/filesystem/rules.make | 41 + build/import/libboost/filesystem/stub.make | 32 + build/import/libboost/regex/rules.make | 38 + build/import/libboost/regex/stub.make | 32 + build/import/libboost/version | 1 + build/import/libcult/LICENSE | 340 ++ build/import/libcult/configuration-rules.make | 15 + build/import/libcult/configure | 55 + build/import/libcult/stub.make | 30 + build/import/libxsd-frontend/LICENSE | 22 + .../libxsd-frontend/configuration-rules.make | 15 + build/import/libxsd-frontend/configure | 55 + build/import/libxsd-frontend/stub.make | 30 + build/xsde/hybrid/xsd-cxx.make | 139 + build/xsde/parser/xsd-cxx.make | 103 + build/xsde/serializer/xsd-cxx.make | 103 + documentation/cxx/hybrid/guide/figure-1.png | Bin 0 -> 11933 bytes documentation/cxx/hybrid/guide/figure-1.svg | 217 + documentation/cxx/hybrid/guide/guide.html2ps | 65 + documentation/cxx/hybrid/guide/index.xhtml | 5099 ++++++++++++++++ documentation/cxx/hybrid/guide/makefile | 12 + documentation/cxx/parser/guide/figure-1.png | Bin 0 -> 34195 bytes documentation/cxx/parser/guide/figure-1.svg | 373 ++ documentation/cxx/parser/guide/guide.html2ps | 65 + documentation/cxx/parser/guide/index.xhtml | 5236 ++++++++++++++++ documentation/cxx/parser/guide/makefile | 12 + documentation/cxx/serializer/guide/figure-1.png | Bin 0 -> 30198 bytes documentation/cxx/serializer/guide/figure-1.svg | 372 ++ documentation/cxx/serializer/guide/guide.html2ps | 65 + documentation/cxx/serializer/guide/index.xhtml | 6391 ++++++++++++++++++++ documentation/cxx/serializer/guide/makefile | 12 + documentation/default.css | 319 + documentation/makefile | 18 + documentation/xsde.1 | 1940 ++++++ documentation/xsde.xhtml | 1578 +++++ 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 + examples/makefile | 20 + libxsde/makefile | 26 + libxsde/xsde/c/expat/COPYING | 22 + libxsde/xsde/c/expat/ascii.h | 85 + libxsde/xsde/c/expat/asciitab.h | 36 + libxsde/xsde/c/expat/config.h | 42 + libxsde/xsde/c/expat/expat.h | 1013 ++++ libxsde/xsde/c/expat/expat_external.h | 119 + libxsde/xsde/c/expat/iasciitab.h | 37 + libxsde/xsde/c/expat/internal.h | 73 + libxsde/xsde/c/expat/latin1tab.h | 36 + libxsde/xsde/c/expat/nametab.h | 150 + libxsde/xsde/c/expat/utf8tab.h | 37 + libxsde/xsde/c/expat/xmlparse.c | 6260 +++++++++++++++++++ libxsde/xsde/c/expat/xmlrole.c | 1466 +++++ libxsde/xsde/c/expat/xmlrole.h | 114 + libxsde/xsde/c/expat/xmltok.c | 1671 +++++ libxsde/xsde/c/expat/xmltok.h | 316 + libxsde/xsde/c/expat/xmltok_impl.c | 1792 ++++++ libxsde/xsde/c/expat/xmltok_impl.h | 46 + libxsde/xsde/c/expat/xmltok_ns.c | 106 + libxsde/xsde/c/genx/COPYING | 39 + libxsde/xsde/c/genx/char-props.c | 380 ++ libxsde/xsde/c/genx/genx.c | 2118 +++++++ libxsde/xsde/c/genx/genx.h | 322 + libxsde/xsde/cxx/buffer.cxx | 145 + libxsde/xsde/cxx/buffer.hxx | 149 + libxsde/xsde/cxx/buffer.ixx | 213 + libxsde/xsde/cxx/compilers/vc-6/post.hxx | 6 + libxsde/xsde/cxx/compilers/vc-6/pre.hxx | 33 + libxsde/xsde/cxx/compilers/vc-7/post.hxx | 6 + libxsde/xsde/cxx/compilers/vc-7/pre.hxx | 37 + libxsde/xsde/cxx/compilers/vc-8/post.hxx | 6 + libxsde/xsde/cxx/compilers/vc-8/pre.hxx | 30 + libxsde/xsde/cxx/config.hxx | 27 + libxsde/xsde/cxx/date-time.hxx | 415 ++ libxsde/xsde/cxx/date-time.ixx | 725 +++ libxsde/xsde/cxx/errno.hxx | 23 + libxsde/xsde/cxx/errno.ixx | 44 + libxsde/xsde/cxx/exceptions.hxx | 21 + libxsde/xsde/cxx/hashmap.cxx | 210 + libxsde/xsde/cxx/hashmap.hxx | 156 + libxsde/xsde/cxx/hashmap.ixx | 177 + libxsde/xsde/cxx/hybrid/any-type.hxx | 26 + libxsde/xsde/cxx/hybrid/base.hxx | 370 ++ libxsde/xsde/cxx/hybrid/sequence.cxx | 31 + libxsde/xsde/cxx/hybrid/sequence.hxx | 921 +++ libxsde/xsde/cxx/hybrid/sequence.ixx | 881 +++ libxsde/xsde/cxx/hybrid/sequence.txx | 133 + libxsde/xsde/cxx/hybrid/xml-schema.hxx | 23 + libxsde/xsde/cxx/parser/context.cxx | 18 + libxsde/xsde/cxx/parser/context.hxx | 139 + libxsde/xsde/cxx/parser/context.ixx | 91 + libxsde/xsde/cxx/parser/elements.cxx | 201 + libxsde/xsde/cxx/parser/elements.hxx | 248 + libxsde/xsde/cxx/parser/elements.ixx | 221 + libxsde/xsde/cxx/parser/error.cxx | 20 + libxsde/xsde/cxx/parser/error.hxx | 135 + libxsde/xsde/cxx/parser/error.ixx | 143 + libxsde/xsde/cxx/parser/exceptions.cxx | 64 + libxsde/xsde/cxx/parser/exceptions.hxx | 103 + libxsde/xsde/cxx/parser/exceptions.ixx | 66 + libxsde/xsde/cxx/parser/expat/document.cxx | 1044 ++++ libxsde/xsde/cxx/parser/expat/document.hxx | 337 ++ libxsde/xsde/cxx/parser/expat/document.ixx | 53 + libxsde/xsde/cxx/parser/expat/xml-error.cxx | 25 + libxsde/xsde/cxx/parser/expat/xml-error.hxx | 28 + libxsde/xsde/cxx/parser/map.cxx | 35 + libxsde/xsde/cxx/parser/map.hxx | 87 + libxsde/xsde/cxx/parser/map.ixx | 41 + .../xsde/cxx/parser/non-validating/any-type.hxx | 43 + .../cxx/parser/non-validating/base64-binary.cxx | 241 + .../cxx/parser/non-validating/base64-binary.hxx | 55 + libxsde/xsde/cxx/parser/non-validating/boolean.cxx | 80 + libxsde/xsde/cxx/parser/non-validating/boolean.hxx | 49 + libxsde/xsde/cxx/parser/non-validating/byte.cxx | 48 + libxsde/xsde/cxx/parser/non-validating/byte.hxx | 48 + .../xsde/cxx/parser/non-validating/date-time.cxx | 154 + .../xsde/cxx/parser/non-validating/date-time.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/date.cxx | 126 + libxsde/xsde/cxx/parser/non-validating/date.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/decimal.cxx | 49 + libxsde/xsde/cxx/parser/non-validating/decimal.hxx | 46 + libxsde/xsde/cxx/parser/non-validating/double.cxx | 62 + libxsde/xsde/cxx/parser/non-validating/double.hxx | 46 + .../xsde/cxx/parser/non-validating/duration.cxx | 166 + .../xsde/cxx/parser/non-validating/duration.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/float.cxx | 76 + libxsde/xsde/cxx/parser/non-validating/float.hxx | 46 + libxsde/xsde/cxx/parser/non-validating/gday.cxx | 88 + libxsde/xsde/cxx/parser/non-validating/gday.hxx | 44 + .../xsde/cxx/parser/non-validating/gmonth-day.cxx | 100 + .../xsde/cxx/parser/non-validating/gmonth-day.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/gmonth.cxx | 88 + libxsde/xsde/cxx/parser/non-validating/gmonth.hxx | 44 + .../xsde/cxx/parser/non-validating/gyear-month.cxx | 121 + .../xsde/cxx/parser/non-validating/gyear-month.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/gyear.cxx | 115 + libxsde/xsde/cxx/parser/non-validating/gyear.hxx | 44 + .../xsde/cxx/parser/non-validating/hex-binary.cxx | 159 + .../xsde/cxx/parser/non-validating/hex-binary.hxx | 55 + libxsde/xsde/cxx/parser/non-validating/id-stl.cxx | 50 + libxsde/xsde/cxx/parser/non-validating/id-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/id.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/id.hxx | 44 + .../xsde/cxx/parser/non-validating/idref-stl.cxx | 49 + .../xsde/cxx/parser/non-validating/idref-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/idref.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/idref.hxx | 44 + .../xsde/cxx/parser/non-validating/idrefs-stl.cxx | 94 + .../xsde/cxx/parser/non-validating/idrefs-stl.hxx | 54 + libxsde/xsde/cxx/parser/non-validating/idrefs.cxx | 133 + libxsde/xsde/cxx/parser/non-validating/idrefs.hxx | 54 + libxsde/xsde/cxx/parser/non-validating/int.cxx | 50 + libxsde/xsde/cxx/parser/non-validating/int.hxx | 48 + libxsde/xsde/cxx/parser/non-validating/integer.cxx | 50 + libxsde/xsde/cxx/parser/non-validating/integer.hxx | 49 + .../cxx/parser/non-validating/language-stl.cxx | 49 + .../cxx/parser/non-validating/language-stl.hxx | 44 + .../xsde/cxx/parser/non-validating/language.cxx | 67 + .../xsde/cxx/parser/non-validating/language.hxx | 44 + .../xsde/cxx/parser/non-validating/long-long.cxx | 50 + .../xsde/cxx/parser/non-validating/long-long.hxx | 48 + libxsde/xsde/cxx/parser/non-validating/long.cxx | 50 + libxsde/xsde/cxx/parser/non-validating/long.hxx | 48 + .../xsde/cxx/parser/non-validating/name-stl.cxx | 49 + .../xsde/cxx/parser/non-validating/name-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/name.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/name.hxx | 44 + .../xsde/cxx/parser/non-validating/ncname-stl.cxx | 50 + .../xsde/cxx/parser/non-validating/ncname-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/ncname.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/ncname.hxx | 44 + .../cxx/parser/non-validating/negative-integer.cxx | 48 + .../cxx/parser/non-validating/negative-integer.hxx | 49 + .../xsde/cxx/parser/non-validating/nmtoken-stl.cxx | 49 + .../xsde/cxx/parser/non-validating/nmtoken-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx | 44 + .../cxx/parser/non-validating/nmtokens-stl.cxx | 90 + .../cxx/parser/non-validating/nmtokens-stl.hxx | 54 + .../xsde/cxx/parser/non-validating/nmtokens.cxx | 129 + .../xsde/cxx/parser/non-validating/nmtokens.hxx | 54 + .../parser/non-validating/non-negative-integer.cxx | 44 + .../parser/non-validating/non-negative-integer.hxx | 50 + .../parser/non-validating/non-positive-integer.cxx | 48 + .../parser/non-validating/non-positive-integer.hxx | 50 + .../non-validating/normalized-string-stl.cxx | 48 + .../non-validating/normalized-string-stl.hxx | 44 + .../parser/non-validating/normalized-string.cxx | 60 + .../parser/non-validating/normalized-string.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/number.cxx | 127 + libxsde/xsde/cxx/parser/non-validating/number.hxx | 37 + libxsde/xsde/cxx/parser/non-validating/parser.cxx | 473 ++ libxsde/xsde/cxx/parser/non-validating/parser.hxx | 196 + libxsde/xsde/cxx/parser/non-validating/parser.ixx | 77 + .../cxx/parser/non-validating/positive-integer.cxx | 44 + .../cxx/parser/non-validating/positive-integer.hxx | 49 + .../xsde/cxx/parser/non-validating/qname-stl.cxx | 58 + .../xsde/cxx/parser/non-validating/qname-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/qname.cxx | 153 + libxsde/xsde/cxx/parser/non-validating/qname.hxx | 55 + libxsde/xsde/cxx/parser/non-validating/short.cxx | 48 + libxsde/xsde/cxx/parser/non-validating/short.hxx | 48 + .../xsde/cxx/parser/non-validating/string-stl.cxx | 38 + .../xsde/cxx/parser/non-validating/string-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/string.cxx | 48 + libxsde/xsde/cxx/parser/non-validating/string.hxx | 44 + .../xsde/cxx/parser/non-validating/time-zone.cxx | 53 + .../xsde/cxx/parser/non-validating/time-zone.hxx | 32 + libxsde/xsde/cxx/parser/non-validating/time.cxx | 118 + libxsde/xsde/cxx/parser/non-validating/time.hxx | 44 + .../xsde/cxx/parser/non-validating/token-stl.cxx | 73 + .../xsde/cxx/parser/non-validating/token-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/token.cxx | 94 + libxsde/xsde/cxx/parser/non-validating/token.hxx | 44 + .../cxx/parser/non-validating/unsigned-byte.cxx | 44 + .../cxx/parser/non-validating/unsigned-byte.hxx | 48 + .../cxx/parser/non-validating/unsigned-int.cxx | 44 + .../cxx/parser/non-validating/unsigned-int.hxx | 48 + .../parser/non-validating/unsigned-long-long.cxx | 44 + .../parser/non-validating/unsigned-long-long.hxx | 49 + .../cxx/parser/non-validating/unsigned-long.cxx | 44 + .../cxx/parser/non-validating/unsigned-long.hxx | 49 + .../cxx/parser/non-validating/unsigned-short.cxx | 44 + .../cxx/parser/non-validating/unsigned-short.hxx | 48 + libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx | 49 + libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx | 44 + libxsde/xsde/cxx/parser/non-validating/uri.cxx | 67 + libxsde/xsde/cxx/parser/non-validating/uri.hxx | 44 + .../cxx/parser/non-validating/xml-schema-pimpl.hxx | 82 + .../cxx/parser/non-validating/xml-schema-pskel.cxx | 612 ++ .../cxx/parser/non-validating/xml-schema-pskel.hxx | 1388 +++++ .../cxx/parser/non-validating/xml-schema-pskel.ixx | 704 +++ libxsde/xsde/cxx/parser/state.cxx | 37 + libxsde/xsde/cxx/parser/state.hxx | 89 + libxsde/xsde/cxx/parser/state.ixx | 102 + libxsde/xsde/cxx/parser/substitution-map-load.hxx | 31 + libxsde/xsde/cxx/parser/substitution-map.cxx | 236 + libxsde/xsde/cxx/parser/substitution-map.hxx | 115 + libxsde/xsde/cxx/parser/substitution-map.ixx | 71 + libxsde/xsde/cxx/parser/validating/any-type.hxx | 43 + .../xsde/cxx/parser/validating/base64-binary.cxx | 281 + .../xsde/cxx/parser/validating/base64-binary.hxx | 58 + libxsde/xsde/cxx/parser/validating/boolean.cxx | 93 + libxsde/xsde/cxx/parser/validating/boolean.hxx | 54 + libxsde/xsde/cxx/parser/validating/byte.cxx | 71 + libxsde/xsde/cxx/parser/validating/byte.hxx | 52 + libxsde/xsde/cxx/parser/validating/date-time.cxx | 259 + libxsde/xsde/cxx/parser/validating/date-time.hxx | 53 + libxsde/xsde/cxx/parser/validating/date.cxx | 182 + libxsde/xsde/cxx/parser/validating/date.hxx | 51 + libxsde/xsde/cxx/parser/validating/decimal.cxx | 74 + libxsde/xsde/cxx/parser/validating/decimal.hxx | 50 + libxsde/xsde/cxx/parser/validating/double.cxx | 99 + libxsde/xsde/cxx/parser/validating/double.hxx | 50 + libxsde/xsde/cxx/parser/validating/duration.cxx | 265 + libxsde/xsde/cxx/parser/validating/duration.hxx | 51 + libxsde/xsde/cxx/parser/validating/float.cxx | 118 + libxsde/xsde/cxx/parser/validating/float.hxx | 50 + libxsde/xsde/cxx/parser/validating/gday.cxx | 112 + libxsde/xsde/cxx/parser/validating/gday.hxx | 50 + libxsde/xsde/cxx/parser/validating/gmonth-day.cxx | 137 + libxsde/xsde/cxx/parser/validating/gmonth-day.hxx | 50 + libxsde/xsde/cxx/parser/validating/gmonth.cxx | 112 + libxsde/xsde/cxx/parser/validating/gmonth.hxx | 50 + libxsde/xsde/cxx/parser/validating/gyear-month.cxx | 161 + libxsde/xsde/cxx/parser/validating/gyear-month.hxx | 51 + libxsde/xsde/cxx/parser/validating/gyear.cxx | 138 + libxsde/xsde/cxx/parser/validating/gyear.hxx | 50 + libxsde/xsde/cxx/parser/validating/hex-binary.cxx | 172 + libxsde/xsde/cxx/parser/validating/hex-binary.hxx | 58 + libxsde/xsde/cxx/parser/validating/id-stl.cxx | 60 + libxsde/xsde/cxx/parser/validating/id-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/id.cxx | 80 + libxsde/xsde/cxx/parser/validating/id.hxx | 47 + libxsde/xsde/cxx/parser/validating/idref-stl.cxx | 60 + libxsde/xsde/cxx/parser/validating/idref-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/idref.cxx | 79 + libxsde/xsde/cxx/parser/validating/idref.hxx | 47 + libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx | 133 + libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx | 57 + libxsde/xsde/cxx/parser/validating/idrefs.cxx | 136 + libxsde/xsde/cxx/parser/validating/idrefs.hxx | 57 + .../cxx/parser/validating/inheritance-map-load.hxx | 35 + .../xsde/cxx/parser/validating/inheritance-map.cxx | 111 + .../xsde/cxx/parser/validating/inheritance-map.hxx | 63 + .../xsde/cxx/parser/validating/inheritance-map.ixx | 34 + libxsde/xsde/cxx/parser/validating/int.cxx | 75 + libxsde/xsde/cxx/parser/validating/int.hxx | 52 + libxsde/xsde/cxx/parser/validating/integer.cxx | 75 + libxsde/xsde/cxx/parser/validating/integer.hxx | 53 + .../xsde/cxx/parser/validating/language-stl.cxx | 95 + .../xsde/cxx/parser/validating/language-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/language.cxx | 114 + libxsde/xsde/cxx/parser/validating/language.hxx | 47 + libxsde/xsde/cxx/parser/validating/long-long.cxx | 75 + libxsde/xsde/cxx/parser/validating/long-long.hxx | 52 + libxsde/xsde/cxx/parser/validating/long.cxx | 75 + libxsde/xsde/cxx/parser/validating/long.hxx | 52 + libxsde/xsde/cxx/parser/validating/name-stl.cxx | 86 + libxsde/xsde/cxx/parser/validating/name-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/name.cxx | 105 + libxsde/xsde/cxx/parser/validating/name.hxx | 47 + libxsde/xsde/cxx/parser/validating/ncname-stl.cxx | 60 + libxsde/xsde/cxx/parser/validating/ncname-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/ncname.cxx | 79 + libxsde/xsde/cxx/parser/validating/ncname.hxx | 47 + .../cxx/parser/validating/negative-integer.cxx | 71 + .../cxx/parser/validating/negative-integer.hxx | 53 + libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx | 79 + libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx | 47 + libxsde/xsde/cxx/parser/validating/nmtoken.cxx | 98 + libxsde/xsde/cxx/parser/validating/nmtoken.hxx | 47 + .../xsde/cxx/parser/validating/nmtokens-stl.cxx | 127 + .../xsde/cxx/parser/validating/nmtokens-stl.hxx | 57 + libxsde/xsde/cxx/parser/validating/nmtokens.cxx | 132 + libxsde/xsde/cxx/parser/validating/nmtokens.hxx | 57 + .../cxx/parser/validating/non-negative-integer.cxx | 66 + .../cxx/parser/validating/non-negative-integer.hxx | 54 + .../cxx/parser/validating/non-positive-integer.cxx | 71 + .../cxx/parser/validating/non-positive-integer.hxx | 54 + .../parser/validating/normalized-string-stl.cxx | 48 + .../parser/validating/normalized-string-stl.hxx | 44 + .../cxx/parser/validating/normalized-string.cxx | 60 + .../cxx/parser/validating/normalized-string.hxx | 44 + libxsde/xsde/cxx/parser/validating/number.cxx | 133 + libxsde/xsde/cxx/parser/validating/number.hxx | 37 + libxsde/xsde/cxx/parser/validating/parser.cxx | 633 ++ libxsde/xsde/cxx/parser/validating/parser.hxx | 304 + libxsde/xsde/cxx/parser/validating/parser.ixx | 121 + .../cxx/parser/validating/positive-integer.cxx | 64 + .../cxx/parser/validating/positive-integer.hxx | 53 + libxsde/xsde/cxx/parser/validating/qname-stl.cxx | 79 + libxsde/xsde/cxx/parser/validating/qname-stl.hxx | 49 + libxsde/xsde/cxx/parser/validating/qname.cxx | 180 + libxsde/xsde/cxx/parser/validating/qname.hxx | 58 + libxsde/xsde/cxx/parser/validating/short.cxx | 70 + libxsde/xsde/cxx/parser/validating/short.hxx | 52 + libxsde/xsde/cxx/parser/validating/string-stl.cxx | 38 + libxsde/xsde/cxx/parser/validating/string-stl.hxx | 44 + libxsde/xsde/cxx/parser/validating/string.cxx | 48 + libxsde/xsde/cxx/parser/validating/string.hxx | 44 + libxsde/xsde/cxx/parser/validating/time-zone.cxx | 79 + libxsde/xsde/cxx/parser/validating/time-zone.hxx | 32 + libxsde/xsde/cxx/parser/validating/time.cxx | 181 + libxsde/xsde/cxx/parser/validating/time.hxx | 51 + libxsde/xsde/cxx/parser/validating/token-stl.cxx | 73 + libxsde/xsde/cxx/parser/validating/token-stl.hxx | 44 + libxsde/xsde/cxx/parser/validating/token.cxx | 94 + libxsde/xsde/cxx/parser/validating/token.hxx | 44 + .../xsde/cxx/parser/validating/unsigned-byte.cxx | 66 + .../xsde/cxx/parser/validating/unsigned-byte.hxx | 52 + .../xsde/cxx/parser/validating/unsigned-int.cxx | 66 + .../xsde/cxx/parser/validating/unsigned-int.hxx | 52 + .../cxx/parser/validating/unsigned-long-long.cxx | 64 + .../cxx/parser/validating/unsigned-long-long.hxx | 53 + .../xsde/cxx/parser/validating/unsigned-long.cxx | 64 + .../xsde/cxx/parser/validating/unsigned-long.hxx | 53 + .../xsde/cxx/parser/validating/unsigned-short.cxx | 66 + .../xsde/cxx/parser/validating/unsigned-short.hxx | 52 + libxsde/xsde/cxx/parser/validating/uri-stl.cxx | 53 + libxsde/xsde/cxx/parser/validating/uri-stl.hxx | 44 + libxsde/xsde/cxx/parser/validating/uri.cxx | 71 + libxsde/xsde/cxx/parser/validating/uri.hxx | 44 + .../cxx/parser/validating/xml-schema-pimpl.hxx | 82 + .../cxx/parser/validating/xml-schema-pskel.cxx | 617 ++ .../cxx/parser/validating/xml-schema-pskel.hxx | 1385 +++++ .../cxx/parser/validating/xml-schema-pskel.ixx | 704 +++ libxsde/xsde/cxx/parser/xml-schema.hxx | 20 + libxsde/xsde/cxx/post.hxx | 14 + libxsde/xsde/cxx/pre.hxx | 15 + libxsde/xsde/cxx/qname-stl.hxx | 59 + libxsde/xsde/cxx/qname-stl.ixx | 82 + libxsde/xsde/cxx/qname.cxx | 71 + libxsde/xsde/cxx/qname.hxx | 99 + libxsde/xsde/cxx/qname.ixx | 125 + libxsde/xsde/cxx/ro-string.cxx | 116 + libxsde/xsde/cxx/ro-string.hxx | 281 + libxsde/xsde/cxx/ro-string.ixx | 409 ++ libxsde/xsde/cxx/schema-error.cxx | 69 + libxsde/xsde/cxx/schema-error.hxx | 84 + libxsde/xsde/cxx/schema-error.ixx | 16 + libxsde/xsde/cxx/sequence-base.cxx | 135 + libxsde/xsde/cxx/sequence-base.hxx | 83 + libxsde/xsde/cxx/sequence-base.ixx | 57 + libxsde/xsde/cxx/serializer/context.cxx | 107 + libxsde/xsde/cxx/serializer/context.hxx | 261 + libxsde/xsde/cxx/serializer/context.ixx | 449 ++ libxsde/xsde/cxx/serializer/elements.cxx | 122 + libxsde/xsde/cxx/serializer/elements.hxx | 302 + libxsde/xsde/cxx/serializer/elements.ixx | 569 ++ libxsde/xsde/cxx/serializer/error.cxx | 20 + libxsde/xsde/cxx/serializer/error.hxx | 121 + libxsde/xsde/cxx/serializer/error.ixx | 128 + libxsde/xsde/cxx/serializer/exceptions.cxx | 62 + libxsde/xsde/cxx/serializer/exceptions.hxx | 91 + libxsde/xsde/cxx/serializer/exceptions.ixx | 44 + libxsde/xsde/cxx/serializer/genx/document.cxx | 822 +++ libxsde/xsde/cxx/serializer/genx/document.hxx | 280 + libxsde/xsde/cxx/serializer/genx/document.ixx | 84 + libxsde/xsde/cxx/serializer/genx/xml-error.cxx | 48 + libxsde/xsde/cxx/serializer/genx/xml-error.hxx | 28 + libxsde/xsde/cxx/serializer/map.cxx | 35 + libxsde/xsde/cxx/serializer/map.hxx | 96 + libxsde/xsde/cxx/serializer/map.ixx | 51 + .../cxx/serializer/non-validating/any-type.hxx | 43 + .../serializer/non-validating/base64-binary.cxx | 166 + .../serializer/non-validating/base64-binary.hxx | 47 + .../serializer/non-validating/base64-binary.ixx | 22 + .../xsde/cxx/serializer/non-validating/boolean.cxx | 30 + .../xsde/cxx/serializer/non-validating/boolean.hxx | 39 + .../xsde/cxx/serializer/non-validating/byte.cxx | 43 + .../xsde/cxx/serializer/non-validating/byte.hxx | 41 + .../cxx/serializer/non-validating/date-time.cxx | 78 + .../cxx/serializer/non-validating/date-time.hxx | 43 + .../cxx/serializer/non-validating/date-time.ixx | 22 + .../xsde/cxx/serializer/non-validating/date.cxx | 59 + .../xsde/cxx/serializer/non-validating/date.hxx | 43 + .../xsde/cxx/serializer/non-validating/date.ixx | 22 + .../xsde/cxx/serializer/non-validating/decimal.cxx | 54 + .../xsde/cxx/serializer/non-validating/decimal.hxx | 50 + .../xsde/cxx/serializer/non-validating/decimal.ixx | 22 + .../xsde/cxx/serializer/non-validating/double.cxx | 103 + .../xsde/cxx/serializer/non-validating/double.hxx | 60 + .../xsde/cxx/serializer/non-validating/double.ixx | 22 + .../cxx/serializer/non-validating/duration.cxx | 171 + .../cxx/serializer/non-validating/duration.hxx | 43 + .../cxx/serializer/non-validating/duration.ixx | 22 + .../xsde/cxx/serializer/non-validating/float.cxx | 103 + .../xsde/cxx/serializer/non-validating/float.hxx | 60 + .../xsde/cxx/serializer/non-validating/float.ixx | 22 + .../xsde/cxx/serializer/non-validating/gday.cxx | 57 + .../xsde/cxx/serializer/non-validating/gday.hxx | 43 + .../xsde/cxx/serializer/non-validating/gday.ixx | 22 + .../cxx/serializer/non-validating/gmonth-day.cxx | 59 + .../cxx/serializer/non-validating/gmonth-day.hxx | 43 + .../cxx/serializer/non-validating/gmonth-day.ixx | 22 + .../xsde/cxx/serializer/non-validating/gmonth.cxx | 57 + .../xsde/cxx/serializer/non-validating/gmonth.hxx | 43 + .../xsde/cxx/serializer/non-validating/gmonth.ixx | 22 + .../cxx/serializer/non-validating/gyear-month.cxx | 59 + .../cxx/serializer/non-validating/gyear-month.hxx | 43 + .../cxx/serializer/non-validating/gyear-month.ixx | 22 + .../xsde/cxx/serializer/non-validating/gyear.cxx | 54 + .../xsde/cxx/serializer/non-validating/gyear.hxx | 43 + .../xsde/cxx/serializer/non-validating/gyear.ixx | 22 + .../cxx/serializer/non-validating/hex-binary.cxx | 70 + .../cxx/serializer/non-validating/hex-binary.hxx | 47 + .../cxx/serializer/non-validating/hex-binary.ixx | 22 + .../xsde/cxx/serializer/non-validating/id-stl.cxx | 35 + .../xsde/cxx/serializer/non-validating/id-stl.hxx | 41 + libxsde/xsde/cxx/serializer/non-validating/id.cxx | 43 + libxsde/xsde/cxx/serializer/non-validating/id.hxx | 47 + libxsde/xsde/cxx/serializer/non-validating/id.ixx | 22 + .../cxx/serializer/non-validating/idref-stl.cxx | 35 + .../cxx/serializer/non-validating/idref-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/idref.cxx | 43 + .../xsde/cxx/serializer/non-validating/idref.hxx | 47 + .../xsde/cxx/serializer/non-validating/idref.ixx | 22 + .../cxx/serializer/non-validating/idrefs-stl.cxx | 108 + .../cxx/serializer/non-validating/idrefs-stl.hxx | 52 + .../cxx/serializer/non-validating/idrefs-stl.ixx | 22 + .../xsde/cxx/serializer/non-validating/idrefs.cxx | 109 + .../xsde/cxx/serializer/non-validating/idrefs.hxx | 52 + .../xsde/cxx/serializer/non-validating/idrefs.ixx | 22 + libxsde/xsde/cxx/serializer/non-validating/int.cxx | 43 + libxsde/xsde/cxx/serializer/non-validating/int.hxx | 39 + .../xsde/cxx/serializer/non-validating/integer.cxx | 43 + .../xsde/cxx/serializer/non-validating/integer.hxx | 41 + .../cxx/serializer/non-validating/language-stl.cxx | 35 + .../cxx/serializer/non-validating/language-stl.hxx | 41 + .../cxx/serializer/non-validating/language.cxx | 43 + .../cxx/serializer/non-validating/language.hxx | 47 + .../cxx/serializer/non-validating/language.ixx | 22 + .../cxx/serializer/non-validating/long-long.cxx | 43 + .../cxx/serializer/non-validating/long-long.hxx | 41 + .../xsde/cxx/serializer/non-validating/long.cxx | 43 + .../xsde/cxx/serializer/non-validating/long.hxx | 41 + .../cxx/serializer/non-validating/name-stl.cxx | 35 + .../cxx/serializer/non-validating/name-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/name.cxx | 43 + .../xsde/cxx/serializer/non-validating/name.hxx | 47 + .../xsde/cxx/serializer/non-validating/name.ixx | 22 + .../cxx/serializer/non-validating/ncname-stl.cxx | 35 + .../cxx/serializer/non-validating/ncname-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/ncname.cxx | 43 + .../xsde/cxx/serializer/non-validating/ncname.hxx | 47 + .../xsde/cxx/serializer/non-validating/ncname.ixx | 22 + .../serializer/non-validating/negative-integer.cxx | 43 + .../serializer/non-validating/negative-integer.hxx | 41 + .../cxx/serializer/non-validating/nmtoken-stl.cxx | 35 + .../cxx/serializer/non-validating/nmtoken-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/nmtoken.cxx | 43 + .../xsde/cxx/serializer/non-validating/nmtoken.hxx | 47 + .../xsde/cxx/serializer/non-validating/nmtoken.ixx | 22 + .../cxx/serializer/non-validating/nmtokens-stl.cxx | 108 + .../cxx/serializer/non-validating/nmtokens-stl.hxx | 52 + .../cxx/serializer/non-validating/nmtokens-stl.ixx | 22 + .../cxx/serializer/non-validating/nmtokens.cxx | 109 + .../cxx/serializer/non-validating/nmtokens.hxx | 52 + .../cxx/serializer/non-validating/nmtokens.ixx | 22 + .../non-validating/non-negative-integer.cxx | 43 + .../non-validating/non-negative-integer.hxx | 41 + .../non-validating/non-positive-integer.cxx | 43 + .../non-validating/non-positive-integer.hxx | 41 + .../non-validating/normalized-string-stl.cxx | 36 + .../non-validating/normalized-string-stl.hxx | 41 + .../non-validating/normalized-string.cxx | 44 + .../non-validating/normalized-string.hxx | 47 + .../non-validating/normalized-string.ixx | 22 + .../serializer/non-validating/positive-integer.cxx | 43 + .../serializer/non-validating/positive-integer.hxx | 41 + .../cxx/serializer/non-validating/qname-stl.cxx | 50 + .../cxx/serializer/non-validating/qname-stl.hxx | 43 + .../cxx/serializer/non-validating/qname-stl.ixx | 22 + .../xsde/cxx/serializer/non-validating/qname.cxx | 62 + .../xsde/cxx/serializer/non-validating/qname.hxx | 47 + .../xsde/cxx/serializer/non-validating/qname.ixx | 22 + .../cxx/serializer/non-validating/serializer.cxx | 29 + .../cxx/serializer/non-validating/serializer.hxx | 58 + .../cxx/serializer/non-validating/serializer.ixx | 61 + .../xsde/cxx/serializer/non-validating/short.cxx | 43 + .../xsde/cxx/serializer/non-validating/short.hxx | 41 + .../cxx/serializer/non-validating/string-stl.cxx | 35 + .../cxx/serializer/non-validating/string-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/string.cxx | 43 + .../xsde/cxx/serializer/non-validating/string.hxx | 47 + .../xsde/cxx/serializer/non-validating/string.ixx | 22 + .../cxx/serializer/non-validating/time-zone.cxx | 65 + .../cxx/serializer/non-validating/time-zone.hxx | 33 + .../xsde/cxx/serializer/non-validating/time.cxx | 73 + .../xsde/cxx/serializer/non-validating/time.hxx | 43 + .../xsde/cxx/serializer/non-validating/time.ixx | 22 + .../cxx/serializer/non-validating/token-stl.cxx | 35 + .../cxx/serializer/non-validating/token-stl.hxx | 41 + .../xsde/cxx/serializer/non-validating/token.cxx | 43 + .../xsde/cxx/serializer/non-validating/token.hxx | 47 + .../xsde/cxx/serializer/non-validating/token.ixx | 22 + .../serializer/non-validating/unsigned-byte.cxx | 43 + .../serializer/non-validating/unsigned-byte.hxx | 41 + .../cxx/serializer/non-validating/unsigned-int.cxx | 43 + .../cxx/serializer/non-validating/unsigned-int.hxx | 41 + .../non-validating/unsigned-long-long.cxx | 43 + .../non-validating/unsigned-long-long.hxx | 41 + .../serializer/non-validating/unsigned-long.cxx | 43 + .../serializer/non-validating/unsigned-long.hxx | 41 + .../serializer/non-validating/unsigned-short.cxx | 43 + .../serializer/non-validating/unsigned-short.hxx | 41 + .../xsde/cxx/serializer/non-validating/uri-stl.cxx | 35 + .../xsde/cxx/serializer/non-validating/uri-stl.hxx | 41 + libxsde/xsde/cxx/serializer/non-validating/uri.cxx | 43 + libxsde/xsde/cxx/serializer/non-validating/uri.hxx | 47 + libxsde/xsde/cxx/serializer/non-validating/uri.ixx | 22 + .../serializer/non-validating/xml-schema-simpl.hxx | 82 + .../serializer/non-validating/xml-schema-sskel.cxx | 560 ++ .../serializer/non-validating/xml-schema-sskel.hxx | 1382 +++++ .../serializer/non-validating/xml-schema-sskel.ixx | 704 +++ .../xsde/cxx/serializer/substitution-map-load.hxx | 40 + libxsde/xsde/cxx/serializer/substitution-map.cxx | 248 + libxsde/xsde/cxx/serializer/substitution-map.hxx | 88 + libxsde/xsde/cxx/serializer/substitution-map.ixx | 33 + .../xsde/cxx/serializer/validating/any-type.hxx | 43 + .../cxx/serializer/validating/base64-binary.cxx | 166 + .../cxx/serializer/validating/base64-binary.hxx | 47 + .../cxx/serializer/validating/base64-binary.ixx | 22 + libxsde/xsde/cxx/serializer/validating/boolean.cxx | 30 + libxsde/xsde/cxx/serializer/validating/boolean.hxx | 39 + libxsde/xsde/cxx/serializer/validating/byte.cxx | 45 + libxsde/xsde/cxx/serializer/validating/byte.hxx | 41 + .../xsde/cxx/serializer/validating/date-time.cxx | 87 + .../xsde/cxx/serializer/validating/date-time.hxx | 43 + .../xsde/cxx/serializer/validating/date-time.ixx | 22 + libxsde/xsde/cxx/serializer/validating/date.cxx | 71 + libxsde/xsde/cxx/serializer/validating/date.hxx | 43 + libxsde/xsde/cxx/serializer/validating/date.ixx | 22 + libxsde/xsde/cxx/serializer/validating/decimal.cxx | 66 + libxsde/xsde/cxx/serializer/validating/decimal.hxx | 50 + libxsde/xsde/cxx/serializer/validating/decimal.ixx | 22 + libxsde/xsde/cxx/serializer/validating/double.cxx | 105 + libxsde/xsde/cxx/serializer/validating/double.hxx | 60 + libxsde/xsde/cxx/serializer/validating/double.ixx | 22 + .../xsde/cxx/serializer/validating/duration.cxx | 195 + .../xsde/cxx/serializer/validating/duration.hxx | 43 + .../xsde/cxx/serializer/validating/duration.ixx | 22 + libxsde/xsde/cxx/serializer/validating/float.cxx | 105 + libxsde/xsde/cxx/serializer/validating/float.hxx | 60 + libxsde/xsde/cxx/serializer/validating/float.ixx | 22 + libxsde/xsde/cxx/serializer/validating/gday.cxx | 67 + libxsde/xsde/cxx/serializer/validating/gday.hxx | 43 + libxsde/xsde/cxx/serializer/validating/gday.ixx | 22 + .../xsde/cxx/serializer/validating/gmonth-day.cxx | 68 + .../xsde/cxx/serializer/validating/gmonth-day.hxx | 43 + .../xsde/cxx/serializer/validating/gmonth-day.ixx | 22 + libxsde/xsde/cxx/serializer/validating/gmonth.cxx | 67 + libxsde/xsde/cxx/serializer/validating/gmonth.hxx | 43 + libxsde/xsde/cxx/serializer/validating/gmonth.ixx | 22 + .../xsde/cxx/serializer/validating/gyear-month.cxx | 68 + .../xsde/cxx/serializer/validating/gyear-month.hxx | 43 + .../xsde/cxx/serializer/validating/gyear-month.ixx | 22 + libxsde/xsde/cxx/serializer/validating/gyear.cxx | 67 + libxsde/xsde/cxx/serializer/validating/gyear.hxx | 43 + libxsde/xsde/cxx/serializer/validating/gyear.ixx | 22 + .../xsde/cxx/serializer/validating/hex-binary.cxx | 70 + .../xsde/cxx/serializer/validating/hex-binary.hxx | 47 + .../xsde/cxx/serializer/validating/hex-binary.ixx | 22 + libxsde/xsde/cxx/serializer/validating/id-stl.cxx | 38 + libxsde/xsde/cxx/serializer/validating/id-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/id.cxx | 52 + libxsde/xsde/cxx/serializer/validating/id.hxx | 47 + libxsde/xsde/cxx/serializer/validating/id.ixx | 22 + .../xsde/cxx/serializer/validating/idref-stl.cxx | 38 + .../xsde/cxx/serializer/validating/idref-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/idref.cxx | 52 + libxsde/xsde/cxx/serializer/validating/idref.hxx | 47 + libxsde/xsde/cxx/serializer/validating/idref.ixx | 22 + .../xsde/cxx/serializer/validating/idrefs-stl.cxx | 109 + .../xsde/cxx/serializer/validating/idrefs-stl.hxx | 52 + .../xsde/cxx/serializer/validating/idrefs-stl.ixx | 22 + libxsde/xsde/cxx/serializer/validating/idrefs.cxx | 110 + libxsde/xsde/cxx/serializer/validating/idrefs.hxx | 52 + libxsde/xsde/cxx/serializer/validating/idrefs.ixx | 22 + .../serializer/validating/inheritance-map-load.hxx | 35 + .../cxx/serializer/validating/inheritance-map.cxx | 111 + .../cxx/serializer/validating/inheritance-map.hxx | 63 + .../cxx/serializer/validating/inheritance-map.ixx | 34 + libxsde/xsde/cxx/serializer/validating/int.cxx | 45 + libxsde/xsde/cxx/serializer/validating/int.hxx | 39 + libxsde/xsde/cxx/serializer/validating/integer.cxx | 45 + libxsde/xsde/cxx/serializer/validating/integer.hxx | 41 + .../cxx/serializer/validating/language-stl.cxx | 73 + .../cxx/serializer/validating/language-stl.hxx | 41 + .../xsde/cxx/serializer/validating/language.cxx | 81 + .../xsde/cxx/serializer/validating/language.hxx | 47 + .../xsde/cxx/serializer/validating/language.ixx | 22 + .../xsde/cxx/serializer/validating/long-long.cxx | 45 + .../xsde/cxx/serializer/validating/long-long.hxx | 41 + libxsde/xsde/cxx/serializer/validating/long.cxx | 45 + libxsde/xsde/cxx/serializer/validating/long.hxx | 41 + .../xsde/cxx/serializer/validating/name-stl.cxx | 62 + .../xsde/cxx/serializer/validating/name-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/name.cxx | 70 + libxsde/xsde/cxx/serializer/validating/name.hxx | 47 + libxsde/xsde/cxx/serializer/validating/name.ixx | 22 + .../xsde/cxx/serializer/validating/ncname-stl.cxx | 38 + .../xsde/cxx/serializer/validating/ncname-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/ncname.cxx | 52 + libxsde/xsde/cxx/serializer/validating/ncname.hxx | 47 + libxsde/xsde/cxx/serializer/validating/ncname.ixx | 22 + .../cxx/serializer/validating/negative-integer.cxx | 51 + .../cxx/serializer/validating/negative-integer.hxx | 41 + .../xsde/cxx/serializer/validating/nmtoken-stl.cxx | 53 + .../xsde/cxx/serializer/validating/nmtoken-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/nmtoken.cxx | 61 + libxsde/xsde/cxx/serializer/validating/nmtoken.hxx | 47 + libxsde/xsde/cxx/serializer/validating/nmtoken.ixx | 22 + .../cxx/serializer/validating/nmtokens-stl.cxx | 109 + .../cxx/serializer/validating/nmtokens-stl.hxx | 52 + .../cxx/serializer/validating/nmtokens-stl.ixx | 22 + .../xsde/cxx/serializer/validating/nmtokens.cxx | 110 + .../xsde/cxx/serializer/validating/nmtokens.hxx | 52 + .../xsde/cxx/serializer/validating/nmtokens.ixx | 22 + .../serializer/validating/non-negative-integer.cxx | 45 + .../serializer/validating/non-negative-integer.hxx | 41 + .../serializer/validating/non-positive-integer.cxx | 51 + .../serializer/validating/non-positive-integer.hxx | 41 + .../validating/normalized-string-stl.cxx | 47 + .../validating/normalized-string-stl.hxx | 41 + .../serializer/validating/normalized-string.cxx | 55 + .../serializer/validating/normalized-string.hxx | 47 + .../serializer/validating/normalized-string.ixx | 22 + .../cxx/serializer/validating/positive-integer.cxx | 51 + .../cxx/serializer/validating/positive-integer.hxx | 41 + .../xsde/cxx/serializer/validating/qname-stl.cxx | 68 + .../xsde/cxx/serializer/validating/qname-stl.hxx | 43 + .../xsde/cxx/serializer/validating/qname-stl.ixx | 22 + libxsde/xsde/cxx/serializer/validating/qname.cxx | 79 + libxsde/xsde/cxx/serializer/validating/qname.hxx | 47 + libxsde/xsde/cxx/serializer/validating/qname.ixx | 22 + .../xsde/cxx/serializer/validating/serializer.cxx | 29 + .../xsde/cxx/serializer/validating/serializer.hxx | 58 + .../xsde/cxx/serializer/validating/serializer.ixx | 61 + libxsde/xsde/cxx/serializer/validating/short.cxx | 45 + libxsde/xsde/cxx/serializer/validating/short.hxx | 41 + .../xsde/cxx/serializer/validating/string-stl.cxx | 35 + .../xsde/cxx/serializer/validating/string-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/string.cxx | 43 + libxsde/xsde/cxx/serializer/validating/string.hxx | 47 + libxsde/xsde/cxx/serializer/validating/string.ixx | 22 + .../xsde/cxx/serializer/validating/time-zone.cxx | 65 + .../xsde/cxx/serializer/validating/time-zone.hxx | 40 + .../xsde/cxx/serializer/validating/time-zone.ixx | 32 + libxsde/xsde/cxx/serializer/validating/time.cxx | 79 + libxsde/xsde/cxx/serializer/validating/time.hxx | 43 + libxsde/xsde/cxx/serializer/validating/time.ixx | 22 + .../xsde/cxx/serializer/validating/token-stl.cxx | 58 + .../xsde/cxx/serializer/validating/token-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/token.cxx | 66 + libxsde/xsde/cxx/serializer/validating/token.hxx | 47 + libxsde/xsde/cxx/serializer/validating/token.ixx | 22 + .../cxx/serializer/validating/unsigned-byte.cxx | 45 + .../cxx/serializer/validating/unsigned-byte.hxx | 41 + .../cxx/serializer/validating/unsigned-int.cxx | 45 + .../cxx/serializer/validating/unsigned-int.hxx | 41 + .../serializer/validating/unsigned-long-long.cxx | 45 + .../serializer/validating/unsigned-long-long.hxx | 41 + .../cxx/serializer/validating/unsigned-long.cxx | 45 + .../cxx/serializer/validating/unsigned-long.hxx | 41 + .../cxx/serializer/validating/unsigned-short.cxx | 45 + .../cxx/serializer/validating/unsigned-short.hxx | 41 + libxsde/xsde/cxx/serializer/validating/uri-stl.cxx | 39 + libxsde/xsde/cxx/serializer/validating/uri-stl.hxx | 41 + libxsde/xsde/cxx/serializer/validating/uri.cxx | 47 + libxsde/xsde/cxx/serializer/validating/uri.hxx | 47 + libxsde/xsde/cxx/serializer/validating/uri.ixx | 22 + .../cxx/serializer/validating/xml-schema-simpl.hxx | 82 + .../cxx/serializer/validating/xml-schema-sskel.cxx | 560 ++ .../cxx/serializer/validating/xml-schema-sskel.hxx | 1382 +++++ .../cxx/serializer/validating/xml-schema-sskel.ixx | 704 +++ libxsde/xsde/cxx/serializer/xml-schema.hxx | 20 + libxsde/xsde/cxx/strdupx.cxx | 48 + libxsde/xsde/cxx/strdupx.hxx | 27 + libxsde/xsde/cxx/string-sequence-stl.cxx | 147 + libxsde/xsde/cxx/string-sequence-stl.hxx | 135 + libxsde/xsde/cxx/string-sequence-stl.ixx | 204 + libxsde/xsde/cxx/string-sequence.cxx | 76 + libxsde/xsde/cxx/string-sequence.hxx | 133 + libxsde/xsde/cxx/string-sequence.ixx | 233 + libxsde/xsde/cxx/string.cxx | 75 + libxsde/xsde/cxx/string.hxx | 112 + libxsde/xsde/cxx/string.ixx | 149 + libxsde/xsde/cxx/sys-error.cxx | 27 + libxsde/xsde/cxx/sys-error.hxx | 42 + libxsde/xsde/cxx/sys-error.ixx | 16 + libxsde/xsde/cxx/version.hxx | 29 + libxsde/xsde/cxx/xml/char-table.cxx | 27 + libxsde/xsde/cxx/xml/char-table.hxx | 24 + libxsde/xsde/cxx/xml/ncname.cxx | 43 + libxsde/xsde/cxx/xml/ncname.hxx | 23 + libxsde/xsde/makefile | 558 ++ makefile | 43 + tests/cxx/hashmap/driver.cxx | 98 + tests/cxx/hashmap/makefile | 61 + tests/cxx/hashmap/output | 9 + tests/cxx/hybrid/built-in/driver.cxx | 56 + tests/cxx/hybrid/built-in/makefile | 88 + tests/cxx/hybrid/built-in/output | 5 + tests/cxx/hybrid/built-in/test.xml | 24 + tests/cxx/hybrid/built-in/test.xsd | 125 + tests/cxx/hybrid/choice/driver.cxx | 70 + tests/cxx/hybrid/choice/makefile | 88 + tests/cxx/hybrid/choice/output | 1 + tests/cxx/hybrid/choice/test.xml | 57 + tests/cxx/hybrid/choice/test.xsd | 174 + tests/cxx/hybrid/compositor/includee.xsd | 14 + tests/cxx/hybrid/compositor/includer.xsd | 14 + tests/cxx/hybrid/compositor/test.xsd | 186 + tests/cxx/hybrid/compositor/tmp.xsd | 87 + tests/cxx/hybrid/file-per-type/a.xsd | 14 + tests/cxx/hybrid/file-per-type/b.xsd | 16 + tests/cxx/hybrid/file-per-type/test.xsd | 9 + tests/cxx/hybrid/list/driver.cxx | 56 + tests/cxx/hybrid/list/makefile | 88 + tests/cxx/hybrid/list/output | 1 + tests/cxx/hybrid/list/test.xml | 8 + tests/cxx/hybrid/list/test.xsd | 35 + tests/cxx/hybrid/makefile | 29 + tests/cxx/hybrid/reorder/test.xsd | 26 + tests/cxx/hybrid/sequences/driver.cxx | 442 ++ tests/cxx/hybrid/sequences/makefile | 61 + tests/cxx/hybrid/size/test.xsd | 136 + tests/cxx/hybrid/test-template/driver.cxx | 56 + tests/cxx/hybrid/test-template/makefile | 88 + tests/cxx/hybrid/test-template/output | 1 + tests/cxx/hybrid/test-template/test.xml | 5 + tests/cxx/hybrid/test-template/test.xsd | 12 + tests/cxx/hybrid/union/driver.cxx | 56 + tests/cxx/hybrid/union/makefile | 88 + tests/cxx/hybrid/union/output | 1 + tests/cxx/hybrid/union/test.xml | 6 + tests/cxx/hybrid/union/test.xsd | 26 + tests/cxx/makefile | 24 + tests/cxx/parser/built-in/driver.cxx | 661 ++ tests/cxx/parser/built-in/makefile | 79 + tests/cxx/parser/built-in/output-long | 167 + tests/cxx/parser/built-in/output-long-long | 167 + tests/cxx/parser/built-in/test-long-long.xml | 199 + tests/cxx/parser/built-in/test-long.xml | 199 + tests/cxx/parser/built-in/test.xsd | 63 + tests/cxx/parser/duplicate/makefile | 79 + tests/cxx/parser/duplicate/output | 3 + tests/cxx/parser/duplicate/test.xml | 9 + tests/cxx/parser/duplicate/test.xsd | 16 + tests/cxx/parser/enumeration/driver.cxx | 99 + tests/cxx/parser/enumeration/gender.hxx | 15 + tests/cxx/parser/enumeration/makefile | 76 + tests/cxx/parser/enumeration/output | 3 + tests/cxx/parser/enumeration/test.map | 7 + tests/cxx/parser/enumeration/test.xml | 10 + tests/cxx/parser/enumeration/test.xsd | 35 + tests/cxx/parser/error-handling/codes/driver.cxx | 276 + tests/cxx/parser/error-handling/codes/makefile | 74 + tests/cxx/parser/error-handling/codes/output | 15 + tests/cxx/parser/error-handling/codes/test.map | 4 + tests/cxx/parser/error-handling/codes/test.xml | 9 + tests/cxx/parser/error-handling/codes/test.xsd | 19 + .../parser/error-handling/exceptions/driver.cxx | 256 + .../cxx/parser/error-handling/exceptions/makefile | 75 + tests/cxx/parser/error-handling/exceptions/output | 15 + .../cxx/parser/error-handling/exceptions/test.map | 4 + .../cxx/parser/error-handling/exceptions/test.xml | 9 + .../cxx/parser/error-handling/exceptions/test.xsd | 19 + tests/cxx/parser/error-handling/makefile | 24 + tests/cxx/parser/generated-impl/makefile | 79 + tests/cxx/parser/generated-impl/output | 122 + tests/cxx/parser/generated-impl/test.xml | 168 + tests/cxx/parser/generated-impl/test.xsd | 142 + tests/cxx/parser/list/driver.cxx | 127 + tests/cxx/parser/list/makefile | 72 + tests/cxx/parser/list/output | 26 + tests/cxx/parser/list/test.xml | 25 + tests/cxx/parser/list/test.xsd | 25 + tests/cxx/parser/makefile | 57 + tests/cxx/parser/name-clash/inheritance/driver.cxx | 87 + tests/cxx/parser/name-clash/inheritance/makefile | 72 + tests/cxx/parser/name-clash/inheritance/output | 2 + tests/cxx/parser/name-clash/inheritance/test.xml | 8 + tests/cxx/parser/name-clash/inheritance/test.xsd | 22 + tests/cxx/parser/polymorphism/driver.cxx | 124 + tests/cxx/parser/polymorphism/makefile | 73 + tests/cxx/parser/polymorphism/output | 14 + tests/cxx/parser/polymorphism/test.xml | 19 + tests/cxx/parser/polymorphism/test.xsd | 45 + tests/cxx/parser/recursive/driver.cxx | 172 + tests/cxx/parser/recursive/makefile | 73 + tests/cxx/parser/recursive/output | 22 + tests/cxx/parser/recursive/test.xml | 11 + tests/cxx/parser/recursive/test.xsd | 27 + tests/cxx/parser/reset/driver.cxx | 300 + tests/cxx/parser/reset/fail-schema.xml | 8 + tests/cxx/parser/reset/fail-xml.xml | 7 + tests/cxx/parser/reset/makefile | 75 + tests/cxx/parser/reset/output | 8 + tests/cxx/parser/reset/pass.xml | 7 + tests/cxx/parser/reset/test.xsd | 27 + tests/cxx/parser/test-template/driver.cxx | 77 + tests/cxx/parser/test-template/makefile | 72 + tests/cxx/parser/test-template/output | 1 + tests/cxx/parser/test-template/test.xml | 7 + tests/cxx/parser/test-template/test.xsd | 12 + tests/cxx/parser/union/driver.cxx | 62 + tests/cxx/parser/union/makefile | 72 + tests/cxx/parser/union/output | 3 + tests/cxx/parser/union/test.xml | 10 + tests/cxx/parser/union/test.xsd | 16 + tests/cxx/parser/validation/all/driver.cxx | 121 + tests/cxx/parser/validation/all/makefile | 82 + tests/cxx/parser/validation/all/test-000.std | 46 + tests/cxx/parser/validation/all/test-000.xml | 53 + tests/cxx/parser/validation/all/test-001.std | 6 + tests/cxx/parser/validation/all/test-001.xml | 11 + tests/cxx/parser/validation/all/test-002.std | 4 + tests/cxx/parser/validation/all/test-002.xml | 9 + tests/cxx/parser/validation/all/test-003.std | 6 + tests/cxx/parser/validation/all/test-003.xml | 12 + tests/cxx/parser/validation/all/test.xsd | 20 + tests/cxx/parser/validation/any/driver.cxx | 139 + tests/cxx/parser/validation/any/makefile | 82 + tests/cxx/parser/validation/any/test-000.std | 29 + tests/cxx/parser/validation/any/test-000.xml | 21 + tests/cxx/parser/validation/any/test.xsd | 20 + tests/cxx/parser/validation/attribute/driver.cxx | 275 + tests/cxx/parser/validation/attribute/makefile | 72 + tests/cxx/parser/validation/attribute/output | 24 + tests/cxx/parser/validation/attribute/test.xml | 10 + tests/cxx/parser/validation/attribute/test.xsd | 71 + .../parser/validation/built-in/any-type/driver.cxx | 187 + .../parser/validation/built-in/any-type/makefile | 82 + .../validation/built-in/any-type/test-000.std | 113 + .../validation/built-in/any-type/test-000.xml | 41 + .../parser/validation/built-in/any-type/test.xsd | 31 + .../parser/validation/built-in/binary/driver.cxx | 176 + .../cxx/parser/validation/built-in/binary/makefile | 61 + .../parser/validation/built-in/boolean/driver.cxx | 150 + .../parser/validation/built-in/boolean/makefile | 61 + .../cxx/parser/validation/built-in/byte/driver.cxx | 280 + tests/cxx/parser/validation/built-in/byte/makefile | 61 + .../validation/built-in/date-time/driver.cxx | 1833 ++++++ .../parser/validation/built-in/date-time/makefile | 61 + .../parser/validation/built-in/float/driver.cxx | 309 + .../cxx/parser/validation/built-in/float/makefile | 61 + .../cxx/parser/validation/built-in/int/driver.cxx | 116 + tests/cxx/parser/validation/built-in/int/makefile | 61 + .../parser/validation/built-in/integer/driver.cxx | 317 + .../parser/validation/built-in/integer/makefile | 61 + .../validation/built-in/long-long/driver.cxx | 118 + .../parser/validation/built-in/long-long/makefile | 61 + .../cxx/parser/validation/built-in/long/driver.cxx | 106 + tests/cxx/parser/validation/built-in/long/makefile | 61 + tests/cxx/parser/validation/built-in/makefile | 35 + .../parser/validation/built-in/qname/driver.cxx | 132 + .../cxx/parser/validation/built-in/qname/makefile | 61 + .../parser/validation/built-in/short/driver.cxx | 116 + .../cxx/parser/validation/built-in/short/makefile | 61 + .../parser/validation/built-in/string/driver.cxx | 613 ++ .../cxx/parser/validation/built-in/string/makefile | 61 + .../cxx/parser/validation/built-in/uri/driver.cxx | 66 + tests/cxx/parser/validation/built-in/uri/makefile | 61 + tests/cxx/parser/validation/choice/driver.cxx | 158 + tests/cxx/parser/validation/choice/makefile | 81 + tests/cxx/parser/validation/choice/test-000.std | 22 + tests/cxx/parser/validation/choice/test-000.xml | 30 + tests/cxx/parser/validation/choice/test-001.std | 4 + tests/cxx/parser/validation/choice/test-001.xml | 10 + tests/cxx/parser/validation/choice/test-002.std | 11 + tests/cxx/parser/validation/choice/test-002.xml | 17 + tests/cxx/parser/validation/choice/test-003.std | 5 + tests/cxx/parser/validation/choice/test-003.xml | 11 + tests/cxx/parser/validation/choice/test-004.std | 4 + tests/cxx/parser/validation/choice/test-004.xml | 11 + tests/cxx/parser/validation/choice/test.xsd | 24 + tests/cxx/parser/validation/makefile | 26 + tests/cxx/parser/validation/restriction/driver.cxx | 122 + tests/cxx/parser/validation/restriction/makefile | 81 + .../cxx/parser/validation/restriction/test-000.std | 0 .../cxx/parser/validation/restriction/test-000.xml | 31 + .../cxx/parser/validation/restriction/test-001.std | 1 + .../cxx/parser/validation/restriction/test-001.xml | 11 + .../cxx/parser/validation/restriction/test-002.std | 1 + .../cxx/parser/validation/restriction/test-002.xml | 12 + .../cxx/parser/validation/restriction/test-003.std | 1 + .../cxx/parser/validation/restriction/test-003.xml | 16 + .../cxx/parser/validation/restriction/test-004.std | 1 + .../cxx/parser/validation/restriction/test-004.xml | 10 + .../cxx/parser/validation/restriction/test-005.std | 1 + .../cxx/parser/validation/restriction/test-005.xml | 11 + tests/cxx/parser/validation/restriction/test.xsd | 82 + tests/cxx/parser/validation/sequence/driver.cxx | 185 + tests/cxx/parser/validation/sequence/makefile | 81 + tests/cxx/parser/validation/sequence/test-000.std | 56 + tests/cxx/parser/validation/sequence/test-000.xml | 46 + tests/cxx/parser/validation/sequence/test-001.std | 4 + tests/cxx/parser/validation/sequence/test-001.xml | 10 + tests/cxx/parser/validation/sequence/test-002.std | 20 + tests/cxx/parser/validation/sequence/test-002.xml | 27 + tests/cxx/parser/validation/sequence/test-003.std | 5 + tests/cxx/parser/validation/sequence/test-003.xml | 17 + tests/cxx/parser/validation/sequence/test-004.std | 4 + tests/cxx/parser/validation/sequence/test-004.xml | 14 + tests/cxx/parser/validation/sequence/test-005.std | 6 + tests/cxx/parser/validation/sequence/test-005.xml | 15 + tests/cxx/parser/validation/sequence/test-006.std | 13 + tests/cxx/parser/validation/sequence/test-006.xml | 17 + tests/cxx/parser/validation/sequence/test.xsd | 28 + tests/cxx/serializer/all/driver.cxx | 108 + tests/cxx/serializer/all/makefile | 72 + tests/cxx/serializer/all/output | 1 + tests/cxx/serializer/all/test.xsd | 27 + tests/cxx/serializer/built-in/driver.cxx | 1304 ++++ tests/cxx/serializer/built-in/makefile | 79 + tests/cxx/serializer/built-in/output-long | 13 + tests/cxx/serializer/built-in/output-long-long | 13 + tests/cxx/serializer/built-in/test.xsd | 64 + tests/cxx/serializer/choice/driver.cxx | 253 + tests/cxx/serializer/choice/makefile | 72 + tests/cxx/serializer/choice/output | 1 + tests/cxx/serializer/choice/test.xsd | 51 + tests/cxx/serializer/complex/driver.cxx | 87 + tests/cxx/serializer/complex/makefile | 72 + tests/cxx/serializer/complex/output | 1 + tests/cxx/serializer/complex/test.xsd | 33 + tests/cxx/serializer/enumeration/boolean.hxx | 15 + tests/cxx/serializer/enumeration/driver.cxx | 74 + tests/cxx/serializer/enumeration/makefile | 75 + tests/cxx/serializer/enumeration/output | 1 + tests/cxx/serializer/enumeration/test.map | 7 + tests/cxx/serializer/enumeration/test.xsd | 35 + .../cxx/serializer/error-handling/codes/driver.cxx | 327 + tests/cxx/serializer/error-handling/codes/makefile | 72 + tests/cxx/serializer/error-handling/codes/output | 20 + tests/cxx/serializer/error-handling/codes/test.xsd | 22 + .../error-handling/exceptions/driver.cxx | 285 + .../serializer/error-handling/exceptions/makefile | 72 + .../serializer/error-handling/exceptions/output | 20 + .../serializer/error-handling/exceptions/test.xsd | 22 + tests/cxx/serializer/error-handling/makefile | 24 + tests/cxx/serializer/generated-driver/makefile | 75 + tests/cxx/serializer/generated-driver/output | 1 + .../cxx/serializer/generated-driver/test-simpl.cxx | 28 + .../cxx/serializer/generated-driver/test-simpl.hxx | 27 + tests/cxx/serializer/generated-driver/test.xsd | 12 + tests/cxx/serializer/generated-impl/makefile | 84 + tests/cxx/serializer/generated-impl/test.xsd | 193 + tests/cxx/serializer/list/driver.cxx | 114 + tests/cxx/serializer/list/makefile | 72 + tests/cxx/serializer/list/output | 1 + tests/cxx/serializer/list/test.xsd | 25 + tests/cxx/serializer/makefile | 52 + tests/cxx/serializer/polymorphism/driver.cxx | 203 + tests/cxx/serializer/polymorphism/makefile | 73 + tests/cxx/serializer/polymorphism/output | 1 + tests/cxx/serializer/polymorphism/test.xsd | 64 + tests/cxx/serializer/recursive/driver.cxx | 135 + tests/cxx/serializer/recursive/makefile | 72 + tests/cxx/serializer/recursive/output | 1 + tests/cxx/serializer/recursive/test.xsd | 27 + tests/cxx/serializer/reset/driver.cxx | 281 + tests/cxx/serializer/reset/makefile | 72 + tests/cxx/serializer/reset/output | 7 + tests/cxx/serializer/reset/test.xsd | 27 + tests/cxx/serializer/restriction/driver.cxx | 246 + tests/cxx/serializer/restriction/makefile | 72 + tests/cxx/serializer/restriction/output | 1 + tests/cxx/serializer/restriction/test.xsd | 175 + tests/cxx/serializer/sequence/driver.cxx | 231 + tests/cxx/serializer/sequence/makefile | 72 + tests/cxx/serializer/sequence/output | 1 + tests/cxx/serializer/sequence/test.xsd | 51 + tests/cxx/serializer/test-template/driver.cxx | 48 + tests/cxx/serializer/test-template/makefile | 72 + tests/cxx/serializer/test-template/output | 1 + tests/cxx/serializer/test-template/test.xsd | 12 + tests/cxx/serializer/union/driver.cxx | 93 + tests/cxx/serializer/union/makefile | 72 + tests/cxx/serializer/union/output | 1 + tests/cxx/serializer/union/test.xsd | 25 + tests/cxx/serializer/validation/any/driver.cxx | 317 + tests/cxx/serializer/validation/any/makefile | 72 + tests/cxx/serializer/validation/any/output | 9 + tests/cxx/serializer/validation/any/test.xsd | 53 + .../cxx/serializer/validation/attribute/driver.cxx | 247 + tests/cxx/serializer/validation/attribute/makefile | 72 + tests/cxx/serializer/validation/attribute/output | 9 + tests/cxx/serializer/validation/attribute/test.xsd | 21 + .../validation/built-in/date-time/driver.cxx | 398 ++ .../validation/built-in/date-time/makefile | 61 + .../validation/built-in/decimal/driver.cxx | 46 + .../validation/built-in/decimal/makefile | 61 + .../validation/built-in/integer/driver.cxx | 63 + .../validation/built-in/integer/makefile | 61 + tests/cxx/serializer/validation/built-in/makefile | 20 + .../validation/built-in/qname/driver.cxx | 70 + .../serializer/validation/built-in/qname/makefile | 61 + .../validation/built-in/string/driver.cxx | 485 ++ .../serializer/validation/built-in/string/makefile | 61 + tests/cxx/serializer/validation/choice/driver.cxx | 114 + tests/cxx/serializer/validation/choice/makefile | 72 + tests/cxx/serializer/validation/choice/output | 2 + tests/cxx/serializer/validation/choice/test.xsd | 21 + tests/cxx/serializer/validation/element/driver.cxx | 106 + tests/cxx/serializer/validation/element/makefile | 72 + tests/cxx/serializer/validation/element/output | 2 + tests/cxx/serializer/validation/element/test.xsd | 19 + tests/cxx/serializer/validation/makefile | 24 + .../cxx/serializer/validation/sequence/driver.cxx | 102 + tests/cxx/serializer/validation/sequence/makefile | 72 + tests/cxx/serializer/validation/sequence/output | 1 + tests/cxx/serializer/validation/sequence/test.xsd | 21 + tests/cxx/serializer/wildcard/driver.cxx | 237 + tests/cxx/serializer/wildcard/makefile | 72 + tests/cxx/serializer/wildcard/output | 1 + tests/cxx/serializer/wildcard/test.xsd | 25 + tests/cxx/string/driver.cxx | 102 + tests/cxx/string/makefile | 61 + tests/makefile | 18 + tests/type-map/driver.cxx | 47 + version | 1 + xsde/cxx/elements.cxx | 1089 ++++ xsde/cxx/elements.hxx | 599 ++ xsde/cxx/hybrid/cli.hxx | 188 + xsde/cxx/hybrid/elements.cxx | 493 ++ xsde/cxx/hybrid/elements.hxx | 1880 ++++++ xsde/cxx/hybrid/generator.cxx | 2476 ++++++++ xsde/cxx/hybrid/generator.hxx | 90 + xsde/cxx/hybrid/parser-aggregate-header.cxx | 837 +++ xsde/cxx/hybrid/parser-aggregate-header.hxx | 22 + xsde/cxx/hybrid/parser-aggregate-source.cxx | 330 + xsde/cxx/hybrid/parser-aggregate-source.hxx | 22 + xsde/cxx/hybrid/parser-header.cxx | 574 ++ xsde/cxx/hybrid/parser-header.hxx | 22 + xsde/cxx/hybrid/parser-name-processor.cxx | 709 +++ xsde/cxx/hybrid/parser-name-processor.hxx | 32 + xsde/cxx/hybrid/parser-source.cxx | 1185 ++++ xsde/cxx/hybrid/parser-source.hxx | 22 + xsde/cxx/hybrid/serializer-aggregate-header.cxx | 847 +++ xsde/cxx/hybrid/serializer-aggregate-header.hxx | 22 + xsde/cxx/hybrid/serializer-aggregate-source.cxx | 330 + xsde/cxx/hybrid/serializer-aggregate-source.hxx | 22 + xsde/cxx/hybrid/serializer-header.cxx | 534 ++ xsde/cxx/hybrid/serializer-header.hxx | 22 + xsde/cxx/hybrid/serializer-name-processor.cxx | 723 +++ xsde/cxx/hybrid/serializer-name-processor.hxx | 32 + xsde/cxx/hybrid/serializer-source.cxx | 1001 +++ xsde/cxx/hybrid/serializer-source.hxx | 22 + xsde/cxx/hybrid/tree-forward.cxx | 626 ++ xsde/cxx/hybrid/tree-forward.hxx | 22 + xsde/cxx/hybrid/tree-header.cxx | 2459 ++++++++ xsde/cxx/hybrid/tree-header.hxx | 22 + xsde/cxx/hybrid/tree-inline.cxx | 1817 ++++++ xsde/cxx/hybrid/tree-inline.hxx | 22 + xsde/cxx/hybrid/tree-name-processor.cxx | 1993 ++++++ xsde/cxx/hybrid/tree-name-processor.hxx | 32 + xsde/cxx/hybrid/tree-size-processor.cxx | 850 +++ xsde/cxx/hybrid/tree-size-processor.hxx | 32 + xsde/cxx/hybrid/tree-source.cxx | 1672 +++++ xsde/cxx/hybrid/tree-source.hxx | 22 + xsde/cxx/hybrid/tree-type-map.cxx | 248 + xsde/cxx/hybrid/tree-type-map.hxx | 32 + xsde/cxx/hybrid/validator.cxx | 584 ++ xsde/cxx/hybrid/validator.hxx | 35 + xsde/cxx/parser/attribute-validation-source.cxx | 468 ++ xsde/cxx/parser/attribute-validation-source.hxx | 22 + xsde/cxx/parser/characters-validation-source.cxx | 76 + xsde/cxx/parser/characters-validation-source.hxx | 22 + xsde/cxx/parser/cli.hxx | 156 + xsde/cxx/parser/driver-source.cxx | 1139 ++++ xsde/cxx/parser/driver-source.hxx | 22 + xsde/cxx/parser/element-validation-source.cxx | 2120 +++++++ xsde/cxx/parser/element-validation-source.hxx | 22 + xsde/cxx/parser/elements.cxx | 258 + xsde/cxx/parser/elements.hxx | 431 ++ xsde/cxx/parser/generator.cxx | 1615 +++++ xsde/cxx/parser/generator.hxx | 56 + xsde/cxx/parser/impl-header.cxx | 309 + xsde/cxx/parser/impl-header.hxx | 22 + xsde/cxx/parser/impl-source.cxx | 543 ++ xsde/cxx/parser/impl-source.hxx | 22 + xsde/cxx/parser/name-processor.cxx | 1326 ++++ xsde/cxx/parser/name-processor.hxx | 32 + xsde/cxx/parser/parser-forward.cxx | 112 + xsde/cxx/parser/parser-forward.hxx | 22 + xsde/cxx/parser/parser-header.cxx | 1818 ++++++ xsde/cxx/parser/parser-header.hxx | 22 + xsde/cxx/parser/parser-inline.cxx | 721 +++ xsde/cxx/parser/parser-inline.hxx | 22 + xsde/cxx/parser/parser-source.cxx | 1626 +++++ xsde/cxx/parser/parser-source.hxx | 22 + xsde/cxx/parser/print-impl-common.hxx | 1063 ++++ xsde/cxx/parser/state-processor.cxx | 319 + xsde/cxx/parser/state-processor.hxx | 28 + xsde/cxx/parser/type-processor.cxx | 352 ++ xsde/cxx/parser/type-processor.hxx | 34 + xsde/cxx/parser/validator.cxx | 704 +++ xsde/cxx/parser/validator.hxx | 36 + .../cxx/serializer/attribute-validation-source.cxx | 463 ++ .../cxx/serializer/attribute-validation-source.hxx | 22 + xsde/cxx/serializer/cli.hxx | 154 + xsde/cxx/serializer/driver-source.cxx | 1047 ++++ xsde/cxx/serializer/driver-source.hxx | 22 + xsde/cxx/serializer/element-validation-source.cxx | 903 +++ xsde/cxx/serializer/element-validation-source.hxx | 22 + xsde/cxx/serializer/elements.cxx | 278 + xsde/cxx/serializer/elements.hxx | 443 ++ xsde/cxx/serializer/generator.cxx | 1600 +++++ xsde/cxx/serializer/generator.hxx | 56 + xsde/cxx/serializer/impl-header.cxx | 488 ++ xsde/cxx/serializer/impl-header.hxx | 22 + xsde/cxx/serializer/impl-source.cxx | 664 ++ xsde/cxx/serializer/impl-source.hxx | 22 + xsde/cxx/serializer/name-processor.cxx | 1409 +++++ xsde/cxx/serializer/name-processor.hxx | 32 + xsde/cxx/serializer/serializer-forward.cxx | 112 + xsde/cxx/serializer/serializer-forward.hxx | 22 + xsde/cxx/serializer/serializer-header.cxx | 2006 ++++++ xsde/cxx/serializer/serializer-header.hxx | 22 + xsde/cxx/serializer/serializer-inline.cxx | 631 ++ xsde/cxx/serializer/serializer-inline.hxx | 22 + xsde/cxx/serializer/serializer-source.cxx | 2703 +++++++++ xsde/cxx/serializer/serializer-source.hxx | 22 + xsde/cxx/serializer/type-processor.cxx | 356 ++ xsde/cxx/serializer/type-processor.hxx | 34 + xsde/cxx/serializer/validator.cxx | 501 ++ xsde/cxx/serializer/validator.hxx | 36 + xsde/elements.hxx | 135 + xsde/makefile | 162 + xsde/processing/inheritance/processor.cxx | 517 ++ xsde/processing/inheritance/processor.hxx | 38 + xsde/type-map/lexer.cxx | 133 + xsde/type-map/lexer.hxx | 80 + xsde/type-map/parser.cxx | 281 + xsde/type-map/parser.hxx | 46 + xsde/type-map/type-map.hxx | 160 + xsde/usage.hxx | 226 + xsde/xsde.cxx | 1422 +++++ xsde/xsde.hxx | 79 + 1382 files changed, 196632 insertions(+) create mode 100644 GPLv2 create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 NEWS create mode 100644 README create mode 100644 build/bootstrap.make create mode 100644 build/configuration-rules.make create mode 100644 build/configuration.make create mode 100755 build/configure create mode 100644 build/import/libbackend-elements/LICENSE create mode 100644 build/import/libbackend-elements/configuration-rules.make create mode 100755 build/import/libbackend-elements/configure create mode 100644 build/import/libbackend-elements/stub.make create mode 100644 build/import/libboost/LICENSE create mode 100644 build/import/libboost/configuration-rules.make create mode 100755 build/import/libboost/configure create mode 100644 build/import/libboost/date-time/rules.make create mode 100644 build/import/libboost/date-time/stub.make create mode 100644 build/import/libboost/filesystem/rules.make create mode 100644 build/import/libboost/filesystem/stub.make create mode 100644 build/import/libboost/regex/rules.make create mode 100644 build/import/libboost/regex/stub.make create mode 100644 build/import/libboost/version create mode 100644 build/import/libcult/LICENSE create mode 100644 build/import/libcult/configuration-rules.make create mode 100755 build/import/libcult/configure create mode 100644 build/import/libcult/stub.make create mode 100644 build/import/libxsd-frontend/LICENSE create mode 100644 build/import/libxsd-frontend/configuration-rules.make create mode 100755 build/import/libxsd-frontend/configure create mode 100644 build/import/libxsd-frontend/stub.make create mode 100644 build/xsde/hybrid/xsd-cxx.make create mode 100644 build/xsde/parser/xsd-cxx.make create mode 100644 build/xsde/serializer/xsd-cxx.make create mode 100644 documentation/cxx/hybrid/guide/figure-1.png create mode 100644 documentation/cxx/hybrid/guide/figure-1.svg create mode 100644 documentation/cxx/hybrid/guide/guide.html2ps create mode 100644 documentation/cxx/hybrid/guide/index.xhtml create mode 100644 documentation/cxx/hybrid/guide/makefile create mode 100644 documentation/cxx/parser/guide/figure-1.png create mode 100644 documentation/cxx/parser/guide/figure-1.svg create mode 100644 documentation/cxx/parser/guide/guide.html2ps create mode 100644 documentation/cxx/parser/guide/index.xhtml create mode 100644 documentation/cxx/parser/guide/makefile create mode 100644 documentation/cxx/serializer/guide/figure-1.png create mode 100644 documentation/cxx/serializer/guide/figure-1.svg create mode 100644 documentation/cxx/serializer/guide/guide.html2ps create mode 100644 documentation/cxx/serializer/guide/index.xhtml create mode 100644 documentation/cxx/serializer/guide/makefile create mode 100644 documentation/default.css create mode 100644 documentation/makefile create mode 100644 documentation/xsde.1 create mode 100644 documentation/xsde.xhtml 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 create mode 100644 examples/makefile create mode 100644 libxsde/makefile create mode 100644 libxsde/xsde/c/expat/COPYING create mode 100644 libxsde/xsde/c/expat/ascii.h create mode 100644 libxsde/xsde/c/expat/asciitab.h create mode 100644 libxsde/xsde/c/expat/config.h create mode 100644 libxsde/xsde/c/expat/expat.h create mode 100644 libxsde/xsde/c/expat/expat_external.h create mode 100644 libxsde/xsde/c/expat/iasciitab.h create mode 100644 libxsde/xsde/c/expat/internal.h create mode 100644 libxsde/xsde/c/expat/latin1tab.h create mode 100644 libxsde/xsde/c/expat/nametab.h create mode 100644 libxsde/xsde/c/expat/utf8tab.h create mode 100644 libxsde/xsde/c/expat/xmlparse.c create mode 100644 libxsde/xsde/c/expat/xmlrole.c create mode 100644 libxsde/xsde/c/expat/xmlrole.h create mode 100644 libxsde/xsde/c/expat/xmltok.c create mode 100644 libxsde/xsde/c/expat/xmltok.h create mode 100644 libxsde/xsde/c/expat/xmltok_impl.c create mode 100644 libxsde/xsde/c/expat/xmltok_impl.h create mode 100644 libxsde/xsde/c/expat/xmltok_ns.c create mode 100644 libxsde/xsde/c/genx/COPYING create mode 100644 libxsde/xsde/c/genx/char-props.c create mode 100644 libxsde/xsde/c/genx/genx.c create mode 100644 libxsde/xsde/c/genx/genx.h create mode 100644 libxsde/xsde/cxx/buffer.cxx create mode 100644 libxsde/xsde/cxx/buffer.hxx create mode 100644 libxsde/xsde/cxx/buffer.ixx create mode 100644 libxsde/xsde/cxx/compilers/vc-6/post.hxx create mode 100644 libxsde/xsde/cxx/compilers/vc-6/pre.hxx create mode 100644 libxsde/xsde/cxx/compilers/vc-7/post.hxx create mode 100644 libxsde/xsde/cxx/compilers/vc-7/pre.hxx create mode 100644 libxsde/xsde/cxx/compilers/vc-8/post.hxx create mode 100644 libxsde/xsde/cxx/compilers/vc-8/pre.hxx create mode 100644 libxsde/xsde/cxx/config.hxx create mode 100644 libxsde/xsde/cxx/date-time.hxx create mode 100644 libxsde/xsde/cxx/date-time.ixx create mode 100644 libxsde/xsde/cxx/errno.hxx create mode 100644 libxsde/xsde/cxx/errno.ixx create mode 100644 libxsde/xsde/cxx/exceptions.hxx create mode 100644 libxsde/xsde/cxx/hashmap.cxx create mode 100644 libxsde/xsde/cxx/hashmap.hxx create mode 100644 libxsde/xsde/cxx/hashmap.ixx create mode 100644 libxsde/xsde/cxx/hybrid/any-type.hxx create mode 100644 libxsde/xsde/cxx/hybrid/base.hxx create mode 100644 libxsde/xsde/cxx/hybrid/sequence.cxx create mode 100644 libxsde/xsde/cxx/hybrid/sequence.hxx create mode 100644 libxsde/xsde/cxx/hybrid/sequence.ixx create mode 100644 libxsde/xsde/cxx/hybrid/sequence.txx create mode 100644 libxsde/xsde/cxx/hybrid/xml-schema.hxx create mode 100644 libxsde/xsde/cxx/parser/context.cxx create mode 100644 libxsde/xsde/cxx/parser/context.hxx create mode 100644 libxsde/xsde/cxx/parser/context.ixx create mode 100644 libxsde/xsde/cxx/parser/elements.cxx create mode 100644 libxsde/xsde/cxx/parser/elements.hxx create mode 100644 libxsde/xsde/cxx/parser/elements.ixx create mode 100644 libxsde/xsde/cxx/parser/error.cxx create mode 100644 libxsde/xsde/cxx/parser/error.hxx create mode 100644 libxsde/xsde/cxx/parser/error.ixx create mode 100644 libxsde/xsde/cxx/parser/exceptions.cxx create mode 100644 libxsde/xsde/cxx/parser/exceptions.hxx create mode 100644 libxsde/xsde/cxx/parser/exceptions.ixx create mode 100644 libxsde/xsde/cxx/parser/expat/document.cxx create mode 100644 libxsde/xsde/cxx/parser/expat/document.hxx create mode 100644 libxsde/xsde/cxx/parser/expat/document.ixx create mode 100644 libxsde/xsde/cxx/parser/expat/xml-error.cxx create mode 100644 libxsde/xsde/cxx/parser/expat/xml-error.hxx create mode 100644 libxsde/xsde/cxx/parser/map.cxx create mode 100644 libxsde/xsde/cxx/parser/map.hxx create mode 100644 libxsde/xsde/cxx/parser/map.ixx create mode 100644 libxsde/xsde/cxx/parser/non-validating/any-type.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/base64-binary.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/boolean.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/boolean.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/byte.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/byte.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/date-time.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/date-time.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/date.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/date.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/decimal.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/decimal.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/double.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/double.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/duration.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/duration.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/float.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/float.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gday.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gday.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gmonth-day.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gmonth-day.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gmonth.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gmonth.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gyear-month.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gyear-month.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gyear.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/gyear.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/hex-binary.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/hex-binary.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/id-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/id-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/id.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/id.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idref-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idref-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idref.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idref.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idrefs-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idrefs-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idrefs.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/idrefs.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/int.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/int.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/integer.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/integer.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/language-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/language-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/language.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/language.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/long-long.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/long-long.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/long.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/long.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/name-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/name-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/name.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/name.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/ncname-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/ncname-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/ncname.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/ncname.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/negative-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/negative-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtokens.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/nmtokens.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/non-negative-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/non-negative-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/non-positive-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/non-positive-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/normalized-string.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/normalized-string.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/number.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/number.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/parser.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/parser.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/parser.ixx create mode 100644 libxsde/xsde/cxx/parser/non-validating/positive-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/positive-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/qname-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/qname-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/qname.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/qname.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/short.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/short.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/string-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/string-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/string.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/string.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/time-zone.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/time-zone.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/time.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/time.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/token-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/token-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/token.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/token.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-byte.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-byte.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-int.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-int.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-long.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-long.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-short.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/unsigned-short.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/uri.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/uri.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.cxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.hxx create mode 100644 libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.ixx create mode 100644 libxsde/xsde/cxx/parser/state.cxx create mode 100644 libxsde/xsde/cxx/parser/state.hxx create mode 100644 libxsde/xsde/cxx/parser/state.ixx create mode 100644 libxsde/xsde/cxx/parser/substitution-map-load.hxx create mode 100644 libxsde/xsde/cxx/parser/substitution-map.cxx create mode 100644 libxsde/xsde/cxx/parser/substitution-map.hxx create mode 100644 libxsde/xsde/cxx/parser/substitution-map.ixx create mode 100644 libxsde/xsde/cxx/parser/validating/any-type.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/base64-binary.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/base64-binary.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/boolean.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/boolean.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/byte.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/byte.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/date-time.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/date-time.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/date.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/date.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/decimal.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/decimal.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/double.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/double.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/duration.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/duration.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/float.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/float.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/gday.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/gday.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/gmonth-day.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/gmonth-day.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/gmonth.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/gmonth.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/gyear-month.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/gyear-month.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/gyear.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/gyear.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/hex-binary.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/hex-binary.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/id-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/id-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/id.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/id.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/idref-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/idref-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/idref.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/idref.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/idrefs.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/idrefs.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/inheritance-map-load.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/inheritance-map.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/inheritance-map.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/inheritance-map.ixx create mode 100644 libxsde/xsde/cxx/parser/validating/int.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/int.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/integer.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/integer.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/language-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/language-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/language.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/language.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/long-long.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/long-long.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/long.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/long.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/name-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/name-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/name.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/name.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/ncname-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/ncname-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/ncname.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/ncname.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/negative-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/negative-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtoken.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtoken.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtokens-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtokens-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtokens.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/nmtokens.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/non-negative-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/non-negative-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/non-positive-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/non-positive-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/normalized-string-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/normalized-string-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/normalized-string.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/normalized-string.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/number.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/number.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/parser.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/parser.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/parser.ixx create mode 100644 libxsde/xsde/cxx/parser/validating/positive-integer.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/positive-integer.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/qname-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/qname-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/qname.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/qname.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/short.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/short.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/string-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/string-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/string.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/string.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/time-zone.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/time-zone.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/time.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/time.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/token-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/token-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/token.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/token.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-byte.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-byte.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-int.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-int.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-long-long.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-long-long.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-long.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-long.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-short.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/unsigned-short.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/uri-stl.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/uri-stl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/uri.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/uri.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/xml-schema-pimpl.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/xml-schema-pskel.cxx create mode 100644 libxsde/xsde/cxx/parser/validating/xml-schema-pskel.hxx create mode 100644 libxsde/xsde/cxx/parser/validating/xml-schema-pskel.ixx create mode 100644 libxsde/xsde/cxx/parser/xml-schema.hxx create mode 100644 libxsde/xsde/cxx/post.hxx create mode 100644 libxsde/xsde/cxx/pre.hxx create mode 100644 libxsde/xsde/cxx/qname-stl.hxx create mode 100644 libxsde/xsde/cxx/qname-stl.ixx create mode 100644 libxsde/xsde/cxx/qname.cxx create mode 100644 libxsde/xsde/cxx/qname.hxx create mode 100644 libxsde/xsde/cxx/qname.ixx create mode 100644 libxsde/xsde/cxx/ro-string.cxx create mode 100644 libxsde/xsde/cxx/ro-string.hxx create mode 100644 libxsde/xsde/cxx/ro-string.ixx create mode 100644 libxsde/xsde/cxx/schema-error.cxx create mode 100644 libxsde/xsde/cxx/schema-error.hxx create mode 100644 libxsde/xsde/cxx/schema-error.ixx create mode 100644 libxsde/xsde/cxx/sequence-base.cxx create mode 100644 libxsde/xsde/cxx/sequence-base.hxx create mode 100644 libxsde/xsde/cxx/sequence-base.ixx create mode 100644 libxsde/xsde/cxx/serializer/context.cxx create mode 100644 libxsde/xsde/cxx/serializer/context.hxx create mode 100644 libxsde/xsde/cxx/serializer/context.ixx create mode 100644 libxsde/xsde/cxx/serializer/elements.cxx create mode 100644 libxsde/xsde/cxx/serializer/elements.hxx create mode 100644 libxsde/xsde/cxx/serializer/elements.ixx create mode 100644 libxsde/xsde/cxx/serializer/error.cxx create mode 100644 libxsde/xsde/cxx/serializer/error.hxx create mode 100644 libxsde/xsde/cxx/serializer/error.ixx create mode 100644 libxsde/xsde/cxx/serializer/exceptions.cxx create mode 100644 libxsde/xsde/cxx/serializer/exceptions.hxx create mode 100644 libxsde/xsde/cxx/serializer/exceptions.ixx create mode 100644 libxsde/xsde/cxx/serializer/genx/document.cxx create mode 100644 libxsde/xsde/cxx/serializer/genx/document.hxx create mode 100644 libxsde/xsde/cxx/serializer/genx/document.ixx create mode 100644 libxsde/xsde/cxx/serializer/genx/xml-error.cxx create mode 100644 libxsde/xsde/cxx/serializer/genx/xml-error.hxx create mode 100644 libxsde/xsde/cxx/serializer/map.cxx create mode 100644 libxsde/xsde/cxx/serializer/map.hxx create mode 100644 libxsde/xsde/cxx/serializer/map.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/any-type.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/base64-binary.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/base64-binary.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/base64-binary.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/boolean.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/boolean.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/byte.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/byte.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date-time.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date-time.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date-time.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/date.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/decimal.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/decimal.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/decimal.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/double.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/double.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/double.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/duration.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/duration.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/duration.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/float.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/float.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/float.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gday.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gday.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gday.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth-day.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth-day.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth-day.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gmonth.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear-month.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear-month.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear-month.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/gyear.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/hex-binary.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/hex-binary.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/hex-binary.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/id-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/id-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/id.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/id.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/id.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idref-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idref-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idref.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idref.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idref.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/idrefs.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/int.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/int.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/language-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/language-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/language.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/language.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/language.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/long-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/long-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/long.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/long.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/name-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/name-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/name.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/name.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/name.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/ncname-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/ncname-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/ncname.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/ncname.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/ncname.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/negative-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/negative-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtoken.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtoken.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtoken.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/nmtokens.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/normalized-string.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/normalized-string.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/normalized-string.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/positive-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/positive-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/qname.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/serializer.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/serializer.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/serializer.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/short.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/short.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/string-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/string-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/string.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/string.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/string.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/time-zone.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/time-zone.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/time.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/time.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/time.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/token-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/token-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/token.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/token.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/token.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-int.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-int.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-short.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/unsigned-short.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/uri-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/uri-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/uri.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/uri.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/uri.ixx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx create mode 100644 libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx create mode 100644 libxsde/xsde/cxx/serializer/substitution-map-load.hxx create mode 100644 libxsde/xsde/cxx/serializer/substitution-map.cxx create mode 100644 libxsde/xsde/cxx/serializer/substitution-map.hxx create mode 100644 libxsde/xsde/cxx/serializer/substitution-map.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/any-type.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/base64-binary.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/base64-binary.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/base64-binary.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/boolean.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/boolean.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/byte.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/byte.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/date-time.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/date-time.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/date-time.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/date.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/date.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/date.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/decimal.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/decimal.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/decimal.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/double.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/double.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/double.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/duration.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/duration.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/duration.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/float.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/float.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/float.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/gday.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gday.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gday.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth-day.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth-day.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gmonth.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear-month.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear-month.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear-month.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/gyear.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/hex-binary.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/hex-binary.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/hex-binary.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/id-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/id-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/id.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/id.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/id.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/idref-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idref-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idref.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idref.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idref.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/idrefs.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/inheritance-map-load.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/inheritance-map.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/inheritance-map.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/inheritance-map.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/int.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/int.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/language-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/language-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/language.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/language.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/language.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/long-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/long-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/long.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/long.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/name-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/name-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/name.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/name.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/name.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/ncname-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/ncname-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/ncname.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/ncname.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/ncname.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/negative-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/negative-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtoken-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtoken-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtoken.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtoken.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtoken.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/nmtokens.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/non-negative-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/non-negative-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/non-positive-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/non-positive-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/normalized-string-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/normalized-string-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/normalized-string.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/normalized-string.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/normalized-string.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/positive-integer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/positive-integer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname-stl.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/qname.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/serializer.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/serializer.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/serializer.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/short.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/short.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/string-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/string-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/string.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/string.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/string.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/time-zone.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/time-zone.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/time-zone.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/time.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/time.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/time.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/token-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/token-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/token.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/token.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/token.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-byte.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-byte.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-int.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-int.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-long-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-long-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-long.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-long.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-short.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/unsigned-short.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/uri-stl.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/uri-stl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/uri.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/uri.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/uri.ixx create mode 100644 libxsde/xsde/cxx/serializer/validating/xml-schema-simpl.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.cxx create mode 100644 libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.hxx create mode 100644 libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.ixx create mode 100644 libxsde/xsde/cxx/serializer/xml-schema.hxx create mode 100644 libxsde/xsde/cxx/strdupx.cxx create mode 100644 libxsde/xsde/cxx/strdupx.hxx create mode 100644 libxsde/xsde/cxx/string-sequence-stl.cxx create mode 100644 libxsde/xsde/cxx/string-sequence-stl.hxx create mode 100644 libxsde/xsde/cxx/string-sequence-stl.ixx create mode 100644 libxsde/xsde/cxx/string-sequence.cxx create mode 100644 libxsde/xsde/cxx/string-sequence.hxx create mode 100644 libxsde/xsde/cxx/string-sequence.ixx create mode 100644 libxsde/xsde/cxx/string.cxx create mode 100644 libxsde/xsde/cxx/string.hxx create mode 100644 libxsde/xsde/cxx/string.ixx create mode 100644 libxsde/xsde/cxx/sys-error.cxx create mode 100644 libxsde/xsde/cxx/sys-error.hxx create mode 100644 libxsde/xsde/cxx/sys-error.ixx create mode 100644 libxsde/xsde/cxx/version.hxx create mode 100644 libxsde/xsde/cxx/xml/char-table.cxx create mode 100644 libxsde/xsde/cxx/xml/char-table.hxx create mode 100644 libxsde/xsde/cxx/xml/ncname.cxx create mode 100644 libxsde/xsde/cxx/xml/ncname.hxx create mode 100644 libxsde/xsde/makefile create mode 100644 makefile create mode 100644 tests/cxx/hashmap/driver.cxx create mode 100644 tests/cxx/hashmap/makefile create mode 100644 tests/cxx/hashmap/output create mode 100644 tests/cxx/hybrid/built-in/driver.cxx create mode 100644 tests/cxx/hybrid/built-in/makefile create mode 100644 tests/cxx/hybrid/built-in/output create mode 100644 tests/cxx/hybrid/built-in/test.xml create mode 100644 tests/cxx/hybrid/built-in/test.xsd create mode 100644 tests/cxx/hybrid/choice/driver.cxx create mode 100644 tests/cxx/hybrid/choice/makefile create mode 100644 tests/cxx/hybrid/choice/output create mode 100644 tests/cxx/hybrid/choice/test.xml create mode 100644 tests/cxx/hybrid/choice/test.xsd create mode 100644 tests/cxx/hybrid/compositor/includee.xsd create mode 100644 tests/cxx/hybrid/compositor/includer.xsd create mode 100644 tests/cxx/hybrid/compositor/test.xsd create mode 100644 tests/cxx/hybrid/compositor/tmp.xsd create mode 100644 tests/cxx/hybrid/file-per-type/a.xsd create mode 100644 tests/cxx/hybrid/file-per-type/b.xsd create mode 100644 tests/cxx/hybrid/file-per-type/test.xsd create mode 100644 tests/cxx/hybrid/list/driver.cxx create mode 100644 tests/cxx/hybrid/list/makefile create mode 100644 tests/cxx/hybrid/list/output create mode 100644 tests/cxx/hybrid/list/test.xml create mode 100644 tests/cxx/hybrid/list/test.xsd create mode 100644 tests/cxx/hybrid/makefile create mode 100644 tests/cxx/hybrid/reorder/test.xsd create mode 100644 tests/cxx/hybrid/sequences/driver.cxx create mode 100644 tests/cxx/hybrid/sequences/makefile create mode 100644 tests/cxx/hybrid/size/test.xsd create mode 100644 tests/cxx/hybrid/test-template/driver.cxx create mode 100644 tests/cxx/hybrid/test-template/makefile create mode 100644 tests/cxx/hybrid/test-template/output create mode 100644 tests/cxx/hybrid/test-template/test.xml create mode 100644 tests/cxx/hybrid/test-template/test.xsd create mode 100644 tests/cxx/hybrid/union/driver.cxx create mode 100644 tests/cxx/hybrid/union/makefile create mode 100644 tests/cxx/hybrid/union/output create mode 100644 tests/cxx/hybrid/union/test.xml create mode 100644 tests/cxx/hybrid/union/test.xsd create mode 100644 tests/cxx/makefile create mode 100644 tests/cxx/parser/built-in/driver.cxx create mode 100644 tests/cxx/parser/built-in/makefile create mode 100644 tests/cxx/parser/built-in/output-long create mode 100644 tests/cxx/parser/built-in/output-long-long create mode 100644 tests/cxx/parser/built-in/test-long-long.xml create mode 100644 tests/cxx/parser/built-in/test-long.xml create mode 100644 tests/cxx/parser/built-in/test.xsd create mode 100644 tests/cxx/parser/duplicate/makefile create mode 100644 tests/cxx/parser/duplicate/output create mode 100644 tests/cxx/parser/duplicate/test.xml create mode 100644 tests/cxx/parser/duplicate/test.xsd create mode 100644 tests/cxx/parser/enumeration/driver.cxx create mode 100644 tests/cxx/parser/enumeration/gender.hxx create mode 100644 tests/cxx/parser/enumeration/makefile create mode 100644 tests/cxx/parser/enumeration/output create mode 100644 tests/cxx/parser/enumeration/test.map create mode 100644 tests/cxx/parser/enumeration/test.xml create mode 100644 tests/cxx/parser/enumeration/test.xsd create mode 100644 tests/cxx/parser/error-handling/codes/driver.cxx create mode 100644 tests/cxx/parser/error-handling/codes/makefile create mode 100644 tests/cxx/parser/error-handling/codes/output create mode 100644 tests/cxx/parser/error-handling/codes/test.map create mode 100644 tests/cxx/parser/error-handling/codes/test.xml create mode 100644 tests/cxx/parser/error-handling/codes/test.xsd create mode 100644 tests/cxx/parser/error-handling/exceptions/driver.cxx create mode 100644 tests/cxx/parser/error-handling/exceptions/makefile create mode 100644 tests/cxx/parser/error-handling/exceptions/output create mode 100644 tests/cxx/parser/error-handling/exceptions/test.map create mode 100644 tests/cxx/parser/error-handling/exceptions/test.xml create mode 100644 tests/cxx/parser/error-handling/exceptions/test.xsd create mode 100644 tests/cxx/parser/error-handling/makefile create mode 100644 tests/cxx/parser/generated-impl/makefile create mode 100644 tests/cxx/parser/generated-impl/output create mode 100644 tests/cxx/parser/generated-impl/test.xml create mode 100644 tests/cxx/parser/generated-impl/test.xsd create mode 100644 tests/cxx/parser/list/driver.cxx create mode 100644 tests/cxx/parser/list/makefile create mode 100644 tests/cxx/parser/list/output create mode 100644 tests/cxx/parser/list/test.xml create mode 100644 tests/cxx/parser/list/test.xsd create mode 100644 tests/cxx/parser/makefile create mode 100644 tests/cxx/parser/name-clash/inheritance/driver.cxx create mode 100644 tests/cxx/parser/name-clash/inheritance/makefile create mode 100644 tests/cxx/parser/name-clash/inheritance/output create mode 100644 tests/cxx/parser/name-clash/inheritance/test.xml create mode 100644 tests/cxx/parser/name-clash/inheritance/test.xsd create mode 100644 tests/cxx/parser/polymorphism/driver.cxx create mode 100644 tests/cxx/parser/polymorphism/makefile create mode 100644 tests/cxx/parser/polymorphism/output create mode 100644 tests/cxx/parser/polymorphism/test.xml create mode 100644 tests/cxx/parser/polymorphism/test.xsd create mode 100644 tests/cxx/parser/recursive/driver.cxx create mode 100644 tests/cxx/parser/recursive/makefile create mode 100644 tests/cxx/parser/recursive/output create mode 100644 tests/cxx/parser/recursive/test.xml create mode 100644 tests/cxx/parser/recursive/test.xsd create mode 100644 tests/cxx/parser/reset/driver.cxx create mode 100644 tests/cxx/parser/reset/fail-schema.xml create mode 100644 tests/cxx/parser/reset/fail-xml.xml create mode 100644 tests/cxx/parser/reset/makefile create mode 100644 tests/cxx/parser/reset/output create mode 100644 tests/cxx/parser/reset/pass.xml create mode 100644 tests/cxx/parser/reset/test.xsd create mode 100644 tests/cxx/parser/test-template/driver.cxx create mode 100644 tests/cxx/parser/test-template/makefile create mode 100644 tests/cxx/parser/test-template/output create mode 100644 tests/cxx/parser/test-template/test.xml create mode 100644 tests/cxx/parser/test-template/test.xsd create mode 100644 tests/cxx/parser/union/driver.cxx create mode 100644 tests/cxx/parser/union/makefile create mode 100644 tests/cxx/parser/union/output create mode 100644 tests/cxx/parser/union/test.xml create mode 100644 tests/cxx/parser/union/test.xsd create mode 100644 tests/cxx/parser/validation/all/driver.cxx create mode 100644 tests/cxx/parser/validation/all/makefile create mode 100644 tests/cxx/parser/validation/all/test-000.std create mode 100644 tests/cxx/parser/validation/all/test-000.xml create mode 100644 tests/cxx/parser/validation/all/test-001.std create mode 100644 tests/cxx/parser/validation/all/test-001.xml create mode 100644 tests/cxx/parser/validation/all/test-002.std create mode 100644 tests/cxx/parser/validation/all/test-002.xml create mode 100644 tests/cxx/parser/validation/all/test-003.std create mode 100644 tests/cxx/parser/validation/all/test-003.xml create mode 100644 tests/cxx/parser/validation/all/test.xsd create mode 100644 tests/cxx/parser/validation/any/driver.cxx create mode 100644 tests/cxx/parser/validation/any/makefile create mode 100644 tests/cxx/parser/validation/any/test-000.std create mode 100644 tests/cxx/parser/validation/any/test-000.xml create mode 100644 tests/cxx/parser/validation/any/test.xsd create mode 100644 tests/cxx/parser/validation/attribute/driver.cxx create mode 100644 tests/cxx/parser/validation/attribute/makefile create mode 100644 tests/cxx/parser/validation/attribute/output create mode 100644 tests/cxx/parser/validation/attribute/test.xml create mode 100644 tests/cxx/parser/validation/attribute/test.xsd create mode 100644 tests/cxx/parser/validation/built-in/any-type/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/any-type/makefile create mode 100644 tests/cxx/parser/validation/built-in/any-type/test-000.std create mode 100644 tests/cxx/parser/validation/built-in/any-type/test-000.xml create mode 100644 tests/cxx/parser/validation/built-in/any-type/test.xsd create mode 100644 tests/cxx/parser/validation/built-in/binary/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/binary/makefile create mode 100644 tests/cxx/parser/validation/built-in/boolean/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/boolean/makefile create mode 100644 tests/cxx/parser/validation/built-in/byte/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/byte/makefile create mode 100644 tests/cxx/parser/validation/built-in/date-time/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/date-time/makefile create mode 100644 tests/cxx/parser/validation/built-in/float/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/float/makefile create mode 100644 tests/cxx/parser/validation/built-in/int/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/int/makefile create mode 100644 tests/cxx/parser/validation/built-in/integer/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/integer/makefile create mode 100644 tests/cxx/parser/validation/built-in/long-long/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/long-long/makefile create mode 100644 tests/cxx/parser/validation/built-in/long/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/long/makefile create mode 100644 tests/cxx/parser/validation/built-in/makefile create mode 100644 tests/cxx/parser/validation/built-in/qname/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/qname/makefile create mode 100644 tests/cxx/parser/validation/built-in/short/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/short/makefile create mode 100644 tests/cxx/parser/validation/built-in/string/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/string/makefile create mode 100644 tests/cxx/parser/validation/built-in/uri/driver.cxx create mode 100644 tests/cxx/parser/validation/built-in/uri/makefile create mode 100644 tests/cxx/parser/validation/choice/driver.cxx create mode 100644 tests/cxx/parser/validation/choice/makefile create mode 100644 tests/cxx/parser/validation/choice/test-000.std create mode 100644 tests/cxx/parser/validation/choice/test-000.xml create mode 100644 tests/cxx/parser/validation/choice/test-001.std create mode 100644 tests/cxx/parser/validation/choice/test-001.xml create mode 100644 tests/cxx/parser/validation/choice/test-002.std create mode 100644 tests/cxx/parser/validation/choice/test-002.xml create mode 100644 tests/cxx/parser/validation/choice/test-003.std create mode 100644 tests/cxx/parser/validation/choice/test-003.xml create mode 100644 tests/cxx/parser/validation/choice/test-004.std create mode 100644 tests/cxx/parser/validation/choice/test-004.xml create mode 100644 tests/cxx/parser/validation/choice/test.xsd create mode 100644 tests/cxx/parser/validation/makefile create mode 100644 tests/cxx/parser/validation/restriction/driver.cxx create mode 100644 tests/cxx/parser/validation/restriction/makefile create mode 100644 tests/cxx/parser/validation/restriction/test-000.std create mode 100644 tests/cxx/parser/validation/restriction/test-000.xml create mode 100644 tests/cxx/parser/validation/restriction/test-001.std create mode 100644 tests/cxx/parser/validation/restriction/test-001.xml create mode 100644 tests/cxx/parser/validation/restriction/test-002.std create mode 100644 tests/cxx/parser/validation/restriction/test-002.xml create mode 100644 tests/cxx/parser/validation/restriction/test-003.std create mode 100644 tests/cxx/parser/validation/restriction/test-003.xml create mode 100644 tests/cxx/parser/validation/restriction/test-004.std create mode 100644 tests/cxx/parser/validation/restriction/test-004.xml create mode 100644 tests/cxx/parser/validation/restriction/test-005.std create mode 100644 tests/cxx/parser/validation/restriction/test-005.xml create mode 100644 tests/cxx/parser/validation/restriction/test.xsd create mode 100644 tests/cxx/parser/validation/sequence/driver.cxx create mode 100644 tests/cxx/parser/validation/sequence/makefile create mode 100644 tests/cxx/parser/validation/sequence/test-000.std create mode 100644 tests/cxx/parser/validation/sequence/test-000.xml create mode 100644 tests/cxx/parser/validation/sequence/test-001.std create mode 100644 tests/cxx/parser/validation/sequence/test-001.xml create mode 100644 tests/cxx/parser/validation/sequence/test-002.std create mode 100644 tests/cxx/parser/validation/sequence/test-002.xml create mode 100644 tests/cxx/parser/validation/sequence/test-003.std create mode 100644 tests/cxx/parser/validation/sequence/test-003.xml create mode 100644 tests/cxx/parser/validation/sequence/test-004.std create mode 100644 tests/cxx/parser/validation/sequence/test-004.xml create mode 100644 tests/cxx/parser/validation/sequence/test-005.std create mode 100644 tests/cxx/parser/validation/sequence/test-005.xml create mode 100644 tests/cxx/parser/validation/sequence/test-006.std create mode 100644 tests/cxx/parser/validation/sequence/test-006.xml create mode 100644 tests/cxx/parser/validation/sequence/test.xsd create mode 100644 tests/cxx/serializer/all/driver.cxx create mode 100644 tests/cxx/serializer/all/makefile create mode 100644 tests/cxx/serializer/all/output create mode 100644 tests/cxx/serializer/all/test.xsd create mode 100644 tests/cxx/serializer/built-in/driver.cxx create mode 100644 tests/cxx/serializer/built-in/makefile create mode 100644 tests/cxx/serializer/built-in/output-long create mode 100644 tests/cxx/serializer/built-in/output-long-long create mode 100644 tests/cxx/serializer/built-in/test.xsd create mode 100644 tests/cxx/serializer/choice/driver.cxx create mode 100644 tests/cxx/serializer/choice/makefile create mode 100644 tests/cxx/serializer/choice/output create mode 100644 tests/cxx/serializer/choice/test.xsd create mode 100644 tests/cxx/serializer/complex/driver.cxx create mode 100644 tests/cxx/serializer/complex/makefile create mode 100644 tests/cxx/serializer/complex/output create mode 100644 tests/cxx/serializer/complex/test.xsd create mode 100644 tests/cxx/serializer/enumeration/boolean.hxx create mode 100644 tests/cxx/serializer/enumeration/driver.cxx create mode 100644 tests/cxx/serializer/enumeration/makefile create mode 100644 tests/cxx/serializer/enumeration/output create mode 100644 tests/cxx/serializer/enumeration/test.map create mode 100644 tests/cxx/serializer/enumeration/test.xsd create mode 100644 tests/cxx/serializer/error-handling/codes/driver.cxx create mode 100644 tests/cxx/serializer/error-handling/codes/makefile create mode 100644 tests/cxx/serializer/error-handling/codes/output create mode 100644 tests/cxx/serializer/error-handling/codes/test.xsd create mode 100644 tests/cxx/serializer/error-handling/exceptions/driver.cxx create mode 100644 tests/cxx/serializer/error-handling/exceptions/makefile create mode 100644 tests/cxx/serializer/error-handling/exceptions/output create mode 100644 tests/cxx/serializer/error-handling/exceptions/test.xsd create mode 100644 tests/cxx/serializer/error-handling/makefile create mode 100644 tests/cxx/serializer/generated-driver/makefile create mode 100644 tests/cxx/serializer/generated-driver/output create mode 100644 tests/cxx/serializer/generated-driver/test-simpl.cxx create mode 100644 tests/cxx/serializer/generated-driver/test-simpl.hxx create mode 100644 tests/cxx/serializer/generated-driver/test.xsd create mode 100644 tests/cxx/serializer/generated-impl/makefile create mode 100644 tests/cxx/serializer/generated-impl/test.xsd create mode 100644 tests/cxx/serializer/list/driver.cxx create mode 100644 tests/cxx/serializer/list/makefile create mode 100644 tests/cxx/serializer/list/output create mode 100644 tests/cxx/serializer/list/test.xsd create mode 100644 tests/cxx/serializer/makefile create mode 100644 tests/cxx/serializer/polymorphism/driver.cxx create mode 100644 tests/cxx/serializer/polymorphism/makefile create mode 100644 tests/cxx/serializer/polymorphism/output create mode 100644 tests/cxx/serializer/polymorphism/test.xsd create mode 100644 tests/cxx/serializer/recursive/driver.cxx create mode 100644 tests/cxx/serializer/recursive/makefile create mode 100644 tests/cxx/serializer/recursive/output create mode 100644 tests/cxx/serializer/recursive/test.xsd create mode 100644 tests/cxx/serializer/reset/driver.cxx create mode 100644 tests/cxx/serializer/reset/makefile create mode 100644 tests/cxx/serializer/reset/output create mode 100644 tests/cxx/serializer/reset/test.xsd create mode 100644 tests/cxx/serializer/restriction/driver.cxx create mode 100644 tests/cxx/serializer/restriction/makefile create mode 100644 tests/cxx/serializer/restriction/output create mode 100644 tests/cxx/serializer/restriction/test.xsd create mode 100644 tests/cxx/serializer/sequence/driver.cxx create mode 100644 tests/cxx/serializer/sequence/makefile create mode 100644 tests/cxx/serializer/sequence/output create mode 100644 tests/cxx/serializer/sequence/test.xsd create mode 100644 tests/cxx/serializer/test-template/driver.cxx create mode 100644 tests/cxx/serializer/test-template/makefile create mode 100644 tests/cxx/serializer/test-template/output create mode 100644 tests/cxx/serializer/test-template/test.xsd create mode 100644 tests/cxx/serializer/union/driver.cxx create mode 100644 tests/cxx/serializer/union/makefile create mode 100644 tests/cxx/serializer/union/output create mode 100644 tests/cxx/serializer/union/test.xsd create mode 100644 tests/cxx/serializer/validation/any/driver.cxx create mode 100644 tests/cxx/serializer/validation/any/makefile create mode 100644 tests/cxx/serializer/validation/any/output create mode 100644 tests/cxx/serializer/validation/any/test.xsd create mode 100644 tests/cxx/serializer/validation/attribute/driver.cxx create mode 100644 tests/cxx/serializer/validation/attribute/makefile create mode 100644 tests/cxx/serializer/validation/attribute/output create mode 100644 tests/cxx/serializer/validation/attribute/test.xsd create mode 100644 tests/cxx/serializer/validation/built-in/date-time/driver.cxx create mode 100644 tests/cxx/serializer/validation/built-in/date-time/makefile create mode 100644 tests/cxx/serializer/validation/built-in/decimal/driver.cxx create mode 100644 tests/cxx/serializer/validation/built-in/decimal/makefile create mode 100644 tests/cxx/serializer/validation/built-in/integer/driver.cxx create mode 100644 tests/cxx/serializer/validation/built-in/integer/makefile create mode 100644 tests/cxx/serializer/validation/built-in/makefile create mode 100644 tests/cxx/serializer/validation/built-in/qname/driver.cxx create mode 100644 tests/cxx/serializer/validation/built-in/qname/makefile create mode 100644 tests/cxx/serializer/validation/built-in/string/driver.cxx create mode 100644 tests/cxx/serializer/validation/built-in/string/makefile create mode 100644 tests/cxx/serializer/validation/choice/driver.cxx create mode 100644 tests/cxx/serializer/validation/choice/makefile create mode 100644 tests/cxx/serializer/validation/choice/output create mode 100644 tests/cxx/serializer/validation/choice/test.xsd create mode 100644 tests/cxx/serializer/validation/element/driver.cxx create mode 100644 tests/cxx/serializer/validation/element/makefile create mode 100644 tests/cxx/serializer/validation/element/output create mode 100644 tests/cxx/serializer/validation/element/test.xsd create mode 100644 tests/cxx/serializer/validation/makefile create mode 100644 tests/cxx/serializer/validation/sequence/driver.cxx create mode 100644 tests/cxx/serializer/validation/sequence/makefile create mode 100644 tests/cxx/serializer/validation/sequence/output create mode 100644 tests/cxx/serializer/validation/sequence/test.xsd create mode 100644 tests/cxx/serializer/wildcard/driver.cxx create mode 100644 tests/cxx/serializer/wildcard/makefile create mode 100644 tests/cxx/serializer/wildcard/output create mode 100644 tests/cxx/serializer/wildcard/test.xsd create mode 100644 tests/cxx/string/driver.cxx create mode 100644 tests/cxx/string/makefile create mode 100644 tests/makefile create mode 100644 tests/type-map/driver.cxx create mode 100644 version create mode 100644 xsde/cxx/elements.cxx create mode 100644 xsde/cxx/elements.hxx create mode 100644 xsde/cxx/hybrid/cli.hxx create mode 100644 xsde/cxx/hybrid/elements.cxx create mode 100644 xsde/cxx/hybrid/elements.hxx create mode 100644 xsde/cxx/hybrid/generator.cxx create mode 100644 xsde/cxx/hybrid/generator.hxx create mode 100644 xsde/cxx/hybrid/parser-aggregate-header.cxx create mode 100644 xsde/cxx/hybrid/parser-aggregate-header.hxx create mode 100644 xsde/cxx/hybrid/parser-aggregate-source.cxx create mode 100644 xsde/cxx/hybrid/parser-aggregate-source.hxx create mode 100644 xsde/cxx/hybrid/parser-header.cxx create mode 100644 xsde/cxx/hybrid/parser-header.hxx create mode 100644 xsde/cxx/hybrid/parser-name-processor.cxx create mode 100644 xsde/cxx/hybrid/parser-name-processor.hxx create mode 100644 xsde/cxx/hybrid/parser-source.cxx create mode 100644 xsde/cxx/hybrid/parser-source.hxx create mode 100644 xsde/cxx/hybrid/serializer-aggregate-header.cxx create mode 100644 xsde/cxx/hybrid/serializer-aggregate-header.hxx create mode 100644 xsde/cxx/hybrid/serializer-aggregate-source.cxx create mode 100644 xsde/cxx/hybrid/serializer-aggregate-source.hxx create mode 100644 xsde/cxx/hybrid/serializer-header.cxx create mode 100644 xsde/cxx/hybrid/serializer-header.hxx create mode 100644 xsde/cxx/hybrid/serializer-name-processor.cxx create mode 100644 xsde/cxx/hybrid/serializer-name-processor.hxx create mode 100644 xsde/cxx/hybrid/serializer-source.cxx create mode 100644 xsde/cxx/hybrid/serializer-source.hxx create mode 100644 xsde/cxx/hybrid/tree-forward.cxx create mode 100644 xsde/cxx/hybrid/tree-forward.hxx create mode 100644 xsde/cxx/hybrid/tree-header.cxx create mode 100644 xsde/cxx/hybrid/tree-header.hxx create mode 100644 xsde/cxx/hybrid/tree-inline.cxx create mode 100644 xsde/cxx/hybrid/tree-inline.hxx create mode 100644 xsde/cxx/hybrid/tree-name-processor.cxx create mode 100644 xsde/cxx/hybrid/tree-name-processor.hxx create mode 100644 xsde/cxx/hybrid/tree-size-processor.cxx create mode 100644 xsde/cxx/hybrid/tree-size-processor.hxx create mode 100644 xsde/cxx/hybrid/tree-source.cxx create mode 100644 xsde/cxx/hybrid/tree-source.hxx create mode 100644 xsde/cxx/hybrid/tree-type-map.cxx create mode 100644 xsde/cxx/hybrid/tree-type-map.hxx create mode 100644 xsde/cxx/hybrid/validator.cxx create mode 100644 xsde/cxx/hybrid/validator.hxx create mode 100644 xsde/cxx/parser/attribute-validation-source.cxx create mode 100644 xsde/cxx/parser/attribute-validation-source.hxx create mode 100644 xsde/cxx/parser/characters-validation-source.cxx create mode 100644 xsde/cxx/parser/characters-validation-source.hxx create mode 100644 xsde/cxx/parser/cli.hxx create mode 100644 xsde/cxx/parser/driver-source.cxx create mode 100644 xsde/cxx/parser/driver-source.hxx create mode 100644 xsde/cxx/parser/element-validation-source.cxx create mode 100644 xsde/cxx/parser/element-validation-source.hxx create mode 100644 xsde/cxx/parser/elements.cxx create mode 100644 xsde/cxx/parser/elements.hxx create mode 100644 xsde/cxx/parser/generator.cxx create mode 100644 xsde/cxx/parser/generator.hxx create mode 100644 xsde/cxx/parser/impl-header.cxx create mode 100644 xsde/cxx/parser/impl-header.hxx create mode 100644 xsde/cxx/parser/impl-source.cxx create mode 100644 xsde/cxx/parser/impl-source.hxx create mode 100644 xsde/cxx/parser/name-processor.cxx create mode 100644 xsde/cxx/parser/name-processor.hxx create mode 100644 xsde/cxx/parser/parser-forward.cxx create mode 100644 xsde/cxx/parser/parser-forward.hxx create mode 100644 xsde/cxx/parser/parser-header.cxx create mode 100644 xsde/cxx/parser/parser-header.hxx create mode 100644 xsde/cxx/parser/parser-inline.cxx create mode 100644 xsde/cxx/parser/parser-inline.hxx create mode 100644 xsde/cxx/parser/parser-source.cxx create mode 100644 xsde/cxx/parser/parser-source.hxx create mode 100644 xsde/cxx/parser/print-impl-common.hxx create mode 100644 xsde/cxx/parser/state-processor.cxx create mode 100644 xsde/cxx/parser/state-processor.hxx create mode 100644 xsde/cxx/parser/type-processor.cxx create mode 100644 xsde/cxx/parser/type-processor.hxx create mode 100644 xsde/cxx/parser/validator.cxx create mode 100644 xsde/cxx/parser/validator.hxx create mode 100644 xsde/cxx/serializer/attribute-validation-source.cxx create mode 100644 xsde/cxx/serializer/attribute-validation-source.hxx create mode 100644 xsde/cxx/serializer/cli.hxx create mode 100644 xsde/cxx/serializer/driver-source.cxx create mode 100644 xsde/cxx/serializer/driver-source.hxx create mode 100644 xsde/cxx/serializer/element-validation-source.cxx create mode 100644 xsde/cxx/serializer/element-validation-source.hxx create mode 100644 xsde/cxx/serializer/elements.cxx create mode 100644 xsde/cxx/serializer/elements.hxx create mode 100644 xsde/cxx/serializer/generator.cxx create mode 100644 xsde/cxx/serializer/generator.hxx create mode 100644 xsde/cxx/serializer/impl-header.cxx create mode 100644 xsde/cxx/serializer/impl-header.hxx create mode 100644 xsde/cxx/serializer/impl-source.cxx create mode 100644 xsde/cxx/serializer/impl-source.hxx create mode 100644 xsde/cxx/serializer/name-processor.cxx create mode 100644 xsde/cxx/serializer/name-processor.hxx create mode 100644 xsde/cxx/serializer/serializer-forward.cxx create mode 100644 xsde/cxx/serializer/serializer-forward.hxx create mode 100644 xsde/cxx/serializer/serializer-header.cxx create mode 100644 xsde/cxx/serializer/serializer-header.hxx create mode 100644 xsde/cxx/serializer/serializer-inline.cxx create mode 100644 xsde/cxx/serializer/serializer-inline.hxx create mode 100644 xsde/cxx/serializer/serializer-source.cxx create mode 100644 xsde/cxx/serializer/serializer-source.hxx create mode 100644 xsde/cxx/serializer/type-processor.cxx create mode 100644 xsde/cxx/serializer/type-processor.hxx create mode 100644 xsde/cxx/serializer/validator.cxx create mode 100644 xsde/cxx/serializer/validator.hxx create mode 100644 xsde/elements.hxx create mode 100644 xsde/makefile create mode 100644 xsde/processing/inheritance/processor.cxx create mode 100644 xsde/processing/inheritance/processor.hxx create mode 100644 xsde/type-map/lexer.cxx create mode 100644 xsde/type-map/lexer.hxx create mode 100644 xsde/type-map/parser.cxx create mode 100644 xsde/type-map/parser.hxx create mode 100644 xsde/type-map/type-map.hxx create mode 100644 xsde/usage.hxx create mode 100644 xsde/xsde.cxx create mode 100644 xsde/xsde.hxx diff --git a/GPLv2 b/GPLv2 new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/GPLv2 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..30df056 --- /dev/null +++ b/INSTALL @@ -0,0 +1,35 @@ +Compiler Prerequisites + + build-time: + + - build >= 0.3.2 http://kolpackov.net/projects/build/ + - g++ >= 3.4.3 http://gcc.gnu.org + + run-time: + + - libxsd-frontend >= 1.16.0 http://codesynthesis.com/projects/libxsd-frontend/ + - libbackend-elements >= 1.7.0 http://kolpackov.net/projects/libbackend-elements/ + - libcult >= 1.4.3 http://kolpackov.net/projects/libcult/ + - libboost_filesystem >= 1.33.1 http://boost.org + - libboost_regex >= 1.33.1 http://boost.org + +Generated Code Prerequisites + + run-time: + + - libxsde (XSD/e runtime library, part of the XSD/e distribution) + + +Building XSD/e + + To build in the source directory simply run 'make'. You can also + build in a separate directory, e.g., + + $ mkdir xsde-i686-pc-linux-gnu + $ cd xsde-i686-pc-linux-gnu + $ make -f ../xsde-x.y.z/makefile + + +Installing XSD/e + + Not supported in this version. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ed9c55c --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..cb3d35b --- /dev/null +++ b/NEWS @@ -0,0 +1,227 @@ +Version 3.0.0 + + * The new Embedded C++/Hybrid mapping provides a light-weight, tree- + like object model with precise reproduction of the XML vocabulary + structure and element order. C++/Hybrid supports fully in-memory + as well as hybrid, partially event-driven, partially in-memory + XML processing. For more information on the new mapping see the + Embedded C++/Hybrid Mapping Getting Started Guide and examples in + the examples/cxx/hybrid/ directory. + + * New option, --disable-warning, disables printing of a warning with + the specified id. Specifying 'all' for the warning id disables all + warnings. + + * The interfaces of the non-STL versions of the xml_schema::qname and + xml_schema::string_sequence classes have changed. Now by default + their modifier functions assume ownership of the passed strings. + The *_copy() versions of the modifier functions that make copies + of the passed strings are now provided. See the documentation for + details. + + * The implementation of the STL version of the xml_schema::string_sequence + class has changed. Now a custom implementation of the sequence + container is used instead of std::vector. See the documentation for + details. + + * When STL is enabled the xml_schema::string_sequence objects + corresponding to the NMTOKENS and IDREFS types are now returned and + passed by pointer rather than by value. + +Version 2.1.0 + + * New delegation-based parser/serializer implementation reuse style in + addition to virtual inheritance-based. The new style results in a much + smaller object code size. The new reuse style is used by default and is + incompatible with the old style. Applications that require backwards + compatibility should use the --reuse-style-mixin option. The reuse + support code now can be completely omitted with the --reuse-style-none + option. A number of examples were converted to support both the new + and old reuse styles while others were converted to support the new + style only. For more information on the new reuse style see Section + 5.6 in the Embedded C++/Parser Getting Started Guide and Section 6.6 + in the Embedded C++/Serializer Getting Started Guide. + + * New option, --file-per-type, triggers generation of a separate set + of C++ files for each type defined in XML Schema. This compilation + mode is primarily useful when some of your schemas cannot be compiled + separately or have cyclic dependencies which involve inheritance. + Other new options that are useful in this compilation mode are + --type-file-regex, --type-file-regex-trace, and --file-list. See the + compiler command line manual (man pages) for more information. + + * New option, --options-file, allows additional command line options + to be provided in files, with one option per line. + + * New option, --reserved-name, allows inserting additional names with + optional replacements to the list of names that should not be used + as identifiers. See the compiler command line manual (man pages) + for details. + + * New options, --location-map, --location-regex, and + --location-regex-trace, allow re-mapping of schema locations + specified in the include and import elements without modifying the + schema files. See the compiler command line manual (man pages) for + more information. + + * New option, --guard-prefix, allows specifying a prefix that will be + added to generated header inclusion guards. + + * New option, --file-list, triggers creation of a file with a list of + generated C++ files. This option is primarily useful in the file-per- + type compilation mode (--file-per-type) to create a list of generated + C++ files, for example, as a makefile fragment. Other new options + that are useful with --file-list are --file-list-prologue, + --file-list-epilogue, and --file-list-delim. See the compiler command + line manual (man pages) for more information. + + * In type map files the optional argument type now defaults to the + return type if the return type ends with * or & (that is, it is + a pointer or a reference) and 'const return type&' otherwise. + + * Type map files can now include comments. A comment starts with # + and ends with a new line or end of file. To specify a name that + contains # enclose it in "". + + C++/Parser + + * New option, --generate-polymorphic, triggers generation of polymorphism- + aware code. This option should be used on XML vocabularies which use + xsi:type and/or substitution groups. For more information see Section + 5.7, "Support for Polymorphism" in the Embedded C++/Parser Mapping + Getting Started Guide we well as the polymorphism and polyroot + examples in the examples/cxx/parser/ directory. + + * New options, --generate-xml-schema and --extern-xml-schema, trigger + generation of the mapping for the XML Schema namespace to a separate + header file and inclusion of that header into other generated header + files instead of generating the necessary declarations inline, + respectively. See the the compiler command line manual (man pages) + for details. + + * Support for parser reuse after an error. For more information refer + to Section 7.4, "Reusing Parsers after an Error" in the Embedded + C++/Parser Mapping Getting Started Guide. To suppress generation + of the reset code use the --suppress-reset option. + + * New, context-based internal parsing architecture which provides + better performance, especially for deeply-nested documents. This + change should not affect user code except for wildcard parsing. + See the wildcard example for the required changes. + + * The generated sample test driver file name was changed from + -driver.cxx to -pdriver.cxx. + + C++/Serializer + + * The mapping now supports automatic generation of sample serializer + implementations and a test driver. The --generate-empty-impl option + triggers generation of a sample implementation with empty function + bodies which can then be filled with application code. The + --generate-test-driver option trigger generation of a test driver. + For more information on this feature see the compiler command line + manual (man pages). Other relevant new options include: + --impl-file-suffix, --force-overwrite, --root-element-first, + --root-element-last, and --root-element. + + * New option, --generate-polymorphic, triggers generation of polymorphism- + aware code. This option should be used on XML vocabularies which use + xsi:type and/or substitution groups. For more information see Section + 6.7, "Support for Polymorphism" in the Embedded C++/Serializer Mapping + Getting Started Guide we well as the polymorphism and polyroot + examples in the examples/cxx/serializer/ directory. + + * New options, --generate-xml-schema and --extern-xml-schema, trigger + generation of the mapping for the XML Schema namespace to a separate + header file and inclusion of that header into other generated header + files instead of generating the necessary declarations inline, + respectively. See the the compiler command line manual (man pages) + for details. + + * Support for serializer reuse after an error. For more information + refer to Section 8.4, "Reusing Serializers after an Error" in the + Embedded C++/Serializer Mapping Getting Started Guide. To suppress + generation of the reset code use the --suppress-reset option. + +Version 2.0.0 + + * The new Embedded C++/Serializer mapping supports event-driven, + stream oriented XML serialization with XML Schema validation + and C++ data binding. The new Embedded C++/Serializer Mapping + Getting Started Guide as well as the set of examples provide + an introduction to the mapping. + + C++/Parser + + * The argument order in the generated parsers() functions has + changed from elements then attributes to attributes then + elements. + + * A number of types in the xml_schema namespaces have been + renamed in order to make the C++/Parser and C++/Serializer + mappings usable in the same translation unit. The old and + new names are listed below: + + document document_pimpl + exception parser_exception + xml parser_xml + schema parser_schema + error parser_error + xml_error parser_xml_error + schema_error parser_schema_error + simple_content parser_simple_content + complex_content parser_complex_content + list_base parser_list_base + + * The error accessor function has been renamed from error() + to _error(). The application error modifier function has + been renamed from error(int) to _app_error(int). + + * For each subsequent element with the same name in the same + complex type, the mapping now produces a separate set of + callbacks and accessors. Note that in this case the + generated code will be able to perform correct dispatching + only with XML Schema validation enabled. When validation is + disabled all events will be delivered to the callback + corresponding to the first element with this name. + +Version 1.1.0 + + * The runtime library now provides parser implementations for all + built-in XML Schema types. See Chapter 6, "Built-In XML Schema + Type Parsers" in the Embedded C++/Parser Mapping Getting Started + Guide for more information. + + * The mapping now supports automatic generation of sample parser + implementations and a test driver. The --generate-noop-impl option + triggers generation of a sample implementation with empty function + bodies. The --generate-print-impl option triggers generation of a + sample implementation that prints the data stored in XML to STDOUT. + The --generate-test-driver option trigger generation of a test driver. + For more information on this feature see the compiler command line + manual (man pages) and the generated example in the examples/cxx/parser/ + directory. Other relevant new options include: --force-overwrite, + --root-element-first, --root-element-last, and --root-element. + + * New example, examples/cxx/parser/wildcard, shows how to parse the + XML data matched by XML Schema wildcards (any and anyAttribute). + + * The xml_schema::document parser has been extended with overridable + virtual functions start_root_element and end_root_element to support + parsing of XML vocabularies with multiple document roots. See the + multiroot example in the examples/cxx/parser/ directory for more + information. + + * Declaration for built-in parser implementations and the document + parser are now automatically included into generated header files. + As a result, you do not need to explicitly include the + xml-schema-impl.hxx or document.hxx header files. + + * The default parser skeleton type and file suffixes have changed + from _skel to _pskel and from -skel to -pskel, respectively. The + --type-suffix and --file-suffix options were renamed to + --skel-type-suffix and --skel-file-suffix, respectively. + +Version 1.0.0 + + * First public release. diff --git a/README b/README new file mode 100644 index 0000000..29f3e6e --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +CodeSynthesis XSD/e is an open-source XML parser/serializer +generator for mobile and embedded systems. It provides event- +driven, stream oriented XML parsing, XML serialization, W3C +XML Schema validation, and C++ data binding while maintaining +a small footprint and portability. + +See the NEWS file for the user-visible changes from the previous +release. + +See the LICENSE file for distribution conditions. + +See the INSTALL file for prerequisites and installation instructions. + +See the documentation/ directory for documentation. + +The project page is at http://www.codesynthesis.com/projects/xsde/. + +Send questions, bug reports, or any other feedback to the +xsde-users@codesynthesis.com mailing list. diff --git a/build/bootstrap.make b/build/bootstrap.make new file mode 100644 index 0000000..ad55b12 --- /dev/null +++ b/build/bootstrap.make @@ -0,0 +1,54 @@ +# file : build/bootstrap.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +project_name := XSD/e + +include build-0.3/bootstrap.make + + +# Configuration +# +$(call include,$(scf_root)/configuration.make) + + +# Aliases +# +ifdef %interactive% + +.PHONY: test $(out_base)/.test \ + install $(out_base)/.install \ + clean $(out_base)/.clean + +test: $(out_base)/.test +install: $(out_base)/.install +clean: $(out_base)/.clean + +ifeq ($(.DEFAULT_GOAL),test) +.DEFAULT_GOAL := +endif + +ifeq ($(.DEFAULT_GOAL),install) +.DEFAULT_GOAL := +endif + +ifeq ($(.DEFAULT_GOAL),clean) +.DEFAULT_GOAL := +endif + +endif + + +# Don't include dependency info if we are cleaning. +# +define include-dep +endef + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),disfigure) +define include-dep +$(call -include,$1) +endef +endif +endif diff --git a/build/configuration-rules.make b/build/configuration-rules.make new file mode 100644 index 0000000..3d468c4 --- /dev/null +++ b/build/configuration-rules.make @@ -0,0 +1,18 @@ +# file : build/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(dcf_root)/configuration-dynamic.make: | $(dcf_root)/. + $(call message,,$(scf_root)/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $$1,rm -f $$1,$(dcf_root)/configuration-dynamic.make) + +endif + +ifeq ($(.DEFAULT_GOAL),$(dcf_root)/configuration-dynamic.make) +.DEFAULT_GOAL := +endif diff --git a/build/configuration.make b/build/configuration.make new file mode 100644 index 0000000..6efbbfd --- /dev/null +++ b/build/configuration.make @@ -0,0 +1,54 @@ +# file : build/configuration.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(call include-once,$(scf_root)/configuration-rules.make,$(dcf_root)) + + +# Dynamic configuration. +# +xsde_arch_width := +xsde_byteorder := +xsde_stl := +xsde_iostream := +xsde_exceptions := +xsde_longlong := +xsde_snprintf := +xsde_parser_validation := +xsde_serializer_validation := +xsde_reuse_style := +xsde_polymorphic := +xsde_parser_smap_buckets := +xsde_parser_imap_buckets := +xsde_serializer_smap_buckets := +xsde_serializer_smap_bucket_buckets := +xsde_serializer_imap_buckets := + + +$(call -include,$(dcf_root)/configuration-dynamic.make) + +ifdef xsde_stl + +$(out_root)/%: xsde_arch_width := $(xsde_arch_width) +$(out_root)/%: xsde_byteorder := $(xsde_byteorder) +$(out_root)/%: xsde_stl := $(xsde_stl) +$(out_root)/%: xsde_iostream := $(xsde_iostream) +$(out_root)/%: xsde_exceptions := $(xsde_exceptions) +$(out_root)/%: xsde_longlong := $(xsde_longlong) +$(out_root)/%: xsde_snprintf := $(xsde_snprintf) +$(out_root)/%: xsde_parser_validation := $(xsde_parser_validation) +$(out_root)/%: xsde_serializer_validation := $(xsde_serializer_validation) +$(out_root)/%: xsde_reuse_style := $(xsde_reuse_style) +$(out_root)/%: xsde_polymorphic := $(xsde_polymorphic) +$(out_root)/%: xsde_parser_smap_buckets := $(xsde_parser_smap_buckets) +$(out_root)/%: xsde_parser_imap_buckets := $(xsde_parser_imap_buckets) +$(out_root)/%: xsde_serializer_smap_buckets := $(xsde_serializer_smap_buckets) +$(out_root)/%: xsde_serializer_smap_bucket_buckets := $(xsde_serializer_smap_bucket_buckets) +$(out_root)/%: xsde_serializer_imap_buckets := $(xsde_serializer_imap_buckets) + +else + +.NOTPARALLEL: + +endif diff --git a/build/configure b/build/configure new file mode 100755 index 0000000..d99f1c2 --- /dev/null +++ b/build/configure @@ -0,0 +1,160 @@ +#! /usr/bin/env bash + +# file : build/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +# $1 out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo +$echo "configuring '$project_name'" +$echo +$echo + +$echo +$echo "Please specify your platform architecture width in bits:" +$echo + +arch_width=`read_value 32` + +$echo +$echo "Is your platform little-endian?" +$echo + +little=`read_y_n y` + +if [ "$little" == "y" ]; then + byteorder=l +else + byteorder=b +fi + +$echo +$echo "Would you like the generated code and runtime to use STL?" +$echo + +stl=`read_y_n y` + +$echo +$echo "Would you like the generated code and runtime to use IO streams?" +$echo + +iostream=`read_y_n y` + +$echo +$echo "Would you like the generated code and runtime to use C++ exceptions?" +$echo + +exceptions=`read_y_n y` + +$echo +$echo "Is the long long int type available on your platform?" +$echo + +longlong=`read_y_n y` + +$echo +$echo "Is the snprintf/_snprintf function available on your platform?" +$echo + +snprintf=`read_y_n y` + +$echo +$echo "Would you like the parser runtime to validate against XML Schema?" +$echo + +parser_validation=`read_y_n y` + +$echo +$echo "Would you like the serializer runtime to validate against XML Schema?" +$echo + +serializer_validation=`read_y_n y` + +$echo +$echo "Please select the base parser/serializer reuse style you would" +$echo "like to use:" +$echo +$echo "(1) mixin (virtual inheritance-based reuse)" +$echo "(2) tiein (delegation-based reuse)" +$echo "(3) none (no reuse support)" +$echo + +reuse_style=`read_option "mixin tiein none" "tiein"` + +$echo +$echo "Would you like the runtime library to support XML Schema polymorphism" +$echo "(xsi:type and substitution groups)?" +$echo + +polymorphic=`read_y_n n` + +parser_smap_buckets=0 +parser_imap_buckets=0 +serializer_smap_buckets=0 +serializer_smap_bucket_buckets=0 +serializer_imap_buckets=0 + +if [ "$polymorphic" = "y" ]; then +$echo +$echo "Enter the substitution and inheritance hashmaps bucket counts." +$echo "Prime numbers are recommended: 53 97 193 389 769 1543 3079 6151" +$echo "12289 24593 49157 98317 196613 393241." +$echo + +$echo +$echo "Parser substitution hashmap buckets:" +$echo +parser_smap_buckets=`read_value 53` + +if [ "$parser_validation" = "y" ]; then +$echo +$echo "Parser inheritance hashmap buckets:" +$echo +parser_imap_buckets=`read_value 97` +fi + +$echo +$echo "Serializer substitution hashmap buckets:" +$echo +serializer_smap_buckets=`read_value 53` + +$echo +$echo "Serializer inner substitution hashmap buckets:" +$echo +serializer_smap_bucket_buckets=`read_value 53` + +if [ "$serializer_validation" = "y" ]; then +$echo +$echo "Serializer inheritance hashmap buckets:" +$echo +serializer_imap_buckets=`read_value 97` +fi + +fi + +echo "xsde_arch_width := $arch_width" >$1 +echo "xsde_byteorder := $byteorder" >>$1 +echo "xsde_stl := $stl" >>$1 +echo "xsde_iostream := $iostream" >>$1 +echo "xsde_exceptions := $exceptions" >>$1 +echo "xsde_longlong := $longlong" >>$1 +echo "xsde_snprintf := $snprintf" >>$1 +echo "xsde_parser_validation := $parser_validation" >>$1 +echo "xsde_serializer_validation := $serializer_validation" >>$1 +echo "xsde_reuse_style := $reuse_style" >>$1 +echo "xsde_polymorphic := $polymorphic" >>$1 +echo "xsde_parser_smap_buckets := $parser_smap_buckets" >>$1 +echo "xsde_parser_imap_buckets := $parser_imap_buckets" >>$1 +echo "xsde_serializer_smap_buckets := $serializer_smap_buckets" >>$1 +echo "xsde_serializer_smap_bucket_buckets := $serializer_smap_bucket_buckets" >>$1 +echo "xsde_serializer_imap_buckets := $serializer_imap_buckets" >>$1 diff --git a/build/import/libbackend-elements/LICENSE b/build/import/libbackend-elements/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/build/import/libbackend-elements/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/build/import/libbackend-elements/configuration-rules.make b/build/import/libbackend-elements/configuration-rules.make new file mode 100644 index 0000000..1766f03 --- /dev/null +++ b/build/import/libbackend-elements/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libbackend-elements/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libbackend-elements/configuration-dynamic.make: | $(dcf_root)/import/libbackend-elements/. + $(call message,,$(scf_root)/import/libbackend-elements/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libbackend-elements/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libbackend-elements/configuration-dynamic.make) + +endif diff --git a/build/import/libbackend-elements/configure b/build/import/libbackend-elements/configure new file mode 100755 index 0000000..db3e44d --- /dev/null +++ b/build/import/libbackend-elements/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file : build/import/libbackend-elements/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + + +# $1 - out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libbackend-elements' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed version" +$echo "of 'libbackend-elements' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libbackend-elements'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libbackend-elements'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libbackend_elements_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root >>$1 + +fi diff --git a/build/import/libbackend-elements/stub.make b/build/import/libbackend-elements/stub.make new file mode 100644 index 0000000..4ff210e --- /dev/null +++ b/build/import/libbackend-elements/stub.make @@ -0,0 +1,32 @@ +# file : build/import/libbackend-elements/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libbackend-elements/configuration-rules.make,$(dcf_root)) + +libbackend_elements_installed := + +$(call -include,$(dcf_root)/import/libbackend-elements/configuration-dynamic.make) + +ifdef libbackend_elements_installed + +ifeq ($(libbackend_elements_installed),y) + +#-lbackend-elements + +$(call export,l: ,cpp_options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libbackend-elements/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/import/libboost/LICENSE b/build/import/libboost/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/build/import/libboost/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/build/import/libboost/configuration-rules.make b/build/import/libboost/configuration-rules.make new file mode 100644 index 0000000..2e89c6e --- /dev/null +++ b/build/import/libboost/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libboost/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libboost/configuration-dynamic.make: | $(dcf_root)/import/libboost/. + $(call message,,$(scf_root)/import/libboost/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libboost/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libboost/configuration-dynamic.make) + +endif diff --git a/build/import/libboost/configure b/build/import/libboost/configure new file mode 100755 index 0000000..9bb9085 --- /dev/null +++ b/build/import/libboost/configure @@ -0,0 +1,83 @@ +#! /usr/bin/env bash + +# file : build/import/libboost/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + + +# $1 - out config file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'boost libraries' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed version" +$echo "of 'boost libraries' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= +type= + +if [ "$installed" = "n" ]; then + + version= + + while [ -z "$version" ]; do + + $echo + $echo "Please enter the 'boost' root directory." + $echo + + root=`read_path --directory --exist` + + version=`sed -e 's/^#define BOOST_LIB_VERSION "\(.*\)"[ ]*$/\1/' -e t -e d \ +$root/boost/version.hpp 2>/dev/null` + + if [ $? != 0 -o -z "$version" ]; then + + version= + echo "Unable to read version information from $root/boost/version.hpp" + fi + done + + $echo + $echo "Please select the library type you would like to use:" + $echo + $echo "(1) archive" + $echo "(2) shared object" + $echo + + type=`read_option "archive shared" "shared"` + + $echo + $echo "For boost 1.34.0 and later, please enter the toolset version" + $echo "that is embedded into the library names. For example, for" + $echo "gcc34 enter 34. For previous versions of boost leave this" + $echo "field blank." + $echo + + toolset= + read -e -p "[]: " toolset +fi + +echo libboost_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + + echo libboost_root := $root >>$1 + echo libboost_type := $type >>$1 + echo libboost_version := $version >>$1 + echo libboost_toolset := $toolset >>$1 + +fi diff --git a/build/import/libboost/date-time/rules.make b/build/import/libboost/date-time/rules.make new file mode 100644 index 0000000..f136cc4 --- /dev/null +++ b/build/import/libboost/date-time/rules.make @@ -0,0 +1,39 @@ +# file : build/import/libboost/date-time/rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libboost/%: root := $(libboost_root) + +$(dcf_root)/import/libboost/date-time/date-time.l: \ + | $(dcf_root)/import/libboost/date-time/. + +ifeq ($(libboost_type),archive) + +$(dcf_root)/import/libboost/date-time/date-time.l: \ + $(libboost_root)/stage/lib/libboost_date_time-gcc$(libboost_toolset)-$(libboost_version).a + @echo $< >$@ + +else + +$(dcf_root)/import/libboost/date-time/date-time.l: \ + $(libboost_root)/stage/lib/libboost_date_time-gcc$(libboost_toolset)-$(libboost_version).so + @echo $< >$@ + @echo rpath:$(root)/stage/lib >>$@ + +endif + + +$(dcf_root)/import/libboost/date-time/date-time.l.cpp-options: \ + | $(dcf_root)/import/libboost/date-time/. + @echo include: -I$(root) >$@ + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libboost/date-time/date-time.l,\ +rm -f $(dcf_root)/import/libboost/date-time/date-time.l) + $(call message,,\ +rm -f $(dcf_root)/import/libboost/date-time/date-time.l.cpp-options) + +endif diff --git a/build/import/libboost/date-time/stub.make b/build/import/libboost/date-time/stub.make new file mode 100644 index 0000000..5f57a42 --- /dev/null +++ b/build/import/libboost/date-time/stub.make @@ -0,0 +1,32 @@ +# file : build/import/libboost/date-time/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libboost/configuration-rules.make,$(dcf_root)) + +libboost_installed := + +$(call -include,$(dcf_root)/import/libboost/configuration-dynamic.make) + +ifdef libboost_installed + +ifeq ($(libboost_installed),y) + +$(call export,l: -lboost_date_time,cpp_options: ) + +else + +$(call include-once,$(scf_root)/import/libboost/date-time/rules.make,$(dcf_root)) + +$(call export,\ + l: $(dcf_root)/import/libboost/date-time/date-time.l,\ + cpp-options: $(dcf_root)/import/libboost/date-time/date-time.l.cpp-options) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/import/libboost/filesystem/rules.make b/build/import/libboost/filesystem/rules.make new file mode 100644 index 0000000..8a1666e --- /dev/null +++ b/build/import/libboost/filesystem/rules.make @@ -0,0 +1,41 @@ +# file : build/import/libboost/filesystem/rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +#@@ Should use message everywhere. +# + +$(dcf_root)/import/libboost/%: root := $(libboost_root) + +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ + | $(dcf_root)/import/libboost/filesystem/. + +ifeq ($(libboost_type),archive) + +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ + $(libboost_root)/stage/lib/libboost_filesystem-gcc$(libboost_toolset)-$(libboost_version).a + @echo $< >$@ + +else + +$(dcf_root)/import/libboost/filesystem/filesystem.l: \ + $(libboost_root)/stage/lib/libboost_filesystem-gcc$(libboost_toolset)-$(libboost_version).so + @echo $< >$@ + @echo rpath:$(root)/stage/lib >>$@ + +endif + + +$(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options: \ + | $(dcf_root)/import/libboost/filesystem/. + @echo include: -I$(root) >$@ + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libboost/filesystem/filesystem.l,\ +rm -f $(dcf_root)/import/libboost/filesystem/filesystem.l) + $(call message,,rm -f $(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options) + +endif diff --git a/build/import/libboost/filesystem/stub.make b/build/import/libboost/filesystem/stub.make new file mode 100644 index 0000000..d5e5500 --- /dev/null +++ b/build/import/libboost/filesystem/stub.make @@ -0,0 +1,32 @@ +# file : build/import/libboost/filesystem/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libboost/configuration-rules.make,$(dcf_root)) + +libboost_installed := + +$(call -include,$(dcf_root)/import/libboost/configuration-dynamic.make) + +ifdef libboost_installed + +ifeq ($(libboost_installed),y) + +$(call export,l: -lboost_filesystem,cpp_options: ) + +else + +$(call include-once,$(scf_root)/import/libboost/filesystem/rules.make,$(dcf_root)) + +$(call export,\ + l: $(dcf_root)/import/libboost/filesystem/filesystem.l,\ + cpp-options: $(dcf_root)/import/libboost/filesystem/filesystem.l.cpp-options) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/import/libboost/regex/rules.make b/build/import/libboost/regex/rules.make new file mode 100644 index 0000000..10303be --- /dev/null +++ b/build/import/libboost/regex/rules.make @@ -0,0 +1,38 @@ +# file : build/import/libboost/regex/rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libboost/%: root := $(libboost_root) + +$(dcf_root)/import/libboost/regex/regex.l: \ + | $(dcf_root)/import/libboost/regex/. + +ifeq ($(libboost_type),archive) + +$(dcf_root)/import/libboost/regex/regex.l: \ + $(libboost_root)/stage/lib/libboost_regex-gcc$(libboost_toolset)-$(libboost_version).a + @echo $< >$@ + +else + +$(dcf_root)/import/libboost/regex/regex.l: \ + $(libboost_root)/stage/lib/libboost_regex-gcc$(libboost_toolset)-$(libboost_version).so + @echo $< >$@ + @echo rpath:$(root)/stage/lib >>$@ + +endif + + +$(dcf_root)/import/libboost/regex/regex.l.cpp-options: \ + | $(dcf_root)/import/libboost/regex/. + @echo include: -I$(root) >$@ + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libboost/regex/regex.l,\ +rm -f $(dcf_root)/import/libboost/regex/regex.l) + $(call message,,rm -f $(dcf_root)/import/libboost/regex/regex.l.cpp-options) + +endif diff --git a/build/import/libboost/regex/stub.make b/build/import/libboost/regex/stub.make new file mode 100644 index 0000000..9af79d2 --- /dev/null +++ b/build/import/libboost/regex/stub.make @@ -0,0 +1,32 @@ +# file : build/import/libboost/regex/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libboost/configuration-rules.make,$(dcf_root)) + +libboost_installed := + +$(call -include,$(dcf_root)/import/libboost/configuration-dynamic.make) + +ifdef libboost_installed + +ifeq ($(libboost_installed),y) + +$(call export,l: -lboost_regex,cpp_options: ) + +else + +$(call include-once,$(scf_root)/import/libboost/regex/rules.make,$(dcf_root)) + +$(call export,\ + l: $(dcf_root)/import/libboost/regex/regex.l,\ + cpp-options: $(dcf_root)/import/libboost/regex/regex.l.cpp-options) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/import/libboost/version b/build/import/libboost/version new file mode 100644 index 0000000..1d0ba9e --- /dev/null +++ b/build/import/libboost/version @@ -0,0 +1 @@ +0.4.0 diff --git a/build/import/libcult/LICENSE b/build/import/libcult/LICENSE new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/build/import/libcult/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/build/import/libcult/configuration-rules.make b/build/import/libcult/configuration-rules.make new file mode 100644 index 0000000..dc19df4 --- /dev/null +++ b/build/import/libcult/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libcult/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(dcf_root)/import/libcult/configuration-dynamic.make: | $(dcf_root)/import/libcult/. + $(call message,,$(scf_root)/import/libcult/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libcult/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libcult/configuration-dynamic.make) + +endif diff --git a/build/import/libcult/configure b/build/import/libcult/configure new file mode 100755 index 0000000..afa4c9c --- /dev/null +++ b/build/import/libcult/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file : build/import/libcult/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + + +# $1 - out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libcult' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libcult' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libcult'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libcult'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libcult_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root >>$1 + +fi diff --git a/build/import/libcult/stub.make b/build/import/libcult/stub.make new file mode 100644 index 0000000..f5f7691 --- /dev/null +++ b/build/import/libcult/stub.make @@ -0,0 +1,30 @@ +# file : build/import/libcult/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Boris Kolpackov +# license : GNU GPL v2; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libcult/configuration-rules.make,$(dcf_root)) + +libcult_installed := + +$(call -include,$(dcf_root)/import/libcult/configuration-dynamic.make) + +ifdef libcult_installed + +ifeq ($(libcult_installed),y) + +$(call export,l: -lcult,cpp-options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libcult/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/import/libxsd-frontend/LICENSE b/build/import/libxsd-frontend/LICENSE new file mode 100644 index 0000000..33b4cbc --- /dev/null +++ b/build/import/libxsd-frontend/LICENSE @@ -0,0 +1,22 @@ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +In addition, as a special exception, Code Synthesis Tools CC gives +permission to link this program with the Xerces-C++ library (or with +modified versions of Xerces-C++ that use the same license as Xerces-C++), +and distribute linked combinations including the two. You must obey +the GNU General Public License version 2 in all respects for all of +the code used other than Xerces-C++. If you modify this copy of the +program, you may extend this exception to your version of the program, +but you are not obligated to do so. If you do not wish to do so, delete +this exception statement from your version. diff --git a/build/import/libxsd-frontend/configuration-rules.make b/build/import/libxsd-frontend/configuration-rules.make new file mode 100644 index 0000000..eda6378 --- /dev/null +++ b/build/import/libxsd-frontend/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libxsd-frontend/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(dcf_root)/import/libxsd-frontend/configuration-dynamic.make: | $(dcf_root)/import/libxsd-frontend/. + $(call message,,$(scf_root)/import/libxsd-frontend/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libxsd-frontend/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libxsd-frontend/configuration-dynamic.make) + +endif diff --git a/build/import/libxsd-frontend/configure b/build/import/libxsd-frontend/configure new file mode 100755 index 0000000..1571a27 --- /dev/null +++ b/build/import/libxsd-frontend/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file : build/import/libxsd-frontend/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + + +# $1 - out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libxsd-frontend' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libxsd-frontend' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libxsd-frontend'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libxsd-frontend'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libxsd_frontend_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root >>$1 + +fi diff --git a/build/import/libxsd-frontend/stub.make b/build/import/libxsd-frontend/stub.make new file mode 100644 index 0000000..8061c35 --- /dev/null +++ b/build/import/libxsd-frontend/stub.make @@ -0,0 +1,30 @@ +# file : build/import/libxsd-frontend/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libxsd-frontend/configuration-rules.make,$(dcf_root)) + +libxsd_frontend_installed := + +$(call -include,$(dcf_root)/import/libxsd-frontend/configuration-dynamic.make) + +ifdef libxsd_frontend_installed + +ifeq ($(libxsd_frontend_installed),y) + +$(call export,l: -lxsd-frontend,cpp_options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libxsd-frontend/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif diff --git a/build/xsde/hybrid/xsd-cxx.make b/build/xsde/hybrid/xsd-cxx.make new file mode 100644 index 0000000..b221d7a --- /dev/null +++ b/build/xsde/hybrid/xsd-cxx.make @@ -0,0 +1,139 @@ +# file : build/xsde/hybrid/xsd-cxx.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#@@ Need to use extensions from cxx config. +# + +$(call include,$(scf_root)/configuration.make) + +ifeq ($(xsd_pskel_suffix),) +xsd_pskel_suffix := -pskel +endif + +ifeq ($(xsd_pimpl_suffix),) +xsd_pimpl_suffix := -pimpl +endif + +ifeq ($(xsd_sskel_suffix),) +xsd_sskel_suffix := -sskel +endif + +ifeq ($(xsd_simpl_suffix),) +xsd_simpl_suffix := -simpl +endif + +xsd_hybrid_pattern := \ +$(out_base)/%.cxx \ +$(out_base)/%.hxx \ +$(out_base)/%.ixx + +xsd_hybrid_pattern += \ +$(out_base)/%$(xsd_pskel_suffix).cxx \ +$(out_base)/%$(xsd_pskel_suffix).hxx \ +$(out_base)/%$(xsd_pskel_suffix).ixx + +xsd_hybrid_pattern += \ +$(out_base)/%$(xsd_pimpl_suffix).cxx \ +$(out_base)/%$(xsd_pimpl_suffix).hxx + +xsd_hybrid_pattern += \ +$(out_base)/%$(xsd_sskel_suffix).cxx \ +$(out_base)/%$(xsd_sskel_suffix).hxx \ +$(out_base)/%$(xsd_sskel_suffix).ixx + +xsd_hybrid_pattern += \ +$(out_base)/%$(xsd_simpl_suffix).cxx \ +$(out_base)/%$(xsd_simpl_suffix).hxx + +$(xsd_hybrid_pattern): xsde := xsde +$(xsd_hybrid_pattern): xsde_command := cxx-hybrid + +ops := \ +--pskel-file-suffix $(xsd_pskel_suffix) \ +--pimpl-file-suffix $(xsd_pimpl_suffix) \ +--sskel-file-suffix $(xsd_sskel_suffix) \ +--simpl-file-suffix $(xsd_simpl_suffix) + + +ifeq ($(xsde_stl),n) +ops += --no-stl +endif + +ifeq ($(xsde_iostream),n) +ops += --no-iostream +endif + +ifeq ($(xsde_exceptions),n) +ops += --no-exceptions +endif + +ifeq ($(xsde_longlong),n) +ops += --no-long-long +endif + +ifeq ($(xsde_parser_validation),n) +ops += --suppress-parser-val +endif + +ifeq ($(xsde_serializer_validation),n) +ops += --suppress-serializer-val +endif + +#ifeq ($(xsde_polymorphic),y) +#ops += --runtime-polymorphic +#endif + +ifeq ($(xsde_reuse_style),mixin) +ops += --reuse-style-mixin +endif + +ifeq ($(xsde_reuse_style),none) +$(error Hybrid mapping requires support for base parser/serializer reuse) +endif + +$(xsd_hybrid_pattern): xsde_options := $(ops) + +.PRECIOUS: $(xsd_hybrid_pattern) + +$(xsd_hybrid_pattern): $(out_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +ifneq ($(out_base),$(src_base)) + +$(xsd_hybrid_pattern): $(src_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +endif + + +.PHONY: $(out_base)/%.cxx.xsd.clean + +$(out_base)/%.cxx.xsd.clean: pskel := $(xsd_pskel_suffix) +$(out_base)/%.cxx.xsd.clean: pimpl := $(xsd_pimpl_suffix) +$(out_base)/%.cxx.xsd.clean: sskel := $(xsd_sskel_suffix) +$(out_base)/%.cxx.xsd.clean: simpl := $(xsd_simpl_suffix) + +$(out_base)/%.cxx.xsd.clean: + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.hxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.ixx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(pskel).cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(pskel).hxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(pskel).ixx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(pimpl).cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(pimpl).hxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(sskel).cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(sskel).hxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(sskel).ixx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(simpl).cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=$(simpl).hxx)) + + +# Reset the config variables so they won't take effect in other places. +# +xsd_pskel_suffix := +xsd_pimpl_suffix := +xsd_sskel_suffix := +xsd_simpl_suffix := diff --git a/build/xsde/parser/xsd-cxx.make b/build/xsde/parser/xsd-cxx.make new file mode 100644 index 0000000..ee6c742 --- /dev/null +++ b/build/xsde/parser/xsd-cxx.make @@ -0,0 +1,103 @@ +# file : build/xsde/parser/xsd-cxx.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#@@ Need to use extensions from cxx config. +# + +$(call include,$(scf_root)/configuration.make) + +ifeq ($(xsd_pskel_suffix),) +xsd_pskel_suffix := -pskel +endif + +xsd_parser_pattern := \ +$(out_base)/%$(xsd_pskel_suffix).cxx \ +$(out_base)/%$(xsd_pskel_suffix).hxx \ +$(out_base)/%$(xsd_pskel_suffix).ixx + +ifneq ($(xsd_pimpl_suffix),) +xsd_parser_pattern += \ +$(out_base)/%$(xsd_pimpl_suffix).cxx \ +$(out_base)/%$(xsd_pimpl_suffix).hxx \ +$(out_base)/%-pdriver.cxx +endif + +$(xsd_parser_pattern): xsde := xsde +$(xsd_parser_pattern): xsde_command := cxx-parser + +ops := --skel-file-suffix $(xsd_pskel_suffix) + +ifneq ($(xsd_pimpl_suffix),) +ops += --impl-file-suffix $(xsd_pimpl_suffix) +endif + +ifeq ($(xsde_stl),n) +ops += --no-stl +endif + +ifeq ($(xsde_iostream),n) +ops += --no-iostream +endif + +ifeq ($(xsde_exceptions),n) +ops += --no-exceptions +endif + +ifeq ($(xsde_longlong),n) +ops += --no-long-long +endif + +ifeq ($(xsde_parser_validation),n) +ops += --suppress-validation +endif + +ifeq ($(xsde_polymorphic),y) +ops += --runtime-polymorphic +endif + +ifeq ($(xsde_reuse_style),mixin) +ops += --reuse-style-mixin +endif + +ifeq ($(xsde_reuse_style),none) +ops += $(xsde_options) --reuse-style-none +endif + +$(xsd_parser_pattern): xsde_options := $(ops) + + +.PRECIOUS: $(xsd_parser_pattern) + +$(xsd_parser_pattern): $(out_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +ifneq ($(out_base),$(src_base)) + +$(xsd_parser_pattern): $(src_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +endif + + +.PHONY: $(out_base)/%$(xsd_pskel_suffix).cxx.xsd.clean + +$(out_base)/%$(xsd_pskel_suffix).cxx.xsd.clean: + $(call message,rm $(@:.cxx.xsd.clean=.cxx),rm -f $(@:.cxx.xsd.clean=.cxx)) + $(call message,rm $(@:.cxx.xsd.clean=.hxx),rm -f $(@:.cxx.xsd.clean=.hxx)) + $(call message,rm $(@:.cxx.xsd.clean=.ixx),rm -f $(@:.cxx.xsd.clean=.ixx)) + +ifneq ($(xsd_pimpl_suffix),) +.PHONY: $(out_base)/%$(xsd_pimpl_suffix).cxx.xsd.clean + +$(out_base)/%$(xsd_pimpl_suffix).cxx.xsd.clean: + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.hxx)) + $(call message,rm $$1,rm -f $$1,$(out_base)/$*-pdriver.cxx) +endif + +# Reset the config variables so they won't take effect in other places. +# +xsd_pskel_suffix := +xsd_pimpl_suffix := diff --git a/build/xsde/serializer/xsd-cxx.make b/build/xsde/serializer/xsd-cxx.make new file mode 100644 index 0000000..d318346 --- /dev/null +++ b/build/xsde/serializer/xsd-cxx.make @@ -0,0 +1,103 @@ +# file : build/xsde/serializer/xsd-cxx.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#@@ Need to use extensions from cxx config. +# + +$(call include,$(scf_root)/configuration.make) + +ifeq ($(xsd_sskel_suffix),) +xsd_sskel_suffix := -sskel +endif + +xsd_serializer_pattern := \ +$(out_base)/%$(xsd_sskel_suffix).cxx \ +$(out_base)/%$(xsd_sskel_suffix).hxx \ +$(out_base)/%$(xsd_sskel_suffix).ixx + +ifneq ($(xsd_simpl_suffix),) +xsd_serializer_pattern += \ +$(out_base)/%$(xsd_simpl_suffix).cxx \ +$(out_base)/%$(xsd_simpl_suffix).hxx \ +$(out_base)/%-sdriver.cxx +endif + +$(xsd_serializer_pattern): xsde := xsde +$(xsd_serializer_pattern): xsde_command := cxx-serializer + +ops := --skel-file-suffix $(xsd_sskel_suffix) + +ifneq ($(xsd_pimpl_suffix),) +ops += --impl-file-suffix $(xsd_simpl_suffix) +endif + +ifeq ($(xsde_stl),n) +ops += --no-stl +endif + +ifeq ($(xsde_iostream),n) +ops += --no-iostream +endif + +ifeq ($(xsde_exceptions),n) +ops += --no-exceptions +endif + +ifeq ($(xsde_longlong),n) +ops += --no-long-long +endif + +ifeq ($(xsde_serializer_validation),n) +ops += --suppress-validation +endif + +ifeq ($(xsde_polymorphic),y) +ops += --runtime-polymorphic +endif + +ifeq ($(xsde_reuse_style),mixin) +ops += --reuse-style-mixin +endif + +ifeq ($(xsde_reuse_style),none) +ops += $(xsde_options) --reuse-style-none +endif + +$(xsd_serializer_pattern): xsde_options := $(ops) + + +.PRECIOUS: $(xsd_serializer_pattern) + +$(xsd_serializer_pattern): $(out_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +ifneq ($(out_base),$(src_base)) + +$(xsd_serializer_pattern): $(src_base)/%.xsd | $$(dir $$@). + $(call message,xsde $<,$(xsde) $(xsde_command) $(xsde_options) --output-dir $(dir $@) $<) + +endif + + +.PHONY: $(out_base)/%$(xsd_sskel_suffix).cxx.xsd.clean + +$(out_base)/%$(xsd_sskel_suffix).cxx.xsd.clean: + $(call message,rm $(@:.cxx.xsd.clean=.cxx),rm -f $(@:.cxx.xsd.clean=.cxx)) + $(call message,rm $(@:.cxx.xsd.clean=.hxx),rm -f $(@:.cxx.xsd.clean=.hxx)) + $(call message,rm $(@:.cxx.xsd.clean=.ixx),rm -f $(@:.cxx.xsd.clean=.ixx)) + +ifneq ($(xsd_simpl_suffix),) +.PHONY: $(out_base)/%$(xsd_simpl_suffix).cxx.xsd.clean + +$(out_base)/%$(xsd_simpl_suffix).cxx.xsd.clean: + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.cxx)) + $(call message,rm $$1,rm -f $$1,$(@:.cxx.xsd.clean=.hxx)) + $(call message,rm $$1,rm -f $$1,$(out_base)/$*-sdriver.cxx) +endif + +# Reset the config variables so they won't take effect in other places. +# +xsd_sskel_suffix := +xsd_simpl_suffix := diff --git a/documentation/cxx/hybrid/guide/figure-1.png b/documentation/cxx/hybrid/guide/figure-1.png new file mode 100644 index 0000000..b89cec8 Binary files /dev/null and b/documentation/cxx/hybrid/guide/figure-1.png differ diff --git a/documentation/cxx/hybrid/guide/figure-1.svg b/documentation/cxx/hybrid/guide/figure-1.svg new file mode 100644 index 0000000..ccc79cd --- /dev/null +++ b/documentation/cxx/hybrid/guide/figure-1.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + Object Model + Parser + + + Parser + + + + Serializer + + C++/Hybrid + + Application + + + C++/Parser + C++/Serializer + + diff --git a/documentation/cxx/hybrid/guide/guide.html2ps b/documentation/cxx/hybrid/guide/guide.html2ps new file mode 100644 index 0000000..55aa4bf --- /dev/null +++ b/documentation/cxx/hybrid/guide/guide.html2ps @@ -0,0 +1,65 @@ +@html2ps { + option { + toc: hb; + colour: 1; + hyphenate: 1; + titlepage: 1; + } + + datefmt: "%B %Y"; + + titlepage { + content: " +
+

Embedded C++/Hybrid Mapping

+

Getting Started Guide

+

 

+

 

+

 

+

 

+

 

+

 

+
+

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

"; + } + + toc { + indent: 2em; + } + + header { + odd-right: $H; + even-left: $H; + } + + footer { + odd-left: $D; + odd-center: $T; + odd-right: $N; + + even-left: $N; + even-center: $T; + even-right: $D; + } +} + +body { + font-size: 12pt; + text-align: justify; +} + +pre { + font-size: 10pt; +} diff --git a/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml new file mode 100644 index 0000000..b555009 --- /dev/null +++ b/documentation/cxx/hybrid/guide/index.xhtml @@ -0,0 +1,5099 @@ + + + + + + Embedded C++/Hybrid Mapping Getting Started Guide + + + + + + + + + + + + + +
+
+ +
+ +
+
Embedded C++/Hybrid Mapping
+
Getting Started Guide
+ +

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

+ +
+ +

Table of Contents

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preface + + + +
About This Document
More Information
+
1Introduction + + + +
1.1Mapping Overview
1.2Benefits
+
2Hello World Example + + + + + + + +
2.1Writing XML Document and Schema
2.2Translating Schema to C++
2.3Implementing Application Logic
2.4Compiling and Running
2.5Adding Serialization
2.6A Minimal Version
+
3Mapping Configuration + + + + + + + +
3.1Standard Template Library
3.2Input/Output Stream Library
3.3C++ Exceptions
3.4XML Schema Validation
3.564-bit Integer Type
3.6Parser and Serializer Reuse
+
4Working with Object Models + + + + + + + + + +
4.1Namespaces
4.2Memory Management
4.3Attributes and Elements
4.4Compositors
4.5Accessing the Object Model
4.6Modifying the Object Model
4.7Creating the Object Model from Scratch
4.8Customizing the Object Model
+
5Mapping for Built-In XML Schema Types + + + + + + + + + + + + + + +
5.1Mapping for QName
5.2Mapping for NMTOKENS and IDREFSs
5.3Mapping for base54Binary and hexBinarys
5.4Time Zone Representation
5.5Mapping for date
5.6Mapping for dateTime
5.7Mapping for duration
5.8Mapping for gDay
5.9Mapping for gMonth
5.10Mapping for gMonthDay
5.11Mapping for gYear
5.12Mapping for gYearMonth
5.13Mapping for time
+
6Parsing and Serialization + + +
6.1Customizing Parsers and Serializers
+
+
+ +

Preface

+ +

About This Document

+ +

The goal of this document is to provide you with an + understanding of the C++/Hybrid programming model and allow you + to efficiently evaluate XSD/e against your project's technical + requirements. As such, this document is intended for embedded + C++ developers and software architects who are looking for an + embedded XML processing solution. Prior experience with XML + and C++ is required to understand this document. Basic + understanding of XML Schema is advantageous but not expected + or required. +

+ + +

More Information

+ +

Beyond this guide, you may also find the following sources of + information useful:

+ + + + + +

1 Introduction

+ +

Welcome to CodeSynthesis XSD/e and the Embedded C++/Hybrid mapping. + XSD/e is a validating XML parser/serializer and data binding generator + for mobile and embedded systems. Embedded C++/Hybrid is a W3C XML + Schema to C++ mapping that represents the data stored in XML as a + light-weight, statically-typed, in-memory object model. +

+ +

1.1 Mapping Overview

+ +

Based on a formal description of an XML vocabulary (schema), the + C++/Hybrid mapping produces a tree-like data structure suitable + for in-memory processing. The core of the mapping consists of C++ + classes that constitute the object model and are derived from + types defined in XML Schema. The C++/Hybrid mapping uses the + APIs provided by the + Embedded + C++/Parser and + Embedded + C++/Serializer + mappings to perform validation and parsing of XML to the object + model and validation and serialization of the object model to + XML. The following diagram illustrates the high-level architecture + of the C++/Hybrid mapping:

+ + +
+ +

The use of well-defined APIs presented by the C++/Parser and + C++/Serializer mappings for XML parsing and serialization + allows a number of advanced techniques, for example, customization + of parsing and serialization code, filtering of XML during + parsing or object model during serialization, as well as the hybrid, + partially event-driven, partially in-memory processing + where the XML document is delivered to the application as + parts of the object model. The last feature combines the + ease and convenience of the in-memory processing model + with the ability to minimize the use of RAM and process documents + that would otherwise not fit into memory. +

+ +

The Embedded C++/Hybrid mapping was specifically designed and + optimized for mobile and embedded systems where hardware + constraints require high efficiency and economical use of + resources. As a result, the generated parsing and serialization + code is 2-10 times faster than general-purpose XML processors + while at the same time maintaining extremely low static and + dynamic memory footprints. For example, an executable that + performs validating XML parsing and serialization can be as small + as 150KB in size. The size can be further reduced by disabling + support for parsing or serialization as well as XML Schema + validation. +

+ +

The generated code and the runtime library are also highly-portable + and, in their minimal configuration, can be used without STL, RTTI, + iostream, C++ exceptions, and with the minimal use of C++ templates.

+ +

A typical application that uses the C++/Hybrid mapping for XML + processing performs the following three steps: it first + reads (parses) an XML document to an in-memory object model, it + then performs some useful computations on that object model which + may involve modification of the model, and finally it may write + (serialize) the modified object model back to XML. The next chapter + presents a simple application that performs these three steps. The + following chapters describe the Embedded C++/Hybrid mapping in more + detail.

+ +

1.2 Benefits

+ +

Traditional XML access APIs such as Document Object Model (DOM) + or Simple API for XML (SAX) as well as general-purpose XML Schema + validators have a number of drawbacks that make them less suitable + for creating mobile and embedded XML processing applications. These + drawbacks include: +

+ +
    +
  • Generic representation of XML in terms of elements, attributes, + and text forces an application developer to write a substantial + amount of bridging code that identifies and transforms pieces + of information encoded in XML to a representation more suitable + for consumption by the application logic.
  • + +
  • String-based flow control defers error detection to runtime. + It also reduces code readability and maintainability.
  • + +
  • Lack of type safety and inefficient use of resources due to + the data being represented as text.
  • + +
  • Extra validation code that is not used by the application.
  • + +
  • Resulting applications are hard to debug, change, and + maintain.
  • +
+ +

In contrast, a light-weight, statically-typed, vocabulary-specific + object model produced by the Embedded C++/Hybrid mapping allows + you to operate in your domain terms instead of the generic elements, + attributes, and text. Native data types are used to store the XML + data (for example, integers are stored as integers, not as text). + Validation code is included only for XML Schema constructs that + are used in the application. This results in efficient use of + resources and compact object code.

+ +

Furthermore, static typing helps catch errors at + compile-time rather than at run-time. Automatic code generation + frees you for more interesting tasks (such as doing something + useful with the information stored in the XML documents) and + minimizes the effort needed to adapt your applications to changes + in the document structure. To summarize, the C++/Hybrid object + model has the following key advantages over generic XML access + APIs:

+ +
    +
  • Ease of use. The generated code hides all the complexity + associated with parsing and serializing XML. This includes navigating + the structure and converting between the text representation and + data types suitable for manipulation by the application logic.
  • + +
  • Natural representation. The object representation allows + you to access the XML data using your domain vocabulary instead + of generic elements, attributes, and text.
  • + +
  • Concise code. With the object representation the + application implementation is simpler and thus easier + to read and understand.
  • + +
  • Safety. The generated object model is statically + typed and uses functions instead of strings to access the + information. This helps catch programming errors at compile-time + rather than at runtime.
  • + +
  • Maintainability. Automatic code generation minimizes the + effort needed to adapt the application to changes in the + document structure. With static typing, the C++ compiler + can pin-point the places in the client code that need to be + changed.
  • + +
  • Efficiency. If the application makes repetitive use + of the data extracted from XML, then the C++/Hybrid object model + is more efficient because the navigation is performed using + function calls rather than string comparisons and the XML + data is extracted only once. The runtime memory + usage is also reduced due to more efficient data storage + (for instance, storing numeric data as integers instead of + strings) as well as the static knowledge of cardinality + constraints. + +

    Furthermore, the generated XML parsing and serialization code + combines validation and data-to-text conversion in a single step. + This makes the generated code much more efficient than traditional + architectures with separate stages for validation and data + conversion.

    +
  • +
+ + + + +

2 Hello World Example

+ +

In this chapter we will examine how to parse, access, modify, and + serialize a very simple XML document using the generated + C++/Hybrid object model as well as the XML parser and serializer. The + code presented in this chapter is based on the hello + example which can be found in the examples/cxx/hybrid/ + directory of the XSD/e distribution.

+ +

2.1 Writing XML Document and Schema

+ +

First, we need to get an idea about the structure + of the XML documents we are going to process. Our + hello.xml, for example, could look like this:

+ +
+<?xml version="1.0"?>
+<hello>
+
+  <greeting>Hello</greeting>
+
+  <name>sun</name>
+  <name>earth</name>
+  <name>world</name>
+
+</hello>
+  
+ +

Then we can write a description of the above XML in the + XML Schema language and save it into hello.xsd:

+ +
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="hello">
+    <xs:sequence>
+      <xs:element name="greeting" type="xs:string"/>
+      <xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="hello" type="hello"/>
+
+</xs:schema>
+  
+ +

Even if you are not familiar with XML Schema, it + should be easy to connect declarations in hello.xsd + to elements in hello.xml. The hello type + is defined as a sequence of the nested greeting and + name elements. Note that the term sequence in XML + Schema means that elements should appear in a particular order + as opposed to appearing multiple times. The name + element has its maxOccurs property set to + unbounded which means it can appear multiple times + in an XML document. Finally, the globally-defined hello + element prescribes the root element for our vocabulary. For an + easily-approachable introduction to XML Schema refer to + XML Schema Part 0: + Primer.

+ +

The above schema is a specification of our XML vocabulary; it tells + everybody what valid documents of our XML-based language should look + like. The next step is to compile the schema to generate the object + model and the parser.

+ + +

2.2 Translating Schema to C++

+ +

Now we are ready to translate our hello.xsd to C++. + To do this we invoke the XSD/e compiler from a terminal (UNIX) or + a command prompt (Windows): +

+ +
+$ xsde cxx-hybrid --generate-parser --generate-aggregate hello.xsd
+  
+ +

This invocation of the XSD/e compiler produces three pairs of C++ files: + hello.hxx and hello.cxx, + hello-pskel.hxx and hello-pskel.cxx, as well as + hello-pimpl.hxx and hello-pimpl.cxx. The + first pair contains the object model classes. The second pair contains + parser skeletons. Parser skeletons are generated by the C++/Parser + mapping which is automatically invoked by C++/Hybrid. + For now we can ignore parser skeletons except that we need to compile + them and link the result to our application. The last pair of files + contains parser implementations. They implement the parser skeletons + to create and populate the object model types from XML data. The generation + of parser skeletons and parser implementations is requested with the + --generate-parser XSD/e compiler option.

+ +

You may be wondering what is the --generate-aggregate + option for. This option instructs the XSD/e compiler to generate + parser and, as we will see later, serializer aggregates. The + generated parser implementation files mentioned above contain + a separate parser implementation class for each type defined + in XML Schema. These parser implementations need to be + instantiated and connected before we can use them to parse an XML document. + When you specify the --generate-aggregate option, + the XSD/e compiler generates a class (in the parser implementation + files), called parser aggregate, for each global element defined + in the schema (you can also generate a parser aggregate for a type + as well as control for which global elements parser aggregates + are generated, see the + XSD/e + Compiler Command Line Manual for more information). A parser + aggregate instantiates and connects all the necessary parser + implementations needed to parse an XML document with a given root + element. We will see how to use the parser aggregate for the + hello root element in the next section.

+ +

The following code fragment is taken from hello.hxx; it + shows what the C++ object model for our "Hello World" XML vocabulary + looks like: +

+ +
+class hello
+{
+public:
+  hello ();
+
+  // greeting
+  //
+  const std::string&
+  greeting () const;
+
+  std::string&
+  greeting ();
+
+  void
+  greeting (const std::string&);
+
+  // name
+  //
+  typedef xsde::string_sequence name_sequence;
+  typedef name_sequence::iterator name_iterator;
+  typedef name_sequence::const_iterator name_const_iterator;
+
+  const name_sequence&
+  name () const;
+
+  name_sequence&
+  name ();
+
+private:
+  ...
+};
+  
+ +

The hello C++ class corresponds to the + hello XML Schema type. For each element + in this type a set of accessor and modifier functions + are generated inside the hello class. Note + that the member functions for the greeting and + name elements are different because of the + different cardinalities these two elements have + (greeting is a required single element and + name is a sequence of elements).

+ +

It is also evident that the built-in XML Schema type + string is mapped to std::string. + The internal string_sequence class that + is used in the name_sequence type definition + has an interface similar to std::vector. The + mapping between the built-in XML Schema types and C++ types + is described in more detail in Chapter 5, + "Mapping for Built-in XML Schema Types".

+ + +

2.3 Implementing Application Logic

+ +

At this point we have all the parts we need to do something useful + with the information stored in our XML document: +

+ +
+#include <iostream>
+
+#include "hello.hxx"
+#include "hello-pimpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  try
+  {
+    // Parse.
+    //
+    hello_paggr hello_p;
+    xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+                                      hello_p.root_name ());
+    hello_p.pre ();
+    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 << argv[1] << ":" << e.line () << ":" << e.column ()
+         << ": " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

The first part of our application creates a document parser + and parses the XML file specified in the command line to the + object model. The hello_paggr class is the parser + aggregate class we discussed earlier. Parsing is covered in more + detail in Chapter 6, "Parsing and Serialization". + The second part uses the returned object model to iterate over + names and print a greeting line for each of them. We also catch + and print the xml_schema::parser_exception exception + in case something goes wrong. +

+ +

2.4 Compiling and Running

+ +

After saving our application from the previous section in + driver.cxx, we are ready to compile our first + program and run it on the test XML document. On UNIX + this can be done with the following commands: +

+ +
+$ c++ -I.../libxsde -c driver.cxx hello-pskel.cxx hello-pimpl.cxx
+$ c++ -o driver driver.o hello-pskel.o hello-pimpl.o \
+  .../libxsde/xsde/libxsde.a
+$ ./driver hello.xml
+Hello, sun!
+Hello, moon!
+Hello, world!
+  
+ +

Here .../libxsde represents the path to the + libxsde directory in the XSD/e distribution.

+ +

We can also test the error handling. To test XML well-formedness + checking, we can try to parse hello.hxx:

+ +
+$ ./driver hello.hxx
+hello.hxx:1:0: not well-formed (invalid token)
+  
+ +

We can also try to parse a valid XML but not from our + vocabulary, for example hello.xsd:

+ +
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+  
+ +

2.5 Adding Serialization

+ +

While parsing and accessing the XML data may be everything + you need, there are applications that require creating new + or modifying existing XML documents. To request the generation + of serialization support we will need to add the + --generate-serializer option to our XSD/e + compiler invocation:

+ +
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+  --generate-aggregate hello.xsd
+  
+ +

This will result in two additional pairs of C++ files: + hello-sskel.hxx and hello-sskel.cxx, as well as + hello-simpl.hxx and hello-simpl.cxx. + Similar to the parser files, the first pair contains serializer + skeletons (generated by the C++/Serializer mapping) and the second + pair contains serializer implementations as well as the serializer + aggregate for the hello root element.

+ +

Let us first examine an application that modifies an existing + object model and serializes it back to XML:

+ +
+#include <iostream>
+
+#include "hello.hxx"
+#include "hello-pimpl.hxx"
+#include "hello-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  try
+  {
+    // Parse.
+    //
+    hello_paggr hello_p;
+    xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+                                      hello_p.root_name ());
+    hello_p.pre ();
+    doc_p.parse (argv[1]);
+    hello* h = hello_p.post ();
+
+    // Change the greeting phrase.
+    //
+    h->greeting ("Hi");
+
+    // Add another entry to the name sequence.
+    //
+    h->name ().push_back ("mars");
+
+    // Serialize the modified object model to XML.
+    //
+    hello_saggr hello_s;
+    xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+                                      hello_s.root_name ());
+    hello_s.pre (*h);
+    doc_s.serialize (cout);
+    hello_s.post ();
+
+    delete h;
+  }
+  catch (const xml_schema::parser_exception& e)
+  {
+    cerr << argv[1] << ":" << e.line () << ":" << e.column ()
+         << ": " << e.text () << endl;
+    return 1;
+  }
+  catch (const xml_schema::serializer_exception& e)
+  {
+    cerr << "error: " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

First, our application parses an XML document and obtains its + object model as in the previous example. Then it changes the + greeting string and adds another entry to the list of names. + Finally, it creates a document serializer and serializes the + object model back to XML. The resulting XML is written to + the standard output (cout) for us to inspect. + We could have also written the result to a file or memory + buffer by creating an instance of std::ofstream + or std::ostringstream and passing it to + serialize() instead of cout. + The hello_saggr class is the serializer aggregate + class we discussed earlier. Serialization is covered in more + detail in Chapter 6, "Parsing and Serialization".

+ +

If we now compile and run this application (don't forget to + compile and link hello-sskel.cxx and + hello-simpl.cxx), we will see the + output as shown in the following listing:

+ +
+<hello>
+  <greeting>Hi</greeting>
+  <name>sun</name>
+  <name>earth</name>
+  <name>world</name>
+  <name>mars</name>
+</hello>
+  
+ +

+ We can also test XML Schema validation. We can "accidently" + remove all the names from the object model by adding the following + after: push_back ("mars"):

+ +
+h->name ().clear ();
+  
+ +

This will violate our vocabulary specification which requires + at least one name element to be present. If we + make the above change and recompile our application, we will + get the following output:

+ +
+$ ./driver hello.xml
+error: expected element not encountered
+  
+ +

It is also possible to create and serialize an object model from + scratch as shown in the following example. For this case we + can remove the --generate-parser option since + we don't need support for XML parsing.

+ +
+#include <sstream>
+#include <iostream>
+
+#include "hello.hxx"
+#include "hello-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  try
+  {
+    hello h;
+    h.greeting ("Hi");
+
+    hello::name_sequence& ns = h.name ();
+    ns.push_back ("Jane");
+    ns.push_back ("John");
+
+    // Serialize the object model to XML.
+    //
+    hello_saggr hello_s;
+    xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+                                      hello_s.root_name ());
+    ostringstream ostr;
+
+    hello_s.pre (*h);
+    doc_s.serialize (ostr);
+    hello_s.post ();
+
+    delete h;
+
+    cout << ostr.c_str () << endl;
+  }
+  catch (const xml_schema::serializer_exception& e)
+  {
+    cerr << "error: " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

In this example we used the generated default constructor to + create an empty instance of type hello. We then + set greeting and, to reduce typing, we obtained a reference to + the name sequence which we used to add a few names. The + serialization part is identical to the previous example except + this time we first save the XML representation into a string. + If we compile and run this program, it produces the following + output:

+ +
+<hello>
+  <greeting>Hi</greeting>
+  <name>Jane</name>
+  <name>John</name>
+</hello>
+  
+ +

2.6 A Minimal Version

+ +

The previous sections showed a number of examples that relied + on STL for strings, iostream of input/output and C++ exceptions + for error handling. + As was mentioned in the introduction and will be discussed + in further detail in the next chapter, the C++/Hybrid mapping + can be configured only to rely on the minimal subset of C++. + In this section we will implement an example that parses, + prints, modifies and serializes the object model without + relying on STL, iostream, or C++ exceptions.

+ +

The first step is to instruct the XSD/e compiler not to use + any of the above features in the generated code. You may also + need to re-configure and rebuild the XSD/e runtime library + (libxsde.a) to disable STL, iostream, and + exceptions.

+ +
+$ xsde cxx-hybrid --no-stl --no-iostream --no-exceptions \
+  --generate-parser --generate-serializer --generate-aggregate \
+  hello.xsd
+  
+ +

If you now study the generated hello.hxx file, + you will notice that the use of std::string type + is replaced with char*. When STL is disabled, + built-in XML Schema type string is mapped to a + C string. The following listing presents the content of + driver.cxx in full:

+ +
+#include <stdio.h>
+
+#include "people.hxx"
+
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+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[])
+{
+  // Open the file or use STDIN.
+  //
+  FILE* f = fopen (argv[1], "rb");
+
+  if (f == 0)
+  {
+    fprintf (stderr, "%s: unable to open\n", argc);
+    return 1;
+  }
+
+  // Parse.
+  //
+  using xml_schema::parser_error;
+
+  parser_error pe;
+  bool io_error = false;
+  hello* h = 0;
+
+  do
+  {
+    hello_paggr hello_p;
+    xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+                                      hello_p.root_name ());
+    if (pe = doc_p._error ())
+      break;
+
+    hello_p.pre ();
+
+    if (pe = hello_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;
+
+    h = hello_p.post ();
+    pe = hello_p._error ();
+
+  } while (false);
+
+  fclose (f);
+
+  // Handle parsing errors.
+  //
+  if (io_error)
+  {
+    fprintf (stderr, "%s: read failure\n", argc);
+    return 1;
+  }
+
+  if (pe)
+  {
+    switch (pe.type ())
+    {
+    case parser_error::sys:
+      {
+        fprintf (stderr, "%s: %s\n", argc, pe.sys_text ());
+        break;
+      }
+    case parser_error::xml:
+      {
+        fprintf (stderr, "%s:%lu:%lu: %s\n",
+                 argc, pe.line (), pe.column (), pe.xml_text ());
+        break;
+      }
+    case parser_error::schema:
+      {
+        fprintf (stderr, "%s:%lu:%lu: %s\n",
+                 argc, pe.line (), pe.column (), pe.schema_text ());
+        break;
+      }
+    default:
+      break;
+    }
+
+    return 1;
+  }
+
+  // Print what we've got.
+  //
+  for (hello::name_const_iterator i = h->name ().begin ();
+       i != h->name ().end ();
+       ++i)
+  {
+    printf ("%s, %s!\n", h->greeting (), *i);
+  }
+
+  using xml_schema::strdupx;
+
+  // Change the greeting phrase.
+  //
+  h->greeting (strdupx ("Hi"));
+
+  // Add another entry to the name sequence.
+  //
+  h->name ().push_back (strdupx ("mars"));
+
+  // Serialize.
+  //
+  using xml_schema::serializer_error;
+
+  serializer_error se;
+  writer w;
+
+  do
+  {
+    hello_saggr hello_s;
+    xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+                                      hello_s.root_name ());
+    if (se = doc_s._error ())
+      break;
+
+    hello_s.pre (*h);
+
+    if (se = hello_s._error ())
+      break;
+
+    doc_s.serialize (w);
+
+    if (se = doc_s._error ())
+      break;
+
+    hello_s.post ();
+
+    se = hello_s._error ();
+
+  } while (false);
+
+  delete h;
+
+  // 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;
+      }
+    case serializer_error::schema:
+      {
+        fprintf (stderr, "error: %s\n", se.schema_text ());
+        break;
+      }
+    default:
+      break;
+    }
+
+    return 1;
+  }
+}
+  
+ +

The parsing and serialization parts of the above example got + quite a bit more complex due to the lack of exceptions and iostream + support. For more information on what's going on there, refer to + Chapter 6, "Parsing and Serialization". On the other + hand, the access and modification of the object model stayed + relatively unchanged. The only noticeable change is the use + of the xml_schema::strdupx function to create + C strings from string literals. We have to use this function + because the object model assumes ownership of the strings + passed. We also cannot use the standard C strdup + because the object model expects the strings to be allocated + with C++ operator new[] while C strdup + uses malloc (on most implementations operator + new is implemented in terms of malloc + so you can probably use strdup if you really + want to).

+ + + + + +

3 Mapping Configuration

+ +

The Embedded C++/Hybrid mapping has a number of configuration + parameters that determine the overall properties and behavior + of the generated code, such as the use of Standard Template + Library (STL), Input/Output Stream Library (iostream), C++ + exceptions, XML Schema validation, 64-bit integer types, as well as + parser and serializer implementation reuse styles. In the previous + chapter we have already got an overview of the changes to the + generated code that happen when we disable STL, iostream, and C++ + exceptions. In this chapter we will discuss these and other + configuration parameters in more detail.

+ +

In order to enable or disable a particular feature, the corresponding + configuration parameter should be set accordingly in the XSD/e runtime + library as well as specified during schema compilation with the XSD/e + command line options as described in the + XSD/e + Compiler Command Line Manual. +

+ +

While the XML documents can use various encodings, the Embedded + C++/Hybrid mapping always delivers character data to the application + in the UTF-8 encoding. The underlying XML parser used by the mapping + includes built-in support for XML documents encoded in UTF-8, UTF-16, + ISO-8859-1, and US-ASCII. Other encodings can be supported by providing + application-specific decoder functions. C++/Hybrid also expects character + data supplied by the application to be in the UTF-8 encoding. The + underlying XML serializer used by the mapping produces the resulting + XML in the UTF-8 encoding as well.

+ +

3.1 Standard Template Library

+ +

To disable the use of STL you will need to configure the XSD/e + runtime without support for STL as well as pass the + --no-stl option to the XSD/e compiler when + translating your schemas.

+ +

When STL is disabled, all string-based XML Schema types + (see Chapter 5, "Mapping for Built-In XML Schema + Types") are mapped to C-style char* instead of + std::string. In this configuration when you set an + element or attribute value of a string-based type, the object + model assumes ownership of the string and expects that it was + allocated with operator new[]. To simplify + creation of such strings from string literals, the generated + code provides the strdupx and strndupx + functions in the xml_schema namespace. These functions + are similar to C strdup and strndup except + that they use operator new[] instead of malloc + to allocate the string:

+ +
+namespace xml_schema
+{
+  char*
+  strdupx (const char*);
+
+  char*
+  strndupx (const char*, size_t);
+}
+  
+ +

3.2 Input/Output Stream Library

+ +

To disable the use of iostream you will need to configure the + XSD/e runtime library without support for iostream as well as + pass the --no-iostream option to the XSD/e compiler + when translating your schemas. When iostream is disabled, a + number of overloaded parse() and serialize() + functions in the document parser (xml_schema::document_pimpl) + and document serializer (xml_schema::document_simpl) become + unavailable. See + Chapter 7, + "Document Parser and Error Handling" in the Embedded + C++/Parser Mapping Getting Started Guide and + Chapter 8, + "Document Serializer and Error Handling" in the Embedded + C++/Serializer Mapping Getting Started Guide for details. +

+ +

3.3 C++ Exceptions

+ +

To disable the use of C++ exceptions, you will need to configure + the XSD/e runtime without support for exceptions as well as pass + the --no-exceptions option to the XSD/e compiler + when translating your schemas. When C++ exceptions are disabled, + the error conditions that may arise while parsing, serializing, + and modifying the object model are indicated with error codes + instead of exceptions. For more information on error handling + during parsing, see + Chapter 7, + "Document Parser and Error Handling" in the Embedded C++/Parser + Mapping Getting Started Guide. For more information on error handling + during serialization, see + Chapter 8, + "Document Serializer and Error Handling" in the Embedded + C++/Serializer Mapping Getting Started Guide. For more information on + error handling in the object model, see Chapter 4, "Working + with Object Models" below. +

+ +

3.4 XML Schema Validation

+ +

By default, XML Schema validation is enabled during both parsing + and serialization. To disable validation during parsing, you will + need to configure the XSD/e runtime to disable support for validation + in the C++/Parser mapping as well as pass the --suppress-parser-val + option to the XSD/e compiler when translating your schemas. To disable + validation during serialization, you will need to configure the XSD/e + runtime to disable support for validation in the C++/Serializer mapping + as well as pass the --suppress-serializer-val + option to the XSD/e compiler when translating your schemas. If you + are disabling validation during both parsing and serialization, you + can use the --suppress-validation option instead of the + two options mentioned above.

+ +

Disabling XML Schema validation allows to further increase the + parsing and serialization performance as well as reduce footprint in + cases where the data being parsed and/or serialized is known + to be valid.

+ +

3.5 64-bit Integer Type

+ +

By default the 64-bit long and unsignedLong + built-in XML Schema types are mapped to the 64-bit long long + and unsigned long long fundamental C++ types. To + disable the use of these types in the mapping you will need to + configure the XSD/e runtime accordingly as well as pass + the --no-long-long option to the XSD/e compiler + when translating your schemas. When the use of 64-bit integral + C++ types is disabled the long and + unsignedLong XML Schema built-in types are mapped + to long and unsigned long fundamental + C++ types.

+ +

3.6 Parser and Serializer Reuse

+ +

When one type in XML Schema inherits from another, it is + often desirable to be able to reuse the parser and serializer + implementations corresponding to the base type in the parser + and serializer implementations corresponding to the derived type. + XSD/e provides support for two reuse styles: the so-called mixin + (generated when the --reuse-style-mixin option + is specified) and tiein (generated by default) styles. + The XSD/e runtime should be configured in accordance with the + reuse style used in the generated code. See Section 5.6, + "Parser Reuse" in the Embedded C++/Parser Mapping Getting Started + Guide and + Section 6.6, + "Serializer Reuse" in the Embedded C++/Serializer Mapping Getting + Started Guide for details.

+ + + + + +

4 Working with Object Models

+ +

As we have seen in the previous chapters, the XSD/e compiler generates + a C++ class for each type defined in XML Schema. Together these classes + constitute an object model for an XML vocabulary. In this chapter we + will take a closer look at different parts that comprise an + object model class as well as how to create, access, and modify + object models.

+ +

In this chapter we will use the following schema that describes a + collection of person records. We save it in people.xsd:

+ +
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:simpleType name="gender">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="male"/>
+      <xs:enumeration value="female"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="first-name" type="xs:string"/>
+      <xs:element name="middle-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="last-name" type="xs:string"/>
+      <xs:element name="gender" type="gender"/>
+      <xs:element name="age" type="xs:unsignedShort"/>
+    </xs:sequence>
+    <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="people">
+    <xs:sequence>
+      <xs:element name="person" type="person" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="people" type="people"/>
+
+</xs:schema>
+  
+ +

A sample XML instance to go along with this schema is saved + in people.xml:

+ +
+<?xml version="1.0"?>
+<people>
+
+  <person id="1">
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+
+  <person id="2">
+    <first-name>Jane</first-name>
+    <middle-name>Mary</middle-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+
+</people>
+  
+ +

Compiling people.xsd with the XSD/e compiler results + in three generated object model classes: gender, + person and people. Here is how they + look with STL enabled:

+ +
+// gender (fixed-length)
+//
+class gender: public std::string
+{
+public:
+  gender ();
+  gender (const gender&);
+  gender& operator= (const gender&);
+};
+
+// person (fixed-length)
+//
+class person
+{
+public:
+  person ();
+  person (const person&);
+  person& operator= (const person&);
+
+  // id
+  //
+  unsigned int
+  id () const;
+
+  unsigned int&
+  id ();
+
+  void
+  id (unsigned int);
+
+  // first-name
+  //
+  const std::string&
+  first_name () const;
+
+  std::string&
+  first_name ();
+
+  void
+  first_name (const std::string&);
+
+  // middle-name
+  //
+  bool
+  middle_name_present () const;
+
+  void
+  middle_name_present (bool);
+
+  const std::string&
+  middle_name () const;
+
+  std::string&
+  middle_name ();
+
+  void
+  middle_name (const std::string&);
+
+  // last-name
+  //
+  const std::string&
+  last_name () const;
+
+  std::string&
+  last_name ();
+
+  void
+  last_name (const std::string&);
+
+  // gender
+  //
+  const ::gender&
+  gender () const;
+
+  ::gender&
+  gender ();
+
+  void
+  gender (const ::gender&);
+
+  // age
+  //
+  unsigned short
+  age () const;
+
+  unsigned short&
+  age ();
+
+  void
+  age (unsigned short);
+
+private:
+  ...
+};
+
+// people (variable-length)
+//
+class people
+{
+public:
+  people ();
+
+private:
+  people (const people&);
+  people& operator= (const people&);
+
+public:
+  // person
+  //
+  typedef xsde::fix_sequence<person> person_sequence;
+  typedef person_sequence::iterator person_iterator;
+  typedef person_sequence::const_iterator person_const_iterator;
+
+  const person_sequence&
+  person () const;
+
+  person_sequence&
+  person ();
+
+private:
+  ...
+};
+  
+ +

We will examine these classes in detail in the subsequent + sections.

+ +

4.1 Namespaces

+ +

XSD/e maps XML namespaces specified in the targetNamespace + attribute in XML Schema to one or more nested C++ namespaces. By + default, a namespace URI is mapped to a sequence of C++ namespace + names by removing the protocol and host parts and splitting the + rest into a sequence of names with '/' as the name + separator. For example, the http://www.codesynthesis.com/cs/my + XML namespace is mapped to the cs::my C++ namespace.

+ +

The default mapping of namespace URIs to C++ namespaces + can be altered using the --namespace-map and + --namespace-regex compiler options. For example, + to map the http://www.codesynthesis.com/my XML + namespace to the cs::my C++ namespace, we can use + the following option:

+ +
+--namespace-map http://www.codesynthesis.com/my=cs::my
+  
+ +

A vocabulary without a namespace is mapped to the global scope. This + also can be altered with the above options by using an empty name + for the XML namespace. For example, we could place the generated + object model classes for the people.xsd schema + into the records C++ namespace by adding the following + option:

+ +
+--namespace-map =records
+  
+ + +

4.2 Memory Management

+ +

To ensure that objects are allocated and passed efficiently, + the C++/Hybrid mapping divides all object model types into + fixed-length and variable-length. A type is variable-length + if any of the following is true:

+ +
    +
  1. it is an XML Schema list type
  2. + +
  3. it is an XML Schema union type and STL is disabled
  4. + +
  5. it derives from a variable-length type
  6. + +
  7. it contains an element or attribute of a variable-length type
  8. + +
  9. it contains an element or compositor (sequence + or choice) with maxOccurs + greater than one
  10. + +
  11. it is recursive (that is, one of its elements contains + a reference, directly or indirectly, to the type itself)
  12. +
+ +

The following build-in XML Schema types are variable-length: + base64Binary, hexBinary, NMTOKENS, + and IDREFS. Furthermore, if STL is disabled, all + string-based build-in XML Schema types are variable-length, + namely: string, normalizedString, + token, Name, NMTOKEN, + NCName, language, QName, + ID, IDFER, and anyURI.

+ +

Otherwise, a type is fixed-length. As you might have noticed from + the previous code listings, the XSD/e compiler adds a comment before + each generated object model class that states whether it is fixed or + variable-length. For example, the people type is + variable-length because it contains a sequence of person + elements (maxOccurs="unbounded"). If we recompile + the people.xsd schema with the --no-stl + option, the first two types will also become variable-length + since gender inherits from and person + contains elements of the string built-in type. And + when STL is disabled, string is variable-length.

+ +

The object model uses different methods for storing and passing + around fixed-length and variable-length types. Instances of + fixed-length types are stored and passed by value since it is + cheaper to copy than to allocate them dynamically (in the + STL case, the std::string is expected to support the + referenced-counted copy-on-write optimization, which makes + copying cheap).

+ +

Variable-length types are always allocated dynamically and + are stored and passed as pointers. Because copying an instance + of a variable-length type can be expensive, such types make + their copy constructor and copy assignment operators unavailable.

+ +

When you set a value of an element or attribute of a + variable-length type, the object model assumes ownership of + the pointed to object. It expects you to allocate the object with + operator new and will eventually delete it + with operator delete. As an example, let us extend + our people.xsd schema with the following type:

+ +
+<xs:complexType name="staff">
+  <xs:sequence>
+    <xs:element name="permanent" type="people"/>
+    <xs:element name="contract" type="people"/>
+  </xs:sequence>
+</xs:complexType>
+  
+ +

If we compile it with XSD/e, we will get the following C++ + class:

+ +
+// staff (variable-length)
+//
+class staff
+{
+public:
+  staff ();
+
+private:
+  staff (const staff&);
+  staff& operator= (const staff&);
+
+public:
+  // permanent
+  //
+  const people&
+  permanent () const;
+
+  people&
+  permanent ();
+
+  void
+  permanent (people*);
+
+  // contract
+  //
+  const people&
+  contract () const;
+
+  people&
+  contract ();
+
+  void
+  contract (people*);
+
+private:
+  ...
+};
+  
+ +

Notice that unlike, say, the first_name() modifier + function in the person class, the permanent() + and contract() modifiers expect a pointer to the + people object. The following listing shows how + we can create and populate an instance of the staff + class. The use of smart pointers to hold the results of dynamic + allocations is omitted for brevity:

+ +
+people* per = new people;
+people* con = new people;
+
+// Populate per and con.
+
+staff s;
+s->permanent (per) // Assumes ownership or per.
+s->contract (con)  // Assumes ownership or con.
+  
+ +

4.3 Attributes and Elements

+ +

As we have seen before, XSD/e generates a different + set of member functions for elements with different cardinalities. + The C++/Hybrid mapping divides all the possible element and attribute + cardinalities into three cardinality classes: + one, optional, and sequence.

+ +

The one cardinality class covers all elements that should + occur exactly once as well as the required attributes. In our + example, the first-name, last-name, + gender, and age elements as well as + the id attribute belong to this cardinality class. + The following code fragment shows again the accessor and modifier + functions that are generated for the first-name element + in the person class:

+ +
+class person
+{
+  // first-name
+  //
+  const std::string&
+  first_name () const;
+
+  std::string&
+  first_name ();
+
+  void
+  first_name (const std::string&);
+};
+  
+ +

The first two accessor functions return read-only (constant) and + read-write references to the element's value, respectively. The + modifier function sets the new value for the element. Note that + the signature of the modifier function varies depending on + whether the element or attribute is of a fixed or variable-length + type, as was discussed in the previous section.

+ +

The optional cardinality class covers all elements that + can occur zero or one time as well as optional attributes. In our + example, the middle-name element belongs to this + cardinality class. The following code fragment shows again the + accessor and modifier functions that are generated for this element + in the person class:

+ +
+class person
+{
+  // middle-name
+  //
+  bool
+  middle_name_present () const;
+
+  void
+  middle_name_present (bool);
+
+  const std::string&
+  middle_name () const;
+
+  std::string&
+  middle_name ();
+
+  void
+  middle_name (const std::string&);
+};
+  
+ +

Compared to the one cardinality class, optional adds + two extra functions for querying and modifying the element's presence + status. The following example shows how we can use these functions:

+ +
+person& p = ...
+
+if (p.middle_name_present ())
+{
+  cout << p.middle_name () << endl;
+  p.middle_name_present (false); // Reset to the "not present" state.
+}
+  
+ +

Finally, the sequence cardinality class covers all elements + that can occur more than once. In our example, the + person element in the people type + belongs to this cardinality class. The following code fragment shows + again the type definitions as well as the accessor and modifier + functions that are generated for this element in the people + class:

+ +
+class people
+{
+  // person
+  //
+  typedef xsde::fix_sequence<person> person_sequence;
+  typedef person_sequence::iterator person_iterator;
+  typedef person_sequence::const_iterator person_const_iterator;
+
+  const person_sequence&
+  person () const;
+
+  person_sequence&
+  person ();
+};
+  
+ +

The person_sequence type is a sequence container for the + element's values. It has an interface similar to std::vector + and we will discuss it in more detail shortly. The person_iterator + and person_const_iterator types are read-write and read-only + (constant) iterators for the person_sequence + container.

+ +

Unlike other two cardinality classes, the sequence class + only provides accessor functions that return read-only (constant) + and read-write references to the sequence container. The + modification of the element values is performed my manipulating + the returned sequence container and elements that it contains.

+ +

In the remainder of this section we will examine the interfaces + of the sequence containers which differ slightly depending on + whether the element type is fixed or variable-length and whether + C++ exceptions are enabled. Also, when STL is disabled, string + sequences have a special interface which is also discussed + below.

+ +

When exceptions are enabled, the fixed-length type sequences + are implemented in terms of the following class template:

+ +
+template <typename T>
+class fix_sequence
+{
+public:
+  typedef T         value_type;
+  typedef T*        pointer;
+  typedef const T*  const_pointer;
+  typedef T&        reference;
+  typedef const T&  const_reference;
+
+  typedef size_t    size_type;
+  typedef ptrdiff_t difference_type;
+
+  typedef T*        iterator;
+  typedef const T*  const_iterator;
+
+public:
+  fix_sequence ();
+
+  void
+  swap (fix_sequence&);
+
+private:
+  fix_sequence (const fix_sequence&);
+
+  fix_sequence&
+  operator= (fix_sequence&);
+
+public:
+  iterator
+  begin ();
+
+  const_iterator
+  begin () const;
+
+  iterator
+  end ();
+
+  const_iterator
+  end () const;
+
+  T&
+  front ();
+
+  const T&
+  front () const;
+
+  T&
+  back ();
+
+  const T&
+  back () const;
+
+  T&
+  operator[] (size_t);
+
+  const T&
+  operator[] (size_t) const;
+
+public:
+  bool
+  empty () const;
+
+  size_t
+  size () const;
+
+  size_t
+  capacity () const;
+
+  size_t
+  max_size () const;
+
+public:
+  void
+  clear ();
+
+  void
+  pop_back ();
+
+  iterator
+  erase (iterator);
+
+  void
+  push_back (const T&);
+
+  iterator
+  insert (iterator, const T&);
+
+  void
+  reserve (size_t);
+};
+  
+ +

When C++ exceptions are disabled, the signatures of the + push_back(), insert(), and + reserve() functions change as follows:

+ +
+template <typename T>
+class fix_sequence
+{
+public:
+  enum error
+  {
+    error_none,
+    error_no_memory
+  };
+
+  ...
+
+public:
+  error
+  push_back (const T&);
+
+  error
+  insert (iterator, const T&);
+
+  error
+  insert (iterator, const T&, iterator& result);
+
+  error
+  reserve (size_t);
+};
+  
+ +

That is, the functions that may require memory allocation + now return an error code that you will need to check in + order to detect the out of memory condition.

+ +

When exceptions are enabled, the variable-length type sequences + are implemented in terms of the following class template:

+ +
+template <typename T>
+class var_sequence
+{
+public:
+  typedef T         value_type;
+  typedef T*        pointer;
+  typedef const T*  const_pointer;
+  typedef T&        reference;
+  typedef const T&  const_reference;
+
+  typedef size_t    size_type;
+  typedef ptrdiff_t difference_type;
+
+  typedef <implementation details> iterator;
+  typedef <implementation details> const_iterator;
+
+public:
+  var_sequence ();
+
+  void
+  swap (var_sequence&);
+
+private:
+  var_sequence (const var_sequence&);
+
+  var_sequence&
+  operator= (var_sequence&);
+
+public:
+  iterator
+  begin ();
+
+  const_iterator
+  begin () const;
+
+  iterator
+  end ();
+
+  const_iterator
+  end () const;
+
+  T&
+  front ();
+
+  const T&
+  front () const;
+
+  T&
+  back ();
+
+  const T&
+  back () const;
+
+  T&
+  operator[] (size_t);
+
+  const T&
+  operator[] (size_t) const;
+
+public:
+  bool
+  empty () const;
+
+  size_t
+  size () const;
+
+  size_t
+  capacity () const;
+
+  size_t
+  max_size () const;
+
+public:
+  void
+  clear ();
+
+  void
+  pop_back ();
+
+  iterator
+  erase (iterator);
+
+  void
+  push_back (T*);
+
+  iterator
+  insert (iterator, T*);
+
+  error
+  reserve (size_t);
+};
+  
+ +

Most of this interface is identical to the fixed-length type + version except for the push_back() and + insert() functions. Similar to the modifier + functions for elements and attributes of variable-length + types, these two functions expect a pointer to the + dynamically-allocated instance of the type and assume + ownership of the passed object. To simplify error handling, + these two functions delete the passed object if the reallocation + of the underlying sequence buffer fails.

+ +

When C++ exceptions are disabled, the push_back(), + insert(), and reserve() functions + return an error code to signal the out of memory condition:

+ +
+template <typename T>
+class var_sequence
+{
+public:
+  enum error
+  {
+    error_none,
+    error_no_memory
+  };
+
+  ...
+
+public:
+  error
+  push_back (T*);
+
+  error
+  insert (iterator, T*);
+
+  error
+  insert (iterator, T*, iterator& result);
+
+  error
+  reserve (size_t);
+};
+  
+ + +

When STL is enabled, the string sequence have the same + interface as fix_sequence<std::string>. When + STL is disabled and strings are mapped to char*, + the string sequence has a special interface. When C++ exceptions are + enabled, it has the following definition:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    typedef char*         value_type;
+    typedef char**        pointer;
+    typedef const char**  const_pointer;
+    typedef char*         reference;
+    typedef const char*   const_reference;
+
+    typedef size_t        size_type;
+    typedef ptrdiff_t     difference_type;
+
+    typedef char** iterator;
+    typedef const char* const* const_iterator;
+
+    string_sequence ();
+
+    void
+    swap (string_sequence&);
+
+  private:
+    string_sequence (string_sequence&);
+
+    string_sequence&
+    operator= (string_sequence&);
+
+  public:
+    iterator
+    begin ();
+
+    const_iterator
+    begin () const;
+
+    iterator
+    end ();
+
+    const_iterator
+    end () const;
+
+    char*
+    front ();
+
+    const char*
+    front () const;
+
+    char*
+    back ();
+
+    const char*
+    back () const;
+
+    char*
+    operator[] (size_t);
+
+    const char*
+    operator[] (size_t) const;
+
+  public:
+    bool
+    empty () const;
+
+    size_t
+    size () const;
+
+    size_t
+    capacity () const;
+
+    size_t
+    max_size () const;
+
+  public:
+    void
+    clear ();
+
+    void
+    pop_back ();
+
+    iterator
+    erase (iterator);
+
+    void
+    push_back (char*);
+
+    void
+    push_back_copy (const char*);
+
+    iterator
+    insert (iterator, char*);
+
+    void
+    reserve (size_t);
+
+    // Detach a string from the sequence at a given position.
+    // The string pointer at this position in the sequence is
+    // set to 0.
+    //
+    char*
+    detach (iterator);
+  };
+}
+  
+ +

The push_back() and insert() functions + assume ownership of the passed string which should be allocated + with operator new[] and will be deallocated + with operator delete[] by the string_sequence + object. Similar to var_sequence, these two functions + free the passed string if the reallocation of the underlying + sequence buffer fails. The push_back_copy() + function makes a copy of the passed string. + If you detach the underlying element string, then it should + eventually be deallocated with operator delete[].

+ +

When C++ exceptions are disabled, the signatures of the + push_back(), push_back_copy(), + insert(), and reserve() functions + in the string_sequence class change as follows:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    ...
+
+  public:
+    error
+    push_back (char*);
+
+    error
+    push_back_copy (const char*);
+
+    error
+    insert (iterator, char*);
+
+    error
+    insert (iterator, char*, iterator& result);
+
+    error
+    reserve (size_t);
+  };
+}
+  
+ +

4.4 Compositors

+ +

The XML Schema language provides three compositor constructs that + are used to group elements: all, sequence, + and choice. If a compositor has an optional + or sequence cardinality class (see Section + 4.3, "Attributes and Elements") or if a compositor is + inside choice, then the C++/Hybrid mapping generates + a nested class for such a compositor as well as a set of accessor + and modifier functions similar to the ones defined for elements + and attributes. Otherwise, the member functions, corresponding + to elements defined in a compositor, are generated directly in + the containing class.

+ +

Compositor classes are either fixed or variable-length and + obey the same storage and passing rules as object model + classes corresponding to XML Schema types (see Section + 4.2, "Memory Management"). Consider the following schema + fragment as an example:

+ +
+<complexType name="type">
+  <sequence>
+    <sequence minOccurs="0">
+      <element name="a" type="int"/>
+      <element name="b" type="string" maxOccurs="unbounded"/>
+    </sequence>
+    <sequence maxOccurs="unbounded">
+      <element name="c" type="int"/>
+      <element name="d" type="string"/>
+    </sequence>
+  </sequence>
+</complexType>
+  
+ +

The corresponding object model class is shown below:

+ +
+// type (variable-length)
+//
+class type
+{
+public:
+  type ();
+
+private:
+  type (const type&);
+  type& operator= (const type&);
+
+public:
+  // sequence (variable-length)
+  //
+  class sequence_type
+  {
+  public:
+    sequence_type ();
+
+  private:
+    sequence_type (const sequence_type&);
+    sequence_type& operator= (const sequence_type&);
+
+  public:
+    // a
+    //
+    int
+    a () const;
+
+    int&
+    a ();
+
+    void
+    a (int);
+
+    // b
+    //
+    typedef xsde::string_sequence b_sequence;
+    typedef b_sequence::iterator b_iterator;
+    typedef b_sequence::const_iterator b_const_iterator;
+
+    const b_sequence&
+    b () const;
+
+    b_sequence&
+    b ();
+
+  private:
+    ...
+  };
+
+  bool
+  sequence_present () const;
+
+  void
+  sequence_present (bool);
+
+  const sequence_type&
+  sequence () const;
+
+  sequence_type&
+  sequence ();
+
+  void
+  sequence (sequence_type*);
+
+  // sequence1 (fixed-length)
+  //
+  class sequence1_type
+  {
+  public:
+    sequence1_type ();
+    sequence1_type (const sequence1_type&);
+    sequence1_type& operator= (const sequence1_type&);
+
+    // c
+    //
+    int
+    c () const;
+
+    int&
+    c ();
+
+    void
+    c (int);
+
+    // d
+    //
+    const std::string&
+    d () const;
+
+    std::string&
+    d ();
+
+    void
+    d (const std::string&);
+
+  private:
+    ...
+  };
+
+  typedef xsde::fix_sequence<sequence1_type> sequence1_sequence;
+  typedef sequence1_sequence::iterator sequence1_iterator;
+  typedef sequence1_sequence::const_iterator sequence1_const_iterator;
+
+  const sequence1_sequence&
+  sequence1 () const;
+
+  sequence1_sequence&
+  sequence1 ();
+
+private:
+  ...
+};
+  
+ +

The content of the outer sequence compositor is + generated in-line since this compositor belongs to the one + cardinality class. The first nested sequence compositor + is optional (minOccurs="0"), which results in a corresponding + nested class. Notice that the sequence_type is + variable-length and the accessor and modifier functions corresponding + to this sequence compositor are the same as for an + optional element or attribute. Similarly, the second nested + compositor is of the sequence cardinality class + (maxOccurs="unbounded"), which also results in a + nested class and a set of accessor functions.

+ +

Generated code corresponding to an all and + sequence compositor, whether in-line or as a + nested class, simply define accessor and modifier functions + for the elements that this compositor contains. For the + choice compositor, on the other hand, + additional types and functions are generated to support + querying and selecting the choice arm that is in effect. + Consider the following simple example:

+ +
+<complexType name="type">
+  <choice>
+    <element name="a" type="int"/>
+    <element name="b" type="string"/>
+    <element name="c" type="boolean"/>
+  </choice>
+</complexType>
+  
+ + +

The corresponding object model class is shown next:

+ +
+// type (fixed-length)
+//
+class type
+{
+public:
+  type ();
+  type (const type&);
+  type& operator= (const type&);
+
+  // choice
+  //
+  enum choice_arm_tag
+  {
+    a_tag,
+    b_tag,
+    c_tag
+  };
+
+  choice_arm_tag
+  choice_arm () const;
+
+  void
+  choice_arm (choice_arm_tag);
+
+  // a
+  //
+  int
+  a () const;
+
+  int&
+  a ();
+
+  void
+  a (int);
+
+  // b
+  //
+  const std::string&
+  b () const;
+
+  std::string&
+  b ();
+
+  void
+  b (const std::string&);
+
+  // c
+  //
+  bool
+  c () const;
+
+  bool&
+  c ();
+
+  void
+  c (bool);
+
+private:
+  ...
+};
+  
+ +

The extra type is the choice_arm_tag enumeration + which defines a set of tags corresponding to each choice arm. + There are also the choice_arm() accessor and modifier + functions that can be used to query and set the current choice arm. + The following code fragment shows how we can use this class:

+ +
+type& x = ...
+
+switch (x.choice_arm ())
+{
+case type::a_tag:
+  {
+    cout << "a: " << x.a () << endl;
+    break;
+  }
+case type::b_tag:
+  {
+    cout << "b: " << x.b () << endl;
+    break;
+  }
+case type::c_tag:
+  {
+    cout << "c: " << x.c () << endl;
+    break;
+  }
+}
+
+// Modifiers automatically set the corresponding arm.
+//
+x.a (10);
+
+// For accessors we need to select the arm explicitly.
+//
+x.choice_arm (type::b_tag);
+x.b () = "b";
+  
+ +

The following slightly more complex example triggers the generation of + nested classes for the choice compositor as well as for + the sequence compositor inside choice. + Notice that the nested class for sequence is generated + because it is in choice even though its cardinality + class is one.

+ +
+<complexType name="type">
+  <choice maxOccurs="unbounded">
+    <sequence>
+      <element name="a" type="int"/>
+      <element name="b" type="string"/>
+    </sequence>
+    <element name="c" type="boolean"/>
+  </choice>
+</complexType>
+  
+ +

The corresponding object model class is shown next:

+ +
+// type (variable-length)
+//
+class type
+{
+public:
+  type ();
+
+private:
+  type (const type&);
+  type& operator= (const type&);
+
+public:
+  // choice (fixed-length)
+  //
+  class choice_type
+  {
+  public:
+    choice_type ();
+    choice_type (const choice_type&);
+    choice_type& operator= (const choice_type&);
+
+    enum choice_arm_tag
+    {
+      sequence_tag,
+      c_tag
+    };
+
+    choice_arm_tag
+    choice_arm () const;
+
+    void
+    choice_arm (choice_arm_tag);
+
+    // sequence (fixed-length)
+    //
+    class sequence_type
+    {
+    public:
+      sequence_type ();
+      sequence_type (const sequence_type&);
+      sequence_type& operator= (const sequence_type&);
+
+      // a
+      //
+      int
+      a () const;
+
+      int&
+      a ();
+
+      void
+      a (int);
+
+      // b
+      //
+      const std::string&
+      b () const;
+
+      std::string&
+      b ();
+
+      void
+      b (const std::string&);
+
+    private:
+      ...
+    };
+
+    const sequence_type&
+    sequence () const;
+
+    sequence_type&
+    sequence ();
+
+    void
+    sequence (const sequence_type&);
+
+    // c
+    //
+    bool
+    c () const;
+
+    bool&
+    c ();
+
+    void
+    c (bool);
+
+  private:
+    ...
+  };
+
+  typedef xsde::fix_sequence<choice_type> choice_sequence;
+  typedef choice_sequence::iterator choice_iterator;
+  typedef choice_sequence::const_iterator choice_const_iterator;
+
+  const choice_sequence&
+  choice () const;
+
+  choice_sequence&
+  choice ();
+
+private:
+  ...
+};
+  
+ +

4.5 Accessing the Object Model

+ +

In this section we will examine how to get to the information + stored in the object model for the person records vocabulary + introduced at the beginning of this chapter. The following + application accesses and prints the contents of the + people.xml file:

+ +
+#include <memory>
+#include <iostream>
+
+#include "people.hxx"
+#include "people-pimpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+  // Parse.
+  //
+  people_paggr people_p;
+  xml_schema::document_pimpl doc_p (people_p.root_parser (),
+                                    people_p.root_name ());
+  people_p.pre ();
+  doc_p.parse ("people.xml");
+  auto_ptr<people> ppl (people_p.post ());
+
+  // Iterate over individual person records.
+  //
+  people::person_sequence& ps = ppl->person ();
+
+  for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+  {
+    person& p = *i;
+
+    // Print names: first-name and last-name are required elements,
+    // middle-name is optional.
+    //
+    cout << "name:   " << p.first_name () << " ";
+
+    if (p.middle_name_present ())
+      cout << p.middle_name () << " ";
+
+    cout << p.last_name () << endl;
+
+    // Print gender, age, and id which are all required.
+    //
+    cout << "gender: " << p.gender () << endl
+         << "age:    " << p.age () << endl
+         << "id:     " << p.id () << endl
+         << endl;
+  }
+}
+  
+ +

This code shows common patterns of accessing elements and attributes + with different cardinality classes. For the sequence element + (person in the people type) we first obtain a + reference to the container and then iterate over individual + records. The values of elements and attributes with the + one cardinality class (first-name, + last-name, gender, age, + and id) can be obtained directly by calling the + corresponding accessor functions. For the optional + middle-name element we first check if the value is present + and only then call the corresponding accessor to retrieve it.

+ +

Note that when we want to reduce typing by creating a variable + representing a fragment of the object model that we are currently + working with (ps and p above), we obtain + a reference to that fragment instead of making a copy. This is + generally a good rule to follow when creating efficient + applications.

+ +

If we run the above application on our sample + people.xml, the output looks as follows:

+ +
+name:   John Doe
+gender: male
+age:    32
+id:     1
+
+name:   Jane Mary Doe
+gender: female
+age:    28
+id:     2
+  
+ + +

4.6 Modifying the Object Model

+ +

In this section we will examine how to modify the information + stored in the object model for our person records vocabulary. + The following application changes the contents of the + people.xml file:

+ +
+#include <memory>
+#include <iostream>
+
+#include "people.hxx"
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+  // Parse.
+  //
+  people_paggr people_p;
+  xml_schema::document_pimpl doc_p (people_p.root_parser (),
+                                    people_p.root_name ());
+  people_p.pre ();
+  doc_p.parse ("people.xml");
+  auto_ptr<people> ppl (people_p.post ());
+
+  // Iterate over individual person records and increment
+  // the age.
+  //
+  people::person_sequence& ps = ppl->person ();
+
+  for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+  {
+    i->age ()++; // Alternative way: i->age (i->age () + 1)
+  }
+
+  // Add middle-name to the first record and remove it from
+  // the second.
+  //
+  person& john = ps[0];
+  person& jane = ps[1];
+
+  john.middle_name ("Mary");
+  jane.middle_name_present (false);
+
+  // Add another John record.
+  //
+  ps.push_back (john);
+
+  // Serialize the modified object model to XML.
+  //
+  people_saggr people_s;
+  xml_schema::document_simpl doc_s (people_s.root_serializer (),
+                                    people_s.root_name ());
+  people_s.pre (*ppl);
+  doc_s.serialize (cout);
+  people_s.post ();
+}
+  
+ +

The first modification the above application performs is iterating + over person records and incrementing the age value. This code + fragment shows how to modify the value of a required attribute + or element. The next modification shows how to set a new value + for the optional middle-name element as well + as clear its value. Finally, the example adds a copy of the + John Doe record to the person element sequence.

+ +

Note that in this case using references for the ps, + john, and jane variables is no longer + a performance improvement but a requirement for the application + to function correctly. If we hadn't used references, all our changes + would have been made on copies without affecting the object model.

+ +

If we run the above application on our sample people.xml, + the output looks as follows:

+ +
+<?xml version="1.0"?>
+<people>
+
+  <person id="1">
+    <first-name>John</first-name>
+    <middle-name>Mary</middle-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>33</age>
+  </person>
+
+  <person id="2">
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>29</age>
+  </person>
+
+  <person id="1">
+    <first-name>John</first-name>
+    <middle-name>Mary</middle-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>33</age>
+  </person>
+
+</people>
+  
+ +

4.7 Creating the Object Model from Scratch

+ +

In this section we will examine how to create a new object model + for our person records vocabulary. The following application + recreates the content of the original people.xml + file:

+ +
+#include <iostream>
+
+#include "people.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+  people ppl;
+  people::person_sequence& ps = ppl.person ();
+
+  // John
+  //
+  {
+    person p;
+    p.first_name ("John");
+    p.last_name ("Doe");
+    p.age (32);
+    p.id (1);
+
+    gender g;
+    g.assign ("male");
+    p.gender (g);
+
+    ps.push_back (p);
+  }
+
+  // Jane
+  //
+  {
+    person p;
+    p.first_name ("Jane");
+    p.middle_name ("Mary");
+    p.last_name ("Doe");
+    p.age (28);
+    p.id (2);
+
+    gender g;
+    g.assign ("male");
+    p.gender (g);
+
+    ps.push_back (p);
+  }
+
+  // Serialize the object model to XML.
+  //
+  people_saggr people_s;
+  xml_schema::document_simpl doc_s (people_s.root_serializer (),
+                                    people_s.root_name ());
+  people_s.pre (ppl);
+  doc_s.serialize (cout);
+  people_s.post ();
+}
+  
+ +

The only new part in the above application is the calls + to the people and person + constructors. As a general rule, a newly created instance + does not assign any values to its elements and attributes. + That is, members with the one cardinality + class are left uninitialized, members with the optional + cardinality class are set to the "not present" state, + and members with the sequence cardinality class + have empty containers. After the instance has been + created, we can set its element and attribute values + using the modifier functions.

+ +

The above application produces the following output:

+ +
+<?xml version="1.0" ?>
+<people>
+
+  <person id="1">
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+
+  <person id="2">
+    <first-name>Jane</first-name>
+    <middle-name>Mary</middle-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+
+</people>
+  
+ +

4.8 Customizing the Object Model

+ +

Sometimes it is desirable to be able to store extra, + application-specific data in some object model classes or + nested compositor classes. Cases where this functionality + may be required include handling of typeless content + matched by XML Schema wildcards as well as a need for + an application to pass extra data as part of the object + model. The C++/Hybrid mapping provides a light-weight + mechanism for storing custom data by allowing you to add + a sequence of opaque objects, stored as void*, + to select generated classes. It is also possible to + customize the parsing and serialization code for such + classes in order to populate the custom data sequence + during parsing and later serialize it to XML. See + Section 6.1, "Customizing Parsers and + Serializers" for details.

+ +

To instruct the XSD/e compiler to include custom data + in a specific object model class, we need to use the + --custom-data option with the corresponding + XML Schema type name as its argument. To include custom + data into a nested compositor class, use its qualified + name starting with the XML Schema type, for example + type::sequence1. If we would like to + add the ability to store custom data in the generated + person class for our person records + vocabulary, we can compile people.xsd + like this:

+ +
+$ xsde cxx-hybrid --custom-type person people.xsd
+  
+ +

The resulting person class will have the + following extra set of type definitions and functions:

+ + +
+// person (variable-length)
+//
+class person
+{
+public:
+
+  ...
+
+  // Custom data.
+  //
+  typedef xsde::data_sequence custom_data_sequence;
+  typedef custom_data_sequence::iterator custom_data_iterator;
+  typedef custom_data_sequence::const_iterator custom_data_const_iterator;
+
+  const custom_data_sequence&
+  custom_data () const;
+
+  custom_data_sequence&
+  custom_data ();
+};
+  
+ +

Notice also that the person class is now variable-length + since it contains a sequence. When C++ exceptions are enabled, the + custom data sequence has the following interface:

+ +
+class data_sequence
+{
+public:
+  typedef void*         value_type;
+  typedef void**        pointer;
+  typedef const void**  const_pointer;
+  typedef void*         reference;
+  typedef const void*   const_reference;
+
+  typedef size_t        size_type;
+  typedef ptrdiff_t     difference_type;
+
+  typedef void** iterator;
+  typedef const void* const* const_iterator;
+
+  typedef void (*destroy_func) (void* data, size_t pos);
+
+public:
+  data_sequence ();
+
+  void
+  destructor (destroy_func);
+
+  void
+  swap (data_sequence&);
+
+private:
+  data_sequence (const data_sequence&);
+
+  data_sequence&
+  operator= (data_sequence&);
+
+public:
+  iterator
+  begin ();
+
+  const_iterator
+  begin () const;
+
+  iterator
+  end ();
+
+  const_iterator
+  end () const;
+
+  void*
+  front ();
+
+  const void*
+  front () const;
+
+  void*
+  back ();
+
+  const void*
+  back () const;
+
+  void*
+  operator[] (size_t);
+
+  const void*
+  operator[] (size_t) const;
+
+public:
+  bool
+  empty () const;
+
+  size_t
+  size () const;
+
+  size_t
+  capacity () const;
+
+  size_t
+  max_size () const;
+
+public:
+  void
+  clear ();
+
+  void
+  pop_back ();
+
+  iterator
+  erase (iterator);
+
+  void
+  push_back (void*);
+
+  iterator
+  insert (iterator, void*);
+
+  void
+  reserve (size_t);
+};
+  
+ +

The destructor() modifier allows you to specify + the clean up function used to free the sequence elements. + The second argument in this clean up function is the position + of the element in the sequence that is being freed. This allows + you to store objects of different types in the same custom + data sequence. The push_back() and insert() + functions free the passed object if the reallocation of the + underlying sequence buffer fails.

+ +

When exceptions are disabled, the push_back(), + insert(), and reserve() functions + return an error code to signal the out of memory condition:

+ +
+class data_sequence
+{
+public:
+  enum error
+  {
+    error_none,
+    error_no_memory
+  };
+
+  ...
+
+public:
+  error
+  push_back (void*);
+
+  error
+  insert (iterator, void*);
+
+  error
+  insert (iterator, void*, iterator& result);
+
+  error
+  reserve (size_t);
+};
+  
+ +

The following code fragment shows how we can store and retrieve + custom data in the person class:

+ +
+class data
+{
+  ...
+};
+
+void
+destroy_data (void* p, size_t)
+{
+  delete static_cast<data*> (p);
+}
+
+person& = ...;
+person::custom_data_sequence& cd = p.custom_data ();
+
+cd.destructor (&destroy_data);
+
+// Store.
+//
+data* d = new data;
+cd.push_back (d);
+
+// Retrieve.
+//
+for (person::custom_data_iterator i = cd.begin (); i != cd.end (); ++i)
+{
+  data* d = static_cast<data*> (*i);
+}
+  
+ + + + + +

5 Mapping for Built-In XML Schema Types

+ +

In XML Schema, built-in types, such as int, + string, etc., are defined in the XML Schema namespace. + By default this namespace is mapped to C++ namespace + xml_schema (this mapping can be altered + with the --namespace-map option). The following table + summarizes the mapping of XML Schema built-in types to C++ types + in the C++/Hybrid mapping. Declarations for these types are + automatically included into each generated header file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
XML Schema typeAlias in the xml_schema namespaceC++ type
fixed-length integral types
bytebytesigned char
unsignedByteunsigned_byteunsigned char
shortshort_short
unsignedShortunsigned_shortunsigned short
intint_int
unsignedIntunsigned_intunsigned int
longlong_long or
long long
+ Section 3.5, "64-bit Integer Type"
unsignedLongunsigned_longunsigned long or + unsigned long long
+ Section 3.5, "64-bit Integer Type"
arbitrary-length integral types
integerintegerlong
nonPositiveIntegernon_positive_integerlong
nonNegativeIntegernon_negative_integerunsigned long
positiveIntegerpositive_integerunsigned long
negativeIntegernegative_integerlong
boolean types
booleanbooleanbool
fixed-precision floating-point types
floatfloat_float
doubledouble_double
arbitrary-precision floating-point types
decimaldecimaldouble
string types
stringstringstd::string or char*
+ Section 3.1, "Standard Template Library"
normalizedStringnormalized_stringstd::string or char*
+ Section 3.1, "Standard Template Library"
tokentokenstd::string or char*
+ Section 3.1, "Standard Template Library"
Namenamestd::string or char*
+ Section 3.1, "Standard Template Library"
NMTOKENnmtokenstd::string or char*
+ Section 3.1, "Standard Template Library"
NMTOKENSnmtokensSection 5.2, "Mapping for NMTOKENS and IDREFS"
NCNamencnamestd::string or char*
+ Section 3.1, "Standard Template Library"
languagelanguagestd::string or char*
+ Section 3.1, "Standard Template Library"
qualified name
QNameqnameSection 5.1, "Mapping for QName"
ID/IDREF types
IDidstd::string or char*
+ Section 3.1, "Standard Template Library"
IDREFidrefstd::string or char*
+ Section 3.1, "Standard Template Library"
IDREFSidrefsSection 5.2, "Mapping for NMTOKENS and IDREFS"
URI types
anyURIuristd::string or char*
+ Section 3.1, "Standard Template Library"
binary types
base64Binarybase64_binarySection 5.3, "Mapping for base64Binary and hexBinary"
hexBinaryhex_binarySection 5.3, "Mapping for base64Binary and hexBinary"
date/time types
datedateSection 5.5, "Mapping for date"
dateTimedate_timeSection 5.6, "Mapping for dateTime"
durationdurationSection 5.7, "Mapping for duration"
gDaygdaySection 5.8, "Mapping for gDay"
gMonthgmonthSection 5.9, "Mapping for gMonth"
gMonthDaygmonth_daySection 5.10, "Mapping for gMonthDay"
gYeargyearSection 5.11, "Mapping for gYear"
gYearMonthgyear_monthSection 5.12, "Mapping for gYearMonth"
timetimeSection 5.13, "Mapping for time"
+ +

As you can see from the table above a number of built-in + XML Schema types are mapped to fundamental C++ types such + as int or bool. All string-based + XML Schema types are mapped to either std::string + or char*, depending on whether the use of STL is + enabled or not. A number of built-in types, such as + QName, the binary types, and the date/time types, + do not have suitable fundamental or standard C++ types to map to. + These types are implemented from scratch in the XSD/e runtime + and are discussed in more detail in the subsequent sections.

+ +

In cases where the schema calls for an inheritance from a built-in + type which is mapped to a fundamental C++ type, a special base + type corresponding to the fundamental type and defined in the + xml_schema namespace is used (C++ does not allow + inheritance from fundamental types). For example:

+ +
+<complexType name="measure">
+  <simpleContent>
+    <extension base="int">
+      <attribute name="unit" type="string" use="required"/>
+    </extension>
+  </simpleContent>
+</complexType>
+  
+ +

The corresponding object model class is shown below:

+ +
+// measure (fixed-length)
+//
+class measure: public xml_schema::int_base
+{
+public:
+  measure ();
+  measure (const measure&);
+  measure& operator= (const measure&);
+
+  // unit
+  //
+  const std::string&
+  unit () const;
+
+  std::string&
+  unit ();
+
+  void
+  unit (const std::string&);
+
+private:
+  ...
+};
+  
+ +

The xml_schema::int_base class has the following + interface:

+ +
+namespace xml_schema
+{
+  class int_base
+  {
+  public:
+    int_base ();
+
+    int_base&
+    operator= (int);
+
+  public:
+    int
+    base_value () const;
+
+    int&
+    base_value ();
+
+    void
+    base_value (int);
+
+    operator const int& () const;
+    operator int& ();
+  };
+}
+  
+ +

All other base types for fundamental C++ types have similar + interfaces. The only exception is the base type for string + types when STL is disabled:

+ +
+namespace xml_schema
+{
+  class string_base
+  {
+  public:
+    string_base ();
+
+    string_base&
+    operator= (char* x)
+
+  public:
+    const char*
+    base_value () const;
+
+    char*
+    base_value ();
+
+    void
+    base_value (char* x);
+
+    operator const char* () const;
+    operator char* ();
+  };
+}
+  
+ +

Note that the string_base object assumes ownership + of the strings passed to the assignment operator and the + base_value() modifier.

+ +

5.1 Mapping for QName

+ +

The QName built-in XML Schema type is mapped to the + qname class which represents an XML qualified name. + With STL enabled (Section 3.1, "Standard Template + Library"), it has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (const std::string& name);
+    qname (const std::string& prefix, const std::string& name);
+
+    void
+    swap (qname&);
+
+    const std::string&
+    prefix () const;
+
+    std::string&
+    prefix ();
+
+    void
+    prefix (const std::string&);
+
+    const std::string&
+    name () const;
+
+    std::string&
+    name ();
+
+    void
+    name (const std::string&);
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

When STL is disabled and C++ exceptions are enabled + (Section 3.3, "C++ Exceptions"), the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    void
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    void
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+
+ +

The modifier functions and constructors that have the char* + argument assume ownership of the passed strings which should be allocated + with operator new char[] and will be deallocated with + operator delete[] by the qname object. + If you detach the underlying prefix or name strings, then they + should eventually be deallocated with operator delete[]. +

+ +

Finally, if both STL and C++ exceptions are disabled, the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    error
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    error
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

5.2 Mapping for NMTOKENS and IDREFS

+ +

The NMTOKENS and IDREFS built-in + XML Schema types are mapped to the string sequence type which + is discussed in Section 4.3, "Attributes and + Elements".

+ +

5.3 Mapping for base64Binary and hexBinary

+ +

The base64Binary and hexBinary built-in + XML Schema types are mapped to the buffer class. + With C++ exceptions enabled (Section 3.3, "C++ + Exceptions"), it has the following interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    class bounds {}; // Out of bounds exception.
+
+  public:
+    buffer ();
+
+    explicit
+    buffer (size_t size);
+    buffer (size_t size, size_t capacity);
+    buffer (const void* data, size_t size);
+    buffer (const void* data, size_t size, size_t capacity);
+
+    enum ownership_value { assume_ownership };
+
+    // This constructor assumes ownership of the memory passed.
+    //
+    buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    void
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    bool
+    capacity (size_t);
+
+  public:
+    size_t
+    size () const;
+
+    bool
+    size (size_t);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

The last constructor and the attach() member function + make the buffer instance assume the ownership of the + memory block pointed to by the data argument and + eventually release it by calling operator delete(). + The detach() member function detaches and returns the + underlying memory block which should eventually be released by + calling operator delete(). +

+ +

The capacity() and size() modifier functions + return true if the underlying buffer has moved. The + bounds exception is thrown if the constructor or + attach() member function arguments violate the + (size <= capacity) constraint.

+ +

If C++ exceptions are disabled, the buffer class has + the following interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_bounds,
+      error_no_memory
+    };
+
+    buffer ();
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    error
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    error
+    capacity (size_t);
+
+    error
+    capacity (size_t, bool& moved);
+
+  public:
+    size_t
+    size () const;
+
+    error
+    size (size_t);
+
+    error
+    size (size_t, bool& moved);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

5.4 Time Zone Representation

+ +

The date, dateTime, gDay, + gMonth, gMonthDay, gYear, + gYearMonth, and time XML Schema built-in + types all include an optional time zone component. The following + time_zone base class is used to represent this + information:

+ +
+namespace xml_schema
+{
+  class time_zone
+  {
+  public:
+    time_zone ();
+    time_zone (short hours, short minutes);
+
+    bool
+    zone_present () const;
+
+    void
+    zone_reset ();
+
+    short
+    zone_hours () const;
+
+    void
+    zone_hours (short);
+
+    short
+    zone_minutes () const;
+
+    void
+    zone_minutes (short);
+  };
+
+  bool
+  operator== (const time_zone&, const time_zone&);
+
+  bool
+  operator!= (const time_zone&, const time_zone&);
+}
+  
+ +

The zone_present() accessor function returns true + if the time zone is specified. The zone_reset() modifier + function resets the time zone object to the "not specified" + state. If the time zone offset is negative then both hours and + minutes components should be negative.

+ +

5.5 Mapping for date

+ +

The date built-in XML Schema type is mapped to the + date class which represents a year, a day, and a month + with an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class date: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date ();
+
+    date (int year, unsigned short month, unsigned short day);
+
+    date (int year, unsigned short month, unsigned short day,
+          short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const date&, const date&);
+
+  bool
+  operator!= (const date&, const date&);
+}
+  
+ +

5.6 Mapping for dateTime

+ +

The dateTime built-in XML Schema type is mapped to the + date_time class which represents a year, a month, a day, + hours, minutes, and seconds with an optional time zone. Its interface + is presented below. For more information on the base + xml_schema::time_zone class refer to Section + 5.4, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class date_time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date_time ();
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds);
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const date_time&, const date_time&);
+
+  bool
+  operator!= (const date_time&, const date_time&);
+}
+  
+ +

5.7 Mapping for duration

+ +

The duration built-in XML Schema type is mapped to the + duration class which represents a potentially + negative duration in the form of years, months, days, hours, minutes, + and seconds. Its interface is presented below.

+ +
+namespace xml_schema
+{
+  class duration
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    duration ();
+
+    duration (bool negative,
+              unsigned int years, unsigned int months, unsigned int days,
+              unsigned int hours, unsigned int minutes, double seconds);
+
+    bool
+    negative () const;
+
+    void
+    negative (bool);
+
+    unsigned int
+    years () const;
+
+    void
+    years (unsigned int);
+
+    unsigned int
+    months () const;
+
+    void
+    months (unsigned int);
+
+    unsigned int
+    days () const;
+
+    void
+    days (unsigned int);
+
+    unsigned int
+    hours () const;
+
+    void
+    hours (unsigned int);
+
+    unsigned int
+    minutes () const;
+
+    void
+    minutes (unsigned int);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const duration&, const duration&);
+
+  bool
+  operator!= (const duration&, const duration&);
+}
+  
+ + +

5.8 Mapping for gDay

+ +

The gDay built-in XML Schema type is mapped to the + gday class which represents a day of the month with + an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gday: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gday ();
+
+    explicit
+    gday (unsigned short day);
+
+    gday (unsigned short day, short zone_hours, short zone_minutes);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gday&, const gday&);
+
+  bool
+  operator!= (const gday&, const gday&);
+}
+  
+ +

5.9 Mapping for gMonth

+ +

The gMonth built-in XML Schema type is mapped to the + gmonth class which represents a month of the year + with an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth ();
+
+    explicit
+    gmonth (unsigned short month);
+
+    gmonth (unsigned short month,
+            short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth&, const gmonth&);
+
+  bool
+  operator!= (const gmonth&, const gmonth&);
+}
+  
+ +

5.10 Mapping for gMonthDay

+ +

The gMonthDay built-in XML Schema type is mapped to the + gmonth_day class which represents a day and a month of + the year with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth_day: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth_day ();
+
+    gmonth_day (unsigned short month, unsigned short day);
+
+    gmonth_day (unsigned short month, unsigned short day,
+                short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth_day&, const gmonth_day&);
+
+  bool
+  operator!= (const gmonth_day&, const gmonth_day&);
+}
+  
+ +

5.11 Mapping for gYear

+ +

The gYear built-in XML Schema type is mapped to the + gyear class which represents a year with + an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gyear: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear ();
+
+    explicit
+    gyear (int year);
+
+    gyear (int year, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+  };
+
+  bool
+  operator== (const gyear&, const gyear&);
+
+  bool
+  operator!= (const gyear&, const gyear&);
+}
+  
+ +

5.12 Mapping for gYearMonth

+ +

The gYearMonth built-in XML Schema type is mapped to the + gyear_month class which represents a year and a month + with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gyear_month: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear_month ();
+
+    gyear_month (int year, unsigned short month);
+
+    gyear_month (int year, unsigned short month,
+                 short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gyear_month&, const gyear_month&);
+
+  bool
+  operator!= (const gyear_month&, const gyear_month&);
+}
+  
+ + +

5.13 Mapping for time

+ +

The time built-in XML Schema type is mapped to the + time class which represents hours, minutes, + and seconds with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 5.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    time ();
+
+    time (unsigned short hours, unsigned short minutes, double seconds);
+
+    time (unsigned short hours, unsigned short minutes, double seconds,
+          short zone_hours, short zone_minutes);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const time&, const time&);
+
+  bool
+  operator!= (const time&, const time&);
+}
+  
+ + + +

6 Parsing and Serialization

+ +

As was mentioned in the introduction, the C++/Hybrid mapping + uses the C++/Parser and C++/Serializer mappings for XML parsing + and serialization. If your parsing and serialization requirements + are fairly basic, for example, parsing from and serializing to + a file or a memory buffer, then you don't need to concern yourself + with these two underlying mappings. On the other hand, the C++/Parser + and C++/Serializer mappings provide well-defined APIs which allow + a great amount of flexibility that may be useful in certain situations. + In such cases, you may need to get an understanding of how the + C++/Parser and C++/Serializer mappings work. See the + Embedded + C++/Parser Mapping Getting Started Guide and the + Embedded + C++/Serializer Mapping Getting Started Guide for more detailed + information on these mappings.

+ +

For each type defined in XML Schema, the C++/Parser and + C++/Serializer mappings generate a parser skeleton class and + serializer skeleton class, respectively. These classes manage + parsing/serialization state, convert data between text + and C++ types, and perform XML Schema validation, if enabled. + Parser skeletons deliver the parsed data and serializer + skeletons request the data to be serialized with callbacks. + These callbacks are implemented by parser and serializer + implementation classes that are derived from the skeletons. + If the application uses the C++/Parser and C++/Serializer + mappings directly, these implementation classes are normally + written by the application developer to perform some + application-specific actions. In case of the C++/Hybrid mapping, + these implementations are automatically generated by the XSD/e + compiler to parse XML to object models and to serialize object + models to XML. + To request the generation of parser skeletons and + implementations, you need to specify the --generate-parser + XSD/e command line option. Similarly, to generate serializer + skeletons and implementations, you will need to use the + --generate-serializer option.

+ +

Before an XML document can be parsed or serialized, the + individual parser and serializer implementations need to + be instantiated and connected to each other. Again, if the + application uses the C++/Parser and C++/Serializer mappings + directly, this is done by the application developer. While + you can also do this with the generated C++/Hybrid parser and + serializer implementations, it is easier to request the + generation of parser and serializer aggregate classes with + the --generate-aggregate options. Aggregate + classes instantiate and connect all the necessary individual + parser and serializer implementations for a particular root + element or type. Consider again the hello.xsd + schema from Chapter 2, "Hello World Example":

+ +
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="hello">
+    <xs:sequence>
+      <xs:element name="greeting" type="xs:string"/>
+      <xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="hello" type="hello"/>
+
+</xs:schema>
+  
+ +

If we compile this schema with the --generate-parser, + --generate-serializer, and --generate-aggregate + options, we will have two aggregate classes, hello_paggr + and hello_saggr, generated for the root hello + element. The interface of the hello_paggr class is + presented below:

+ +
+class hello_paggr
+{
+public:
+  hello_paggr ();
+
+  void
+  pre ();
+
+  hello*
+  post ();
+
+  hello_pimpl&
+  root_parser ();
+
+  static const char*
+  root_name ();
+
+  static const char*
+  root_namespace ();
+};
+  
+ +

The pre() and post() functions + call the corresponding callbacks on the root parser + implementation. The root_parser() function + returns the root parser implementation. The root_name() + and root_namespace() functions return the + root element name and namespace, respectively.

+ +

As was shown in Chapter 2, "Hello World Example", + we can use this parser aggregate to create the document parser + (supplied by the C++/Parser mapping) and perform the parsing:

+ +
+hello_paggr hello_p;
+xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+                                  hello_p.root_name ());
+hello_p.pre ();
+doc_p.parse ("hello.xml");
+hello* h = hello_p.post ();
+  
+ +

For more information on the document_pimpl class, + including the other variants of the parse() function + as well as error handling during parsing, see + Chapter 7, + "Document Parser and Error Handling" in the Embedded C++/Parser + Mapping Getting Started Guide.

+ +

The interface of the hello_saggr serializer aggregate + mirrors that of hello_paggr and is presented below:

+ +
+class hello_saggr
+{
+public:
+  hello_saggr ();
+
+  void
+  pre (const hello&);
+
+  void
+  post ();
+
+  hello_simpl&
+  root_serializer ();
+
+  static const char*
+  root_name ();
+
+  static const char*
+  root_namespace ();
+};
+  
+ +

The pre() and post() functions + call the corresponding callbacks on the root serializer + implementation. The root_serializer() function + returns the root serializer implementation. The + root_name() and root_namespace() + functions return the root element name and namespace, + respectively.

+ +

As was shown in Chapter 2, "Hello World Example", + we can use this serializer aggregate to create the document + serializer (supplied by the C++/Serializer mapping) and perform + the serialization:

+ +
+hello_saggr hello_s;
+xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+                                  hello_s.root_name ());
+hello_s.pre (*h);
+doc_s.serialize (std::cout);
+hello_s.post ();
+  
+ +

For more information on the document_simpl class, + including the other variants of the serialize() + function as well as error handling during serialization, see + Chapter 8, + "Document Serializer and Error Handling" in the Embedded + C++/Serializer Mapping Getting Started Guide.

+ +

6.1 Customizing Parsers and Serializers

+ +

The C++/Hybrid mapping allows you to customize the generated + parser and serializer implementations. This mechanism can be + used, for example, to implement filtering, partially + event-driven XML processing, as well as parsing of content + matched by XML Schema wildcards. 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. 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 section expects you to have an understanding + of the C++/Parser and C++/Serializer programming models.

+ +

To request customization of a parser or serializer + implementation, you will need to specify the + --custom-parser or --custom-serializer + option, respectively. The argument format for these two options + is type[=base[/include]]. The type + component is the XML Schema type name being customized. Optional + base is a C++ name that should be given to the + generated version. It is normally used as a base for the custom + implementation. Optional include is the header file + that defines the custom implementation. It is #include'ed + into the generated code immediately after (if base + is specified) or instead of the generated version. The following + examples show how we can use these options:

+ +
+--custom-parser foo
+--custom-parser foo=foo_base_pimpl
+--custom-parser foo=foo_base_pimpl/foo/foo-custom.hxx
+--custom-parser foo=/foo/foo-custom.hxx
+  
+ +

The first version instructs the XSD/e compiler not to generate + the parser implementation for the foo XML Schema + type. The second version instructs the compiler to generate + the parser implementation for type foo but call + it foo_base_pimpl. The third version is similar to the + second except that the compiler generates the #include + directive with the foo/foo-custom.hxx file (which + presumably defines foo_pimpl) right after the + foo_base_pimpl class. The last version instructs + the XSD/e compiler to include foo/foo-custom.hxx + instead of generating the parser implementation for + foo. If you omit the last component, then + you can include the custom parser/serializer definitions + using one of the prologue or epilogue XSD/e compiler options. + See the XSD/e + Compiler Command Line Manual for details.

+ +

Once you specify the --custom-parser or + --custom-serializer option, you will need to + provide the custom implementation. You have a choice of either + basing it on the generated version and overriding some + callbacks or implementing it from scratch.

+ +

In the remainder of this section we will examine how to + customize the people parser and serializer + implementations from the example presented in Chapter 4, + "Working with Object Models". Our custom parser + implementation will filter the records being parsed + based on a person's age. Similarly, the serializer will + only serialize records of a specific gender. The code + presented below is taken from the filter + example in the XSD/e distribution. Other examples + related to parser/serializer customization are + wildcard and streaming.

+ +

First, we compile the people.xsd schema + and instruct the XSD/e compiler to customize the + parser and serializer implementations for the people + XML Schema type:

+ +
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--custom-parser people=people_base_pimpl/people-custom-pimpl.hxx \
+--custom-serializer people=people_base_simpl/people-custom-simpl.hxx \
+--generate-aggregate people.xsd
+  
+ +

The custom people_pimpl parser implementation + is based on the generated version and is saved to + people-custom-pimpl.hxx:

+ +
+class people_pimpl: public people_base_pimpl
+{
+public:
+  void
+  age_filter (unsigned short min, unsigned short max)
+  {
+    min_age_ = min;
+    max_age_ = max;
+  }
+
+  virtual void
+  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);
+  }
+
+private:
+  unsigned short min_age_;
+  unsigned short max_age_;
+};
+  
+ +

Here we override the person() callback and, + if the filter conditions are satisfied, call the original + version which adds the person record to the object model. + Note that if the person object model class + were variable-length, then the instance would be + dynamically allocated and passed as a pointer. In this + situation, if we don't use the object, we need to delete it, + for example:

+ +
+virtual void
+person (const ::person* p)
+{
+  unsigned short age = p->age ();
+
+  if (age >= min_age_ && age <= max_age_)
+    people_base_pimpl::person (p);
+  else
+    delete p;
+}
+  
+ +

The custom people_simpl parser implementation + is also based on the generated version and is saved to + people-custom-simpl.hxx:

+ +
+class people_simpl: public people_base_simpl
+{
+public:
+  void
+  gender_filter (gender g)
+  {
+    gender_ = g;
+  }
+
+  virtual bool
+  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;
+  }
+
+private:
+  gender gender_;
+};
+  
+ +

Here we override the person_next() callback + where we locate the next record that satisfies the filter + conditions. Note that we use the serialization state + provided by the generated people_base_simpl + implementation.

+ +

The following code fragment shows a test driver that uses + the above implementations to filter the data during parsing + and serialization:

+ +
+#include <memory>
+#include <iostream>
+
+#include "people.hxx"
+
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  // 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 ();
+  doc_p.parse (argv[1]);
+  auto_ptr<people> 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 ();
+}
+  
+ +

If we run this test driver on the following XML document:

+ +
+<?xml version="1.0"?>
+<people>
+
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+
+  <person>
+    <first-name>Joe</first-name>
+    <last-name>Dirt</last-name>
+    <gender>male</gender>
+    <age>25</age>
+  </person>
+
+</people>
+  
+ +

We will get the following output:

+ +
+first:  Jane
+last:   Doe
+gender: female
+age:    28
+
+first:  Joe
+last:   Dirt
+gender: male
+age:    25
+
+<people>
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+</people>
+  
+ + + +
+
+ + + + diff --git a/documentation/cxx/hybrid/guide/makefile b/documentation/cxx/hybrid/guide/makefile new file mode 100644 index 0000000..d476fb9 --- /dev/null +++ b/documentation/cxx/hybrid/guide/makefile @@ -0,0 +1,12 @@ +.PHONY: all +all: cxx-hybrid-e-guide.ps cxx-hybrid-e-guide.pdf + +cxx-hybrid-e-guide.pdf: cxx-hybrid-e-guide.ps + ps2pdf14 $< + +cxx-hybrid-e-guide.ps: index.xhtml guide.html2ps + html2ps -f guide.html2ps -o $@ $< + +.PHONY: clean +clean: + rm -f cxx-hybrid-e-guide.ps cxx-hybrid-e-guide.pdf diff --git a/documentation/cxx/parser/guide/figure-1.png b/documentation/cxx/parser/guide/figure-1.png new file mode 100644 index 0000000..15d1723 Binary files /dev/null and b/documentation/cxx/parser/guide/figure-1.png differ diff --git a/documentation/cxx/parser/guide/figure-1.svg b/documentation/cxx/parser/guide/figure-1.svg new file mode 100644 index 0000000..d994a79 --- /dev/null +++ b/documentation/cxx/parser/guide/figure-1.svg @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + class people_pimpl{ void person ();}; + + + + class person_pimpl{ void first_name (string); void last_name (string); void gender (); void age (short); void post_person ();}; + + + + class string_pimpl{ string post_string ();}; + + + class short_pimpl{ short post_short ();}; + + + class gender_pimpl{ void post_gender ();}; + + + + + + + diff --git a/documentation/cxx/parser/guide/guide.html2ps b/documentation/cxx/parser/guide/guide.html2ps new file mode 100644 index 0000000..47d1a32 --- /dev/null +++ b/documentation/cxx/parser/guide/guide.html2ps @@ -0,0 +1,65 @@ +@html2ps { + option { + toc: hb; + colour: 1; + hyphenate: 1; + titlepage: 1; + } + + datefmt: "%B %Y"; + + titlepage { + content: " +
+

Embedded C++/Parser Mapping

+

Getting Started Guide

+

 

+

 

+

 

+

 

+

 

+

 

+
+

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

"; + } + + toc { + indent: 2em; + } + + header { + odd-right: $H; + even-left: $H; + } + + footer { + odd-left: $D; + odd-center: $T; + odd-right: $N; + + even-left: $N; + even-center: $T; + even-right: $D; + } +} + +body { + font-size: 12pt; + text-align: justify; +} + +pre { + font-size: 10pt; +} diff --git a/documentation/cxx/parser/guide/index.xhtml b/documentation/cxx/parser/guide/index.xhtml new file mode 100644 index 0000000..3f589a1 --- /dev/null +++ b/documentation/cxx/parser/guide/index.xhtml @@ -0,0 +1,5236 @@ + + + + + + Embedded C++/Parser Mapping Getting Started Guide + + + + + + + + + + + + + +
+
+ +
+ +
+
Embedded C++/Parser Mapping
+
Getting Started Guide
+ +

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

+ +
+ +

Table of Contents

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preface + + + +
About This Document
More Information
+
1Introduction + + + +
1.1Mapping Overview
1.2Benefits
+
2Hello World Example + + + + + +
2.1Writing XML Document and Schema
2.2Translating Schema to C++
2.3Implementing Application Logic
2.4Compiling and Running
+
3Parser Skeletons + + + + + +
3.1Implementing the Gender Parser
3.2Implementing the Person Parser
3.3Implementing the People Parser
3.4Connecting the Parsers Together
+
4Type Maps + + + + +
4.1Object Model
4.2Type Map File Format
4.3Parser Implementations
+
5Mapping Configuration + + + + + + + + + +
5.1Standard Template Library
5.2Input/Output Stream Library
5.3C++ Exceptions
5.4XML Schema Validation
5.564-bit Integer Type
5.6Parser Reuse
5.7Support for Polymorphism
5.8A Minimal Example
+
6Built-In XML Schema Type Parsers + + + + + + + + + + + + + + +
6.1QName Parser
6.2NMTOKENS and IDREFS Parsers
6.3base64Binary and hexBinary Parsers
6.4Time Zone Representation
6.5date Parser
6.6dateTime Parser
6.7duration Parser
6.8gDay Parser
6.9gMonth Parser
6.10gMonthDay Parser
6.11gYear Parser
6.12gYearMonth Parser
6.13time Parser
+
7Document Parser and Error Handling + + + + + +
7.1Document Parser
7.2Exceptions
7.3Error Codes
7.4Reusing Parsers after an Error
+
Appendix A — Supported XML Schema Constructs
+
+ +

Preface

+ +

About This Document

+ +

The goal of this document is to provide you with an + understanding of the C++/Parser programming model and allow you + to efficiently evaluate XSD/e against your project's technical + requirements. As such, this document is intended for embedded + C++ developers and software architects who are looking for an + embedded XML processing solution. Prior experience with XML + and C++ is required to understand this document. Basic + understanding of XML Schema is advantageous but not expected + or required. +

+ + +

More Information

+ +

Beyond this guide, you may also find the following sources of + information useful:

+ +
    +
  • XSD/e + Compiler Command Line Manual
  • + +
  • The INSTALL file in the XSD/e distribution provides + build instructions for various platforms.
  • + +
  • The examples/cxx/parser/ directory in the XSD/e + distribution contains a collection of examples and a README + file with an overview of each example.
  • + +
  • The xsde-users + mailing list is the place to ask technical questions about XSD/e and the + Embedded C++/Parser mapping. Furthermore, the + archives + may already have answers to some of your questions.
  • + +
+ + + +

1 Introduction

+ +

Welcome to CodeSynthesis XSD/e and the Embedded C++/Parser mapping. + XSD/e is a validating XML parser/serializer generator for mobile and + embedded systems. Embedded C++/Parser is a W3C XML Schema to C++ + mapping that represents an XML vocabulary as a set of parser + skeletons which you can implement to perform XML processing as + required by your application logic. +

+ +

1.1 Mapping Overview

+ +

The Embedded C++/Parser mapping provides event-driven, stream-oriented + XML parsing, XML Schema validation, and C++ data binding. It was + specifically designed and optimized for mobile and embedded + systems where hardware constraints require high efficiency and + economical use of resources. As a result, the generated + parsers are 2-10 times faster than general-purpose validating + XML parsers while at the same time maintaining extremely low static + and dynamic memory footprints. For example, a validating parser + executable can be as small as 120KB in size. The size can be + further reduced by disabling support for XML Schema validation. +

+ +

The generated code and the runtime library are also highly-portable + and, in their minimal configuration, can be used without STL, RTTI, + iostream, C++ exceptions, and C++ templates.

+ +

To speed up application development, the C++/Parser mapping + can be instructed to generate sample parser implementations + and a test driver which can then be filled with the application + logic code. The mapping also provides a wide range of + mechanisms for controlling and customizing the generated code.

+ +

The next chapter shows how to create a simple application + that uses the Embedded C++/Parser mapping to parse, validate, + and extract data from a simple XML instance document. The + following chapters describe the Embedded C++/Parser mapping + in more detail.

+ +

1.2 Benefits

+ +

Traditional XML access APIs such as Document Object Model (DOM) + or Simple API for XML (SAX) as well as general-purpose XML Schema + validators have a number of drawbacks that make them less suitable + for creating mobile and embedded XML processing applications. These + drawbacks include: +

+ +
    +
  • Text-based representation results in inefficient use of + resources.
  • + +
  • Extra validation code that is not used by the application.
  • + +
  • Generic representation of XML in terms of elements, attributes, + and text forces an application developer to write a substantial + amount of bridging code that identifies and transforms pieces + of information encoded in XML to a representation more suitable + for consumption by the application logic.
  • + +
  • String-based flow control defers error detection to runtime. + It also reduces code readability and maintainability.
  • + +
  • Lack of type safety because all information is represented + as text.
  • + +
  • Resulting applications are hard to debug, change, and + maintain.
  • +
+ +

In contrast, statically-typed, vocabulary-specific parser + skeletons produced by the Embedded C++/Parser mapping use + native data representations (for example, integers are passed as + integers, not as text) and include validation code only for + XML Schema constructs that are used in the application. This + results in efficient use of resources and compact object code.

+ +

Furthermore, the parser skeletons allow you to operate in your + domain terms instead of the generic elements, attributes, and + text. Static typing helps catch errors at compile-time rather + than at run-time. Automatic code generation frees you for more + interesting tasks (such as doing something useful with the + information stored in the XML documents) and minimizes the + effort needed to adapt your applications to changes in the + document structure. To summarize, the C++/Parser mapping has + the following key advantages over generic XML access APIs:

+ +
    +
  • Ease of use. The generated code hides all the complexity + associated with recreating the document structure, maintaining the + dispatch state, and converting the data from the text representation + to data types suitable for manipulation by the application logic. + Parser skeletons also provide a convenient mechanism for building + custom in-memory representations.
  • + +
  • Natural representation. The generated parser skeletons + implement parser callbacks as virtual functions with names + corresponding to elements and attributes in XML. As a result, + you process the XML data using your domain vocabulary instead + of generic elements, attributes, and text. +
  • + +
  • Concise code. With a separate parser skeleton for each + XML Schema type, the application implementation is + simpler and thus easier to read and understand.
  • + +
  • Safety. The XML data is delivered to parser callbacks as + statically typed objects. The parser callbacks themselves are virtual + functions. This helps catch programming errors at compile-time + rather than at runtime.
  • + +
  • Maintainability. Automatic code generation minimizes the + effort needed to adapt the application to changes in the + document structure. With static typing, the C++ compiler + can pin-point the places in the application code that need to be + changed.
  • + +
  • Efficiency. The generated parser skeletons use native + data representations and combine data extraction, validation, + and even dispatching in a single step. This makes them much + more efficient than traditional architectures with separate + stages for validation and data extraction/dispatch.
  • +
+ + + + + +

2 Hello World Example

+ +

In this chapter we will examine how to parse a very simple XML + document using the XSD/e-generated C++/Parser skeletons. + + All the code presented in this chapter is based on the hello + example which can be found in the examples/cxx/parser/ + directory of the XSD/e distribution.

+ +

2.1 Writing XML Document and Schema

+ +

First, we need to get an idea about the structure + of the XML documents we are going to process. Our + hello.xml, for example, could look like this:

+ +
+<?xml version="1.0"?>
+<hello>
+
+  <greeting>Hello</greeting>
+
+  <name>sun</name>
+  <name>earth</name>
+  <name>world</name>
+
+</hello>
+      
+ +

Then we can write a description of the above XML in the + XML Schema language and save it into hello.xsd:

+ +
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="hello">
+    <xs:sequence>
+      <xs:element name="greeting" type="xs:string"/>
+      <xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="hello" type="hello"/>
+
+</xs:schema>
+      
+ +

Even if you are not familiar with the XML Schema language, it + should be easy to connect declarations in hello.xsd + to elements in hello.xml. The hello type + is defined as a sequence of the nested greeting and + name elements. Note that the term sequence in XML + Schema means that elements should appear in a particular order + as opposed to appearing multiple times. The name + element has its maxOccurs property set to + unbounde which means it can appear multiple times + in an XML document. Finally, the globally-defined hello + element prescribes the root element for our vocabulary. For an + easily-approachable introduction to XML Schema refer to + XML Schema Part 0: + Primer.

+ +

The above schema is a specification of our vocabulary; it tells + everybody what valid XML instances of our vocabulary should look + like. The next step is to compile this schema to generate C++ parser + skeletons.

+ +

2.2 Translating Schema to C++

+ +

Now we are ready to translate our hello.xsd to C++ parser + skeletons. To do this we invoke the XSD/e compiler from a terminal + (UNIX) or a command prompt (Windows): +

+ +
+$ xsde cxx-parser hello.xsd
+  
+ +

The XSD/e compiler produces two C++ files: hello-pskel.hxx + and hello-pskel.cxx. The following code fragment is taken + from hello-pskel.hxx; it should give you an idea about what + gets generated: +

+ +
+class hello_pskel
+{
+public:
+  // Parser callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual void
+  greeting (const std::string&);
+
+  virtual void
+  name (const std::string&);
+
+  virtual void
+  post_hello ();
+
+  // Parser construction API.
+  //
+  void
+  greeting_parser (xml_schema::string_pskel&);
+
+  void
+  name_parser (xml_schema::string_pskel&);
+
+  void
+  parsers (xml_schema::string_pskel& /* greeting */,
+           xml_schema::string_pskel& /* name */);
+
+private:
+  ...
+};
+  
+ +

The first four member functions shown above are called parser + callbacks. You would normally override them in your implementation + of the parser to do something useful. Let's go through all of + them one by one.

+ +

The pre() function is an initialization callback. It is + called when a new element of type hello is about + to be parsed. You would normally use this function to allocate a new + instance of the resulting type or clear accumulators that are used + to gather information during parsing. The default implementation + of this function does nothing.

+ +

The post_hello() function is a finalization callback. Its + name is constructed by adding the parser skeleton name to the + post_ prefix. The finalization callback is called when + parsing of the element is complete and the result, if any, should + be returned. Note that in our case the return type of + post_hello() is void which means there + is nothing to return. More on parser return types later. +

+ +

You may be wondering why the finalization callback is called + post_hello() instead of post() just + like pre(). The reason for this is that + finalization callbacks can have different return types and + result in function signature clashes across inheritance + hierarchies. To prevent this, the signatures of finalization + callbacks are made unique by adding the type name to their names.

+ +

The greeting() and name() functions are + called when the greeting and name elements + have been parsed, respectively. Their arguments are of type + std::string and contain the data extracted from XML.

+ +

The last three functions are for connecting parsers to each other. + For example, there is a predefined parser for built-in XML Schema type + string in the XSD/e runtime. We will be using + it to parse the contents of greeting and + name elements, as shown in the next section.

+ +

2.3 Implementing Application Logic

+ +

At this point we have all the parts we need to do something useful + with the information stored in XML documents. The first step is + to implement the parser: +

+ +
+#include <iostream>
+#include "hello-pskel.hxx"
+
+class hello_pimpl: public hello_pskel
+{
+public:
+  virtual void
+  greeting (const std::string& g)
+  {
+    greeting_ = g;
+  }
+
+  virtual void
+  name (const std::string& n)
+  {
+    std::cout << greeting_ << ", " << n << "!" << std::endl;
+  }
+
+private:
+  std::string greeting_;
+};
+  
+ +

We left both pre() and post_hello() with the + default implementations; we don't have anything to initialize or + return. The rest is pretty straightforward: we store the greeting + in a member variable and later, when parsing names, use it to + say hello.

+ +

An observant reader my ask what happens if the name + element comes before greeting? Don't we need to + make sure greeting_ was initialized and report + an error otherwise? The answer is no, we don't have to do + any of this. The hello_pskel parser skeleton + performs validation of XML according to the schema from which + it was generated. As a result, it will check the order + of the greeting and name elements + and report an error if it is violated.

+ +

Now it is time to put this parser implementation to work:

+ +
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  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.
+    //
+    xml_schema::document_pimpl doc_p (hello_p, "hello");
+
+    hello_p.pre ();
+    doc_p.parse (argv[1]);
+    hello_p.post_hello ();
+  }
+  catch (const xml_schema::parser_exception& e)
+  {
+    cerr << argv[1] << ":" << e.line () << ":" << e.column ()
+         << ": " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

The first part of this code snippet instantiates individual parsers + and assembles them into a complete vocabulary parser. + xml_schema::string_pimpl is an implementation of a parser + for built-in XML Schema type string. It is provided by + the XSD/e runtime along with parsers for other built-in types (for + more information on the built-in parsers see Chapter 6, + "Built-In XML Schema Type Parsers"). We use string_pimpl + to parse the greeting and name elements as + indicated by the calls to greeting_parser() and + name_parser(). +

+ +

Then we instantiate a document parser (doc_p). The + first argument to its constructor is the parser for + the root element (hello_p in our case). The + second argument is the root element name. +

+ +

The final piece is the calls to pre(), parse(), + and post_hello(). The call to parse() + perform the actual XML parsing while the calls to pre() and + post_hello() make sure that the parser for the root + element can perform proper initialization and cleanup.

+ +

While our parser implementation and test driver are pretty small and + easy to write by hand, for bigger XML vocabularies it can be a + substantial effort. To help with this task XSD/e can automatically + generate sample parser implementations and a test driver from your + schemas. You can request the generation of a sample implementation with + empty function bodies by specifying the --generate-noop-impl + option. Or you can generate a sample implementation that prints the + data store in XML by using the --generate-print-impl + option. To request the generation of a test driver you can use the + --generate-test-driver option. For more information + on these options refer to the + XSD/e + Compiler Command Line Manual. The 'generated' example + in the XSD/e distribution shows the sample implementation generation + feature in action.

+ + +

2.4 Compiling and Running

+ +

After saving all the parts from the previous section in + driver.cxx, we are ready to compile our first + application and run it on the test XML document. On UNIX + this can be done with the following commands: +

+ +
+$ c++ -I.../libxsde -c driver.cxx hello-pskel.cxx
+$ c++ -o driver driver.o hello-pskel.o .../libxsde/xsde/libxsde.a
+$ ./driver hello.xml
+Hello, sun!
+Hello, moon!
+Hello, world!
+  
+ +

Here .../libxsde represents the path to the + libxsde directory in the XSD/e distribution. + We can also test the error handling. To test XML well-formedness + checking, we can try to parse hello-pskel.hxx:

+ +
+$ ./driver hello-pskel.hxx
+hello-pskel.hxx:1:0: not well-formed (invalid token)
+  
+ +

We can also try to parse a valid XML but not from our + vocabulary, for example hello.xsd:

+ +
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+  
+ + + + + +

3 Parser Skeletons

+ +

As we have seen in the previous chapter, the XSD/e compiler generates + a parser skeleton class for each type defined in XML Schema. In + this chapter we will take a closer look at different functions + that comprise a parser skeleton as well as the way to connect + our implementations of these parser skeletons to create a complete + parser.

+ +

In this and subsequent chapters we will use the following schema + that describes a collection of person records. We save it in + people.xsd:

+ +
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:simpleType name="gender">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="male"/>
+      <xs:enumeration value="female"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="first-name" type="xs:string"/>
+      <xs:element name="last-name" type="xs:string"/>
+      <xs:element name="gender" type="gender"/>
+      <xs:element name="age" type="xs:short"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="people">
+    <xs:sequence>
+      <xs:element name="person" type="person" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="people" type="people"/>
+
+</xs:schema>
+  
+ +

A sample XML instance to go along with this schema is saved + in people.xml:

+ +
+<?xml version="1.0"?>
+<people>
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+</people>
+  
+ +

Compiling people.xsd with the XSD/e compiler results + in three parser skeletons being generated: gender_pskel, + person_pskel, and people_pskel. We are going + to examine and implement each of them in the subsequent sections.

+ +

3.1 Implementing the Gender Parser

+ +

The generated gender_pskel parser skeleton looks like + this:

+ +
+class gender_pskel: public xml_schema::string_pskel
+{
+public:
+  gender_pskel (xml_schema::string_pskel* base_impl);
+
+  // Parser callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual void
+  post_gender ();
+};
+  
+ +

Notice that gender_pskel inherits from + xml_schema::string_pskel which is a parser skeleton + for built-in XML Schema type string and is + predefined in the XSD/e runtime library. This is an example + of the general rule that parser skeletons follow: if a type + in XML Schema inherits from another then there will be an + equivalent inheritance between the corresponding parser + skeleton classes. The gender_pskel class also + declares a constructor which expects a pointer to the base + parser skeleton. We will discuss the purpose of this + constructor shortly.

+ +

The pre() and post_gender() callbacks + should look familiar from the previous chapter. Let's now + implement the parser. Our implementation will simply print + the gender to cout:

+ + +
+class gender_pimpl: public gender_pskel
+{
+public:
+  gender_pimpl ()
+    : gender_pskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  post_gender ()
+  {
+    std::string s = post_string ();
+    cout << "gender: " << s << endl;
+  }
+
+private:
+  xml_schema::string_pimpl base_impl_;
+};
+  
+ +

While the code is quite short, there is a lot going on. First, + notice that we define a member variable base_impl_ + of type xml_schema::string_pimpl and then pass + it to the gender_pskel's constructor. We have + encountered xml_schema::string_pimpl already; it is an + implementation of the xml_schema::string_pskel parser + skeleton for built-in XML Schema type string. By + passing base_impl_ to the gender_pskel's + constructor we provide an implementation for the part of the + parser skeleton that is inherited from string_pskel.

+ +

This is another common theme in the C++/Parser programming model: + reusing implementations of the base parsers in the derived ones. + In our case, string_pimpl will do all the dirty work + of extracting the data and we can just get it at the end with the + call to post_string(). For more information on parser + implementation reuse refer to Section 5.6, + "Parser Reuse".

+ +

In case you are curious, here are the definitions for + xml_schema::string_pskel and + xml_schema::string_pimpl:

+ +
+namespace xml_schema
+{
+  class string_pskel: public parser_simple_content
+  {
+  public:
+    virtual std::string
+    post_string () = 0;
+  };
+
+  class string_pimpl: public string_pskel
+  {
+  public:
+    virtual void
+    _pre ();
+
+    virtual void
+    _characters (const xml_schema::ro_string&);
+
+    virtual std::string
+    post_string ();
+
+  protected:
+    std::string str_;
+  };
+}
+  
+ +

There are three new pieces in this code that we haven't seen yet. + Those are the parser_simple_content class and + the _pre() and _characters() functions. + The parser_simple_content class is defined in the XSD/e + runtime and is a base class for all parser skeletons that conform + to the simple content model in XML Schema. Types with the + simple content model cannot have nested elements—only text + and attributes. There is also the parser_complex_content + class which corresponds to the complex content mode (types with + nested elements, for example, person from + people.xsd).

+ +

The _pre() function is a parser callback. Remember we + talked about the pre() and post_*() callbacks + in the previous chapter? There are actually two more callbacks + with similar roles: _pre() and _post (). + As a result, each parser skeleton has four special callbacks:

+ +
+  virtual void
+  pre ();
+
+  virtual void
+  _pre ();
+
+  virtual void
+  _post ();
+
+  virtual void
+  post_name ();
+  
+ +

pre() and _pre() are initialization + callbacks. They get called in that order before a new instance of the type + is about to be parsed. The difference between pre() and + _pre() is conventional: pre() can + be completely overridden by a derived parser. The derived + parser can also override _pre() but has to always call + the original version. This allows you to partition initialization + into customizable and required parts.

+ +

Similarly, _post() and post_name() are + finalization callbacks with exactly the same semantics: + post_name() can be completely overridden by the derived + parser while the original _post() should always be called. +

+ +

The final bit we need to discuss in this section is the + _characters() function. As you might have guessed, it + is also a callback. A low-level one that delivers raw character content + for the type being parsed. You will seldom need to use this callback + directly. Using implementations for the built-in parsers provided by + the XSD/e runtime is usually a simpler and more convenient + alternative.

+ +

At this point you might be wondering why some post_*() + callbacks, for example post_string(), return some data + while others, for example post_gender(), have + void as a return type. This is a valid concern + and it will be addressed in the next chapter.

+ +

3.2 Implementing the Person Parser

+ +

The generated person_pskel parser skeleton looks like + this:

+ +
+class person_pskel: public xml_schema::parser_complex_content
+{
+public:
+  // Parser callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual void
+  first_name (const std::string&);
+
+  virtual void
+  last_name (const std::string&);
+
+  virtual void
+  gender ();
+
+  virtual void
+  age (short);
+
+  virtual void
+  post_person ();
+
+  // Parser construction API.
+  //
+  void
+  first_name_parser (xml_schema::string_pskel&);
+
+  void
+  last_name_parser (xml_schema::string_pskel&);
+
+  void
+  gender_parser (gender_pskel&);
+
+  void
+  age_parser (xml_schema::short_pskel&);
+
+  void
+  parsers (xml_schema::string_pskel& /* first-name */,
+           xml_schema::string_pskel& /* last-name */,
+           gender_pskel&             /* gender */,
+           xml_schema::short_pskel&  /* age */);
+};
+  
+ + +

As you can see, we have a parser callback for each of the nested + elements found in the person XML Schema type. + The implementation of this parser is straightforward:

+ +
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  first_name (const std::string& n)
+  {
+    cout << "first: " << f << endl;
+  }
+
+  virtual void
+  last_name (const std::string& l)
+  {
+    cout << "last: " << l << endl;
+  }
+
+  virtual void
+  age (short a)
+  {
+    cout << "age: " << a << endl;
+  }
+};
+  
+ +

Notice that we didn't override the gender() callback + because all the printing is done by gender_pimpl.

+ +

3.3 Implementing the People Parser

+ +

The generated people_pskel parser skeleton looks like + this:

+ +
+class people_pskel: public xml_schema::parser_complex_content
+{
+public:
+  // Parser callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual void
+  person ();
+
+  virtual void
+  post_people ();
+
+  // Parser construction API.
+  //
+  void
+  person_parser (person_pskel&);
+
+  void
+  parsers (person_pskel& /* person */);
+};
+  
+ +

The person() callback will be called after parsing each + person element. While person_pimpl does + all the printing, one useful thing we can do in this callback is to + print an extra newline after each person record so that our + output is more readable:

+ +
+class people_pimpl: public people_pskel
+{
+public:
+  virtual void
+  person ()
+  {
+    cout << endl;
+  }
+};
+  
+ +

Now it is time to put everything together.

+ + +

3.4 Connecting the Parsers Together

+ +

At this point we have all the individual parsers implemented + and can proceed to assemble them into a complete parser + for our XML vocabulary. The first step is to instantiate + all the individual parsers that we will need:

+ +
+xml_schema::short_pimpl short_p;
+xml_schema::string_pimpl string_p;
+
+gender_pimpl gender_p;
+person_pimpl person_p;
+people_pimpl people_p;
+  
+ +

Notice that our schema uses two built-in XML Schema types: + string for the first-name and + last-name elements as well as short + for age. We will use predefined parsers that + come with the XSD/e runtime to handle these types. The next + step is to connect all the individual parsers. We do this + with the help of functions defined in the parser + skeletons and marked with the "Parser Construction API" + comment. One way to do it is to connect each individual + parser by calling the *_parser() functions:

+ +
+person_p.first_name_parser (string_p);
+person_p.last_name_parser (string_p);
+person_p.gender_parser (gender_p);
+person_p.age_parser (short_p);
+
+people_p.person_parser (person_p);
+  
+ +

You might be wondering what happens if you do not provide + a parser by not calling one of the *_parser() functions. + In that case the corresponding XML content will be skipped, + including validation. This is an efficient way to ignore parts + of the document that you are not interested in.

+ + +

An alternative, shorter, way to connect the parsers is by using + the parsers() functions which connects all the parsers + for a given type at once:

+ +
+person_p.parsers (string_p, string_p, gender_p, short_p);
+people_p.parsers (person_p);
+  
+ +

The following figure illustrates the resulting connections. Notice + the correspondence between return types of the post_*() + functions and argument types of element callbacks that are connected + by the arrows.

+ + +
+ +

The last step is the construction of the document parser and + invocation of the complete parser on our sample XML instance:

+ +
+xml_schema::document_pimpl doc_p (people_p, "people");
+
+people_p.pre ();
+doc_p.parse ("people.xml");
+people_p.post_people ();
+  
+ +

Let's consider xml_schema::document_pimpl in + more detail. While the exact definition of this class + varies depending on the mapping configuration, here is + the part relevant to our example:

+ +
+namespace xml_schema
+{
+  class document_pimpl
+  {
+  public:
+    document_pimpl (xml_schema::parser_base&,
+                    const std::string& root_element_name);
+
+    document_pimpl (xml_schema::parser_base&,
+                    const std::string& root_element_namespace,
+                    const std::string& root_element_name);
+
+    void
+    parse (const std::string& file);
+
+    void
+    parse (std::istream&);
+
+    void
+    parse (const void* data, size_t size, bool last);
+  };
+}
+  
+ +

xml_schema::document_pimpl is a root parser for + the vocabulary. The first argument to its constructors is the + parser for the type of the root element (people_pimpl + in our case). Because a type parser is only concerned with + the element's content and not with the element's name, we need + to specify the root element name somewhere. That's + what is passed as the second and third arguments to the + document_pimpl's constructors.

+ +

There are also three overloaded parse() function + defined in the document_pimpl class. The first version + parses a local file identified by a name. The second version + reads the data from an input stream. The last version allows + you to parse the data directly from a buffer, one chunk at a + time. You can call this function multiple times with the final + call having the last argument set to true. For more + information on the xml_schema::document_pimpl class + refer to Chapter 7, "Document Parser and Error + Handling".

+ +

Let's now consider a step-by-step list of actions that happen + as we parse through people.xml. The content of + people.xml is repeated below for convenience.

+ +
+<?xml version="1.0"?>
+<people>
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+</people>
+  
+ + +
    +
  1. people_p.pre() is called from + main(). We did not provide any implementation + for this callback so this call is a no-op.
  2. + +
  3. doc_p.parse("people.xml") is called from + main(). The parser opens the file and starts + parsing its content.
  4. + +
  5. The parser encounters the root element. doc_p + verifies that the root element is correct and calls + _pre() on people_p which is also + a no-op. Parsing is now delegated to people_p.
  6. + +
  7. The parser encounters the person element. + people_p determines that person_p + is responsible for parsing this element. pre() + and _pre() callbacks are called on person_p. + Parsing is now delegated to person_p.
  8. + +
  9. The parser encounters the first-name element. + person_p determines that string_p + is responsible for parsing this element. pre() + and _pre() callbacks are called on string_p. + Parsing is now delegated to string_p.
  10. + +
  11. The parser encounters character content consisting of + "John". The _characters() callback is + called on string_p.
  12. + +
  13. The parser encounters the end of first-name + element. The _post() and post_string() + callbacks are called on string_p. The + first_name() callback is called on person_p + with the return value of post_string(). The + first_name() implementation prints + "first: John" to cout. + Parsing is now returned to person_p.
  14. + +
  15. Steps analogous to 5-7 are performed for the last-name, + gender, and age elements.
  16. + +
  17. The parser encounters the end of person + element. The _post() and post_person() + callbacks are called on person_p. The + person() callback is called on people_p. + The person() implementation prints a new line + to cout. Parsing is now returned to + people_p.
  18. + +
  19. Steps 4-9 are performed for the second person + element.
  20. + +
  21. The parser encounters the end of people + element. The _post() callback is called on + people_p. The doc_p.parse("people.xml") + call returns to main().
  22. + +
  23. people_p.post_people() is called from + main() which is a no-op.
  24. + +
+ + + + + +

4 Type Maps

+ +

There are many useful things you can do inside parser callbacks as they + are right now. There are, however, times when you want to propagate + some information from one parser to another or to the caller of the + parser. One common task that would greatly benefit from such a + possibility is building a tree-like in-memory object model of the + data stored in XML. During execution, each individual sub-parser + would create a sub-tree and return it to its parent parser + which can then incorporate this sub-tree into the whole tree.

+ +

In this chapter we will discuss the mechanisms offered by the + C++/Parser mapping for returning information from individual + parsers and see how to use them to build an object model + of our people vocabulary.

+ +

4.1 Object Model

+ +

An object model for our person record example could + look like this (saved in the people.hxx file):

+ +
+#include <string>
+#include <vector>
+
+enum gender
+{
+  male,
+  female
+};
+
+class person
+{
+public:
+  person (const std::string& first,
+          const std::string& last,
+          ::gender gender,
+          short age)
+    : first_ (first), last_ (last),
+      gender_ (gender), age_ (age)
+  {
+  }
+
+  const std::string&
+  first () const
+  {
+    return first_;
+  }
+
+  const std::string&
+  last () const
+  {
+    return last_;
+  }
+
+  ::gender
+  gender () const
+  {
+    return gender_;
+  }
+
+  short
+  age () const
+  {
+    return age_;
+  }
+
+private:
+  std::string first_;
+  std::string last_;
+  ::gender gender_;
+  short age_;
+};
+
+typedef std::vector<person> people;
+  
+ +

While it is clear which parser is responsible for which part of + the object model, it is not exactly clear how, for + example, gender_pimpl will deliver gender + to person_pimpl. You might have noticed that + string_pimpl manages to deliver its value to the + first_name() callback of person_pimpl. Let's + see how we can utilize the same mechanism to propagate our + own data.

+ +

There is a way to tell the XSD/e compiler that you want to + exchange data between parsers. More precisely, for each + type defined in XML Schema, you can tell the compiler two things. + First, the return type of the post_*() callback + in the parser skeleton generated for this type. And, second, + the argument type for callbacks corresponding to elements and + attributes of this type. For example, for XML Schema type + gender we can specify the return type for + post_gender() in the gender_pskel + skeleton and the argument type for the gender() callback + in the person_pskel skeleton. As you might have guessed, + the generated code will then pass the return value from the + post_*() callback as an argument to the element or + attribute callback.

+ +

The way to tell the XSD/e compiler about these XML Schema to + C++ mappings is with type map files. Here is a simple type + map for the gender type from the previous paragraph.

+ +
+include "people.hxx";
+gender ::gender ::gender;
+  
+ +

The first line indicates that the generated code must include + people.hxx in order to get the definition for the + gender type. The second line specifies that both + argument and return types for the gender + XML Schema type should be the ::gender C++ enum + (we use fully-qualified C++ names to avoid name clashes). + The next section will describe the type map format in detail. + We save this type map in people.map and + then translate our schemas with the --type-map + option to let the XSD/e compiler know about our type map:

+ +
+$ xsde cxx-parser --type-map people.map people.xsd
+  
+ +

If we now look at the generated people-pskel.hxx, + we will see the following changes in the gender_pskel and + person_pskel skeletons:

+ +
+#include "people.hxx"
+
+class gender_pskel: public xml_schema::string_pskel
+{
+  virtual ::gender
+  post_gender () = 0;
+
+  ...
+};
+
+class person_pskel: public xml_schema::parser_complex_content
+{
+  virtual void
+  gender (::gender);
+
+  ...
+};
+  
+ +

Notice that #include "people.hxx" was added to + the generated header file from the type map to provide the + definition for the gender enum.

+ +

4.2 Type Map File Format

+ +

Type map files are used to define a mapping between XML Schema + and C++ types. The compiler uses this information + to determine return types of post_*() + callbacks in parser skeletons corresponding to XML Schema + types as well as argument types for callbacks corresponding + to elements and attributes of these types.

+ +

The compiler has a set of predefined mapping rules that map the + built-in XML Schema types to suitable C++ types (discussed + below) and all other types to void. + By providing your own type maps you can override these predefined + rules. The format of the type map file is presented below: +

+ +
+namespace <schema-namespace> [<cxx-namespace>]
+{
+  (include <file-name>;)*
+  ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)*
+}
+  
+ +

Both <schema-namespace> and + <schema-type> are regex patterns while + <cxx-namespace>, + <cxx-ret-type>, and + <cxx-arg-type> are regex pattern + substitutions. All names can be optionally enclosed in + " ", for example, to include white-spaces.

+ +

<schema-namespace> determines XML + Schema namespace. Optional <cxx-namespace> + is prefixed to every C++ type name in this namespace declaration. + <cxx-ret-type> is a C++ type name that is + used as a return type for the post_*() callback. + Optional <cxx-arg-type> is an argument + type for callbacks corresponding to elements and attributes + of this type. If <cxx-arg-type> is not + specified, it defaults to <cxx-ret-type> + if <cxx-ret-type> ends with * or + & (that is, it is a pointer or a reference) and + const <cxx-ret-type>& + otherwise. + <file-name> is a file name either in the + " " or < > format + and is added with the #include directive to + the generated code.

+ +

The # character starts a comment that ends + with a new line or end of file. To specify a name that contains + # enclose it in " ". + For example:

+ +
+namespace http://www.example.com/xmlns/my my
+{
+  include "my.hxx";
+
+  # Pass apples by value.
+  #
+  apple apple;
+
+  # Pass oranges as pointers.
+  #
+  orange orange_t*;
+}
+  
+ +

In the example above, for the + http://www.example.com/xmlns/my#orange + XML Schema type, the my::orange_t* C++ type will + be used as both return and argument types.

+ +

Several namespace declarations can be specified in a single + file. The namespace declaration can also be completely + omitted to map types in a schema without a namespace. For + instance:

+ +
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+  orange "const orange_t*";
+}
+  
+ +

The compiler has a number of predefined mapping rules for + the built-in XML Schema types which can be presented as the + following map files:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  boolean bool bool;
+
+  byte "signed char" "signed char";
+  unsignedByte "unsigned char" "unsigned char";
+
+  short short short;
+  unsignedShort "unsigned short" "unsigned short";
+
+  int int int;
+  unsignedInt "unsigned int" "unsigned int";
+
+  long "long long" "long long";
+  unsignedLong "unsigned long long" "unsigned long long";
+
+  integer long long;
+
+  negativeInteger long long;
+  nonPositiveInteger long long;
+
+  positiveInteger "unsigned long" "unsigned long";
+  nonNegativeInteger "unsigned long" "unsigned long";
+
+  float float float;
+  double double double;
+  decimal double double;
+
+  NMTOKENS xml_schema::string_sequence*;
+  IDREFS xml_schema::string_sequence*;
+
+  base64Binary xml_schema::buffer*;
+  hexBinary xml_schema::buffer*;
+
+  date xml_schema::date;
+  dateTime xml_schema::date_time;
+  duration xml_schema::duration;
+  gDay xml_schema::gday;
+  gMonth xml_schema::gmonth;
+  gMonthDay xml_schema::gmonth_day;
+  gYear xml_schema::gyear;
+  gYearMonth xml_schema::gyear_month;
+  time xml_schema::time;
+}
+  
+ +

If STL is enabled (Section 5.1, "Standard Template + Library"), the following mapping is used for the string-based + XML Schema built-in types:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  include <string>;
+
+  string std::string;
+  normalizedString std::string;
+  token std::string;
+  Name std::string;
+  NMTOKEN std::string;
+  NCName std::string;
+  ID std::string;
+  IDREF std::string;
+  language std::string;
+  anyURI std::string;
+
+  QName xml_schema::qname;
+}
+  
+ +

Otherwise, a C string-based mapping is used:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  string char*;
+  normalizedString char*;
+  token char*;
+  Name char*;
+  NMTOKEN char*;
+  NCName char*;
+  ID char*;
+  IDREF char*;
+  language char*;
+  anyURI char*;
+
+  QName xml_schema::qname*;
+}
+  
+ +

For more information about the mapping of the built-in XML Schema types + to C++ types refer to Chapter 6, "Built-In XML Schema Type + Parsers". The last predefined rule maps anything that wasn't + mapped by previous rules to void:

+ +
+namespace .*
+{
+  .* void void;
+}
+  
+ + +

When you provide your own type maps with the + --type-map option, they are evaluated first. This + allows you to selectively override any + of the predefined rules. Note also that if you change the mapping + of a built-in XML Schema type then it becomes your responsibility + to provide the corresponding parser skeleton and implementation + in the xml_schema namespace. You can include the + custom definitions into the generated header file using the + --hxx-prologue-* options.

+ +

4.3 Parser Implementations

+ +

With the knowledge from the previous section, we can proceed + with creating a type map that maps types in the people.xsd + schema to our object model classes in + people.hxx. In fact, we already have the beginning + of our type map file in people.map. Let's extend + it with the rest of the types:

+ +
+include "people.hxx";
+
+gender ::gender ::gender;
+person ::person;
+people ::people;
+  
+ +

A few things to note about this type map. We did not + provide the argument types for person and + people because the default constant reference is + exactly what we need. We also did not provide any mappings + for built-in XML Schema types string and + short because they are handled by the predefined + rules and we are happy with the result. Note also that + all C++ types are fully qualified. This is done to avoid + potential name conflicts in the generated code. Now we can + recompile our schema and move on to implementing the parsers:

+ +
+$ xsde cxx-parser --type-map people.map people.xsd
+  
+ +

Here is the implementation of our three parsers in full. One + way to save typing when implementing your own parsers is + to open the generated code and copy the signatures of parser + callbacks into your code. Or you could always auto generate the + sample implementations and fill them with your code.

+ +
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+  gender_pimpl ()
+    : gender_pskel (&base_impl_)
+  {
+  }
+
+  virtual ::gender
+  post_gender ()
+  {
+    return post_string () == "male" ? male : female;
+  }
+
+private:
+  xml_schema::string_pimpl base_impl_;
+};
+
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  first_name (const std::string& f)
+  {
+    first_ = f;
+  }
+
+  virtual void
+  last_name (const std::string& l)
+  {
+    last_ = l;
+  }
+
+  virtual void
+  gender (::gender g)
+  {
+    gender_ = g;
+  }
+
+  virtual void
+  age (short a)
+  {
+    age_ = a;
+  }
+
+  virtual ::person
+  post_person ()
+  {
+    return ::person (first_, last_, gender_, age_);
+  }
+
+private:
+  std::string first_;
+  std::string last_;
+  ::gender gender_;
+  short age_;
+};
+
+class people_pimpl: public people_pskel
+{
+public:
+  virtual void
+  person (const ::person& p)
+  {
+    people_.push_back (p);
+  }
+
+  virtual ::people
+  post_people ()
+  {
+    ::people r;
+    r.swap (people_);
+    return r;
+  }
+
+private:
+  ::people people_;
+};
+  
+ +

This code fragment should look familiar by now. Just note that + all the post_*() callbacks now have return types instead + of void. Here is the implementation of the test + driver for this example:

+ +
+#include <iostream>
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+  // Construct the parser.
+  //
+  xml_schema::short_pimpl 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, short_p);
+  people_p.parsers (person_p);
+
+  // Parse the document to obtain the object model.
+  //
+  xml_schema::document_pimpl doc_p (people_p, "people");
+
+  people_p.pre ();
+  doc_p.parse (argv[1]);
+  people ppl = people_p.post_people ();
+
+  // Print the object model.
+  //
+  for (people::iterator i (ppl.begin ()); i != ppl.end (); ++i)
+  {
+    cout << "first:  " << i->first () << endl
+         << "last:   " << i->last () << endl
+         << "gender: " << (i->gender () == male ? "male" : "female") << endl
+         << "age:    " << i->age () << endl
+         << endl;
+  }
+}
+  
+ +

The parser creation and assembly part is exactly the same as in + the previous chapter. The parsing part is a bit different: + post_people() now has a return value which is the + complete object model. We store it in the + ppl variable. The last bit of the code simply iterates + over the people vector and prints the information + for each person. We save the last two code fragments to + driver.cxx and proceed to compile and test + our new application:

+ + +
+$ c++ -I.../libxsde -c driver.cxx people-pskel.cxx
+$ c++ -o driver driver.o people-pskel.o .../libxsde/xsde/libxsde.a
+$ ./driver people.xml
+first:  John
+last:   Doe
+gender: male
+age:    32
+
+first:  Jane
+last:   Doe
+gender: female
+age:    28
+  
+ + + + + +

5 Mapping Configuration

+ +

The Embedded C++/Parser mapping has a number of configuration + parameters that determine the overall properties and behavior + of the generated code, such as the use of Standard Template + Library (STL), Input/Output Stream Library (iostream), C++ + exceptions, XML Schema validation, 64-bit integer types, parser + implementation reuse styles, and support for XML Schema polymorphism. + Previous chapters assumed that the use of STL, iostream, C++ + exceptions, and XML Schema validation were enabled. + This chapter will discuss the changes in the Embedded C++/Parser + programming model that result from the changes to these configuration + parameters. A complete example that uses the minimal mapping + configuration is presented at the end of this chapter.

+ +

In order to enable or disable a particular feature, the corresponding + configuration parameter should be set accordingly in the XSD/e runtime + library as well as specified during schema compilation with the XSD/e + command line options as described in the + XSD/e + Compiler Command Line Manual. +

+ +

While the XML documents can use various encodings, the Embedded + C++/Parser mapping always delivers character data to the application + in the UTF-8 encoding. The underlying XML parser used by the + Embedded C++/Parser mapping includes built-in support for XML + documents encoded in UTF-8, UTF-16, ISO-8859-1, and US-ASCII. + Other encodings can be supported by providing application-specific + decoder functions.

+ +

5.1 Standard Template Library

+ +

To disable the use of STL you will need to configure the XSD/e + runtime without support for STL as well as pass the + --no-stl option to the XSD/e compiler when + translating your schemas. When STL is disabled, all string-based + XML Schema types are mapped to C-style char* instead + of std::string, as described in + Section 4.2, "Type Map File Format". The + following code fragment shows changes in the + signatures of first_name() and last_name() + callbacks from the person record example.

+ +
+class person_pskel
+{
+public:
+  virtual void
+  first_name (char*);
+
+  virtual void
+  last_name (char*);
+
+  ...
+};
+  
+ +

Note that it is your responsibility to eventually release the memory + associated with these strings using operator delete[]. +

+ +

5.2 Input/Output Stream Library

+ +

To disable the use of iostream you will need to configure the + XSD/e runtime library without support for iostream as well as + pass the --no-iostream option to the XSD/e compiler + when translating your schemas. When iostream is disabled, the + following two parse() functions in the + xml_schema::document_pimpl class become unavailable:

+ +
+  void
+  parse (const std::string& file);
+
+  void
+  parse (std::istream&);
+  
+ +

Leaving you with only one function in the form:

+ +
+  void
+  parse (const void* data, size_t size, bool last);
+  
+ +

See Section 7.1, "Document Parser" + for more information on the semantics of these functions.

+ +

5.3 C++ Exceptions

+ +

To disable the use of C++ exceptions, you will need to configure + the XSD/e runtime without support for exceptions as well as pass + the --no-exceptions option to the XSD/e compiler + when translating your schemas. When C++ exceptions are disabled, + the error conditions are indicated with error codes instead of + exceptions, as described in Section 7.3, + "Error Codes". +

+ +

5.4 XML Schema Validation

+ +

To disable support for XML Schema validation, you will need to + configure the XSD/e runtime accordingly as well as pass + the --suppress-validation option to the XSD/e compiler + when translating your schemas. Disabling XML Schema validation + allows to further increase the parsing performance and + reduce footprint in cases where XML instances are known to be + valid. +

+ +

5.5 64-bit Integer Type

+ +

By default the 64-bit long and unsignedLong + XML Schema built-in types are mapped to the 64-bit long long + and unsigned long long fundamental C++ types. To + disable the use of these types in the mapping you will need to + configure the XSD/e runtime accordingly as well as pass + the --no-long-long option to the XSD/e compiler + when translating your schemas. When the use of 64-bit integral + C++ types is disabled the long and + unsignedLong XML Schema built-in types are mapped + to long and unsigned long fundamental + C++ types.

+ +

5.6 Parser Reuse

+ +

When one type in XML Schema inherits from another, it is + often desirable to be able to reuse the parser implementation + corresponding to the base type in the parser implementation + corresponding to the derived type. XSD/e provides support + for two parser reuse styles: the so-called mixin + (generated when the --reuse-style-mixin option + is specified) and tiein (generated by default) styles.

+ +

The compiler can also be instructed not to generate any support + for parser reuse with the --reuse-style-none option. + This is mainly useful to further reduce the generated code size + when your vocabulary does not use inheritance or when you plan + to implement each parser from scratch. Note also that the + XSD/e runtime should be configured in accordance with the + parser reuse style used in the generated code. The remainder + of this section discusses the mixin and tiein parser reuse + styles in more detail.

+ + +

To provide concrete examples for each reuse style we will use the + following schema fragment:

+ +
+<xs:complexType name="person">
+  <xs:sequence>
+    <xs:element name="first-name" type="xs:string"/>
+    <xs:element name="last-name" type="xs:string"/>
+    <xs:element name="age" type="xs:short"/>
+  </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="emplyee">
+  <complexContent>
+    <extension base="person">
+      <xs:sequence>
+        <xs:element name="position" type="xs:string"/>
+        <xs:element name="salary" type="xs:unsignedLong"/>
+      </xs:sequence>
+    </extension>
+  </complexContent>
+</xs:complexType>
+  
+ +

The mixin parser reuse style uses the C++ mixin idiom that + relies on multiple and virtual inheritance. Because + virtual inheritance can result in a significant object + code size increase, this reuse style should be considered + when such an overhead is acceptable and/or the vocabulary + consists of only a handful of types. When the mixin reuse + style is used, the generated parser skeletons use virtual + inheritance, for example:

+ +
+class person_pskel: public virtual parser_complex_content
+{
+  ...
+};
+
+class employee_pskel: public virtual person_pskel
+{
+  ...
+};
+  
+ + +

When you implement the base parser you also need to use + virtual inheritance. The derived parser is implemented + by inheriting from both the derived parser skeleton and + the base parser implementation (that is, mixing in + the base parser implementation), for example:

+ +
+class person_pimpl: public virtual person_pskel
+{
+  ...
+};
+
+class employee_pimpl: public employee_pskel,
+                      public person_pimpl
+{
+  ...
+};
+  
+ + +

The tiein parser reuse style uses delegation and normally + results in a significantly smaller object code while being + almost as convenient to use as the mixin style. When the + tiein reuse style is used, the generated derived parser + skeleton declares a constructor which allows you to specify + the implementation of the base parser:

+ +
+class person_pskel: public parser_complex_content
+{
+  ...
+};
+
+class employee_pskel: public person_pskel
+{
+public:
+  employee_pskel (person_pskel* base_impl)
+
+  ...
+};
+  
+ +

If you pass the implementation of the base parser to this + constructor then the generated code will transparently + forward all the callbacks corresponding to the base parser + skeleton to this implementation. You can also pass + 0 to this constructor in which case you will + need to implement the derived parser from scratch. The + following example shows how we could implement the + person and employee parsers + using the tiein style:

+ +
+class person_pimpl: public person_pskel
+{
+  ...
+};
+
+class employee_pimpl: public employee_pskel
+{
+public:
+  employee_pimpl ()
+    : employee_pskel (&base_impl_)
+  {
+  }
+
+  ...
+
+private:
+  person_pimpl base_impl_;
+};
+  
+ +

Note that you cannot use the tied in base parser + instance (base_impl_ in the above code) for + parsing anything except the derived type.

+ +

The ability to override the base parser callbacks in the + derived parser is also available in the tiein style. For + example, the following code fragment shows how we can + override the age() callback if we didn't + like the implementation provided by the base parser:

+ +
+class employee_pimpl: public employee_pskel
+{
+public:
+  employee_pimpl ()
+    : employee_pskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  age (short a)
+  {
+    ...
+  }
+
+  ...
+
+private:
+  person_pimpl base_impl_;
+};
+  
+ +

In the above example the age element will be + handled by emplyee_pimpl while the first-name + and last-name callbacks will still go to + base_impl_.

+ +

It is also possible to inherit from the base parser implementation + instead of declaring it as a member variable. This can be useful + if you need to access protected members in the base implementation + or need to override a virtual function that is not part of + the parser skeleton interface. Note, however, that in this case + you will need to resolve a number of ambiguities with explicit + qualifications or using-declarations. For example:

+ + +
+class person_pimpl: public person_pskel
+{
+  ...
+protected:
+  virtual person*
+  create ()
+  {
+    return new person ();
+  }
+};
+
+class employee_pimpl: public employee_pskel,
+                      public person_pimpl
+{
+public:
+  employee_pimpl ()
+    : employee_pskel (static_cast<person_pimpl*> (this))
+  {
+  }
+
+  // Resolve ambiguities.
+  //
+  using emplyee_pskel::parsers;
+
+  ...
+
+protected:
+  virtual employee*
+  create ()
+  {
+    return new employee ();
+  }
+};
+  
+ + +

5.7 Support for Polymorphism

+ +

By default the XSD/e compiler generates non-polymorphic code. If your + vocabulary uses XML Schema polymorphism in the form of xsi:type + and/or substitution groups, then you will need to configure the XSD/e + runtime with support for polymorphism, compile your schemas with the + --generate-polymorphic option to produce polymorphism-aware + code, as well as pass true as the last argument to the + xml_schema::document's constructors. If some of your + schemas do not require support for polymorphism then you can compile + them with the --runtime-polymorphic option and still + use the XSD/e runtime configured with polymorphism support. +

+ +

When using the polymorphism-aware generated code, you can specify + several parsers for a single element by passing a parser map + instead of an individual parser to the parser connection function + for the element. One of the parsers will then be looked up and used + depending on the xsi:type attribute value or an element + name from a substitution group. Consider the following schema as an + example:

+ +
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <!-- substitution group root -->
+  <xs:element name="person" type="person"/>
+
+  <xs:complexType name="superman">
+    <xs:complexContent>
+      <xs:extension base="person">
+        <xs:attribute name="can-fly" type="xs:boolean"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="superman"
+              type="superman"
+              substitutionGroup="person"/>
+
+  <xs:complexType name="batman">
+    <xs:complexContent>
+      <xs:extension base="superman">
+        <xs:attribute name="wing-span" type="xs:unsignedInt"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="batman"
+              type="batman"
+              substitutionGroup="superman"/>
+
+  <xs:complexType name="supermen">
+    <xs:sequence>
+      <xs:element ref="person" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="supermen" type="supermen"/>
+
+</xs:schema>
+  
+ +

Conforming XML documents can use the superman + and batman types in place of the person + type either by specifying the type with the xsi:type + attributes or by using the elements from the substitution + group, for instance:

+ + +
+<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <person>
+    <name>John Doe</name>
+  </person>
+
+  <superman can-fly="false">
+    <name>James "007" Bond</name>
+  </superman>
+
+  <superman can-fly="true" wing-span="10" xsi:type="batman">
+    <name>Bruce Wayne</name>
+  </superman>
+
+</supermen>
+  
+ +

To print the data stored in such XML documents we can implement + the parsers as follows:

+ +
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  pre ()
+  {
+    cout << "starting to parse person" << endl;
+  }
+
+  virtual void
+  name (const std::string& v)
+  {
+    cout << "name: " << v << endl;
+  }
+
+  virtual void
+  post_person ()
+  {
+    cout << "finished parsing person" << endl;
+  }
+};
+
+class superman_pimpl: public superman_pskel
+{
+public:
+  superman_pimpl ()
+    : superman_pskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  pre ()
+  {
+    cout << "starting to parse superman" << endl;
+  }
+
+  virtual void
+  can_fly (bool v)
+  {
+    cout << "can-fly: " << v << endl;
+  }
+
+  virtual void
+  post_person ()
+  {
+    post_superman ();
+  }
+
+  virtual void
+  post_superman ()
+  {
+    cout << "finished parsing superman" << endl
+  }
+
+private:
+  person_pimpl base_impl_;
+};
+
+class batman_pimpl: public batman_pskel
+{
+public:
+  batman_pimpl ()
+    : batman_pskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  pre ()
+  {
+    cout << "starting to parse batman" << endl;
+  }
+
+  virtual void
+  wing_span (unsigned int v)
+  {
+    cout << "wing-span: " << v << endl;
+  }
+
+  virtual void
+  post_person ()
+  {
+    post_superman ();
+  }
+
+  virtual void
+  post_superman ()
+  {
+    post_batman ();
+  }
+
+  virtual void
+  post_batman ()
+  {
+    cout << "finished parsing batman" << endl;
+  }
+
+private:
+  superman_pimpl base_impl_;
+};
+  
+ +

Note that because the derived type parsers (superman_pskel + and batman_pskel) are called via the person_pskel + interface, we have to override the post_person() virtual + function in superman_pimpl and batman_pimpl + to call post_superman() and the post_superman() + virtual function in batman_pimpl to call + post_batman() (when the mixin parser reuse style is used + it is not necessary to override post_person() + in batman_pimpl since the suitable implementation + is inherited from superman_pimpl).

+ +

The following code fragment shows how to connect the parsers together. + Notice that for the person element in the supermen_p + parser we specify a parser map instead of a specific parser and we pass + true as the last argument to the document parser constructor + to indicate that we are parsing potentially-polymorphic XML documents:

+ +
+int
+main (int argc, char* argv[])
+{
+  // 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 ();
+  doc_p.parse (argv[1]);
+  supermen_p.post_supermen ();
+}
+  
+ +

When polymorphism-aware code is generated, each element's + *_parser() function is overloaded to also accept + an object of the xml_schema::parser_map type. + For example, the supermen_pskel class from the + above example looks like this:

+ +
+class supermen_pskel: public xml_schema::parser_complex_content
+{
+public:
+
+  ...
+
+  // Parser construction API.
+  //
+  void
+  parsers (person_pskel&);
+
+  // Individual element parsers.
+  //
+  void
+  person_parser (person_pskel&);
+
+  void
+  person_parser (xml_schema::parser_map&);
+
+  ...
+};
+  
+ +

Note that you can specify both the individual (static) parser and + the parser map. The individual parser will be used when the static + element type and the dynamic type of the object being parsed are + the same. This is the case, for example, when there is no + xsi:type attribute and the element hasn't been + substituted. Because the individual parser for an element is + cached and no map lookup is necessary, it makes sense to specify + both the individual parser and the parser map when most of the + objects being parsed are of the static type and optimal + performance is important. The following code fragment shows + how to change the above example to set both the individual + parser and the parser map:

+ +
+int
+main (int argc, char* argv[])
+{
+  ...
+
+  // Here we are specifying several parsers that can be used to
+  // parse the person element.
+  //
+  person_map.insert (superman_p);
+  person_map.insert (batman_p);
+
+  supermen_p.person_parser (person_p);
+  supermen_p.person_parser (person_map);
+
+  ...
+}
+  
+ + +

The xml_schema::parser_map interface and the + xml_schema::parser_map_impl default implementation + are presented below:

+ +
+namespace xml_schema
+{
+  class parser_map
+  {
+  public:
+    virtual parser_base*
+    find (const char* type) const = 0;
+
+    virtual void
+    reset () const = 0;
+  };
+
+  class parser_map_impl: public parser_map
+  {
+  public:
+    parser_map_impl (size_t buckets);
+
+    void
+    insert (parser_base&);
+
+    virtual parser_base*
+    find (const char* type) const;
+
+    virtual void
+    reset () const;
+
+  private:
+    parser_map_impl (const parser_map_impl&);
+
+    parser_map_impl&
+    operator= (const parser_map_impl&);
+
+    ...
+  };
+}
+  
+ +

The type argument in the find() virtual + function is the type name and namespace from the xsi:type attribute + (the namespace prefix is resolved to the actual XML namespace) + or the type of an element from the substitution group in the form + "<name> <namespace>" with the space and the + namespace part absent if the type does not have a namespace. + You can obtain a parser's dynamic type in the same format + using the _dynamic_type() function. The static + type can be obtained by calling the static _static_type() + function, for example person_pskel::_static_type(). + Both functions return a C string (const char*) which + is valid for as long as the application is running. The + reset() virtual function is used to reset + the parsers contained in the map (as opposed to resetting or + clearing the map itself). For more information on parser + resetting refer to Section 7.4, "Reusing Parsers + after an Error". The following example shows how we can + implement our own parser map using std::map:

+ + +
+#include <map>
+#include <string>
+
+class parser_map: public xml_schema::parser_map
+{
+public:
+ void
+ insert (xml_schema::parser_base& p)
+ {
+   map_[p._dynamic_type ()] = &p;
+ }
+
+ virtual xml_schema::parser_base*
+ find (const char* type) const
+ {
+   map::const_iterator i = map_.find (type);
+   return i != map_.end () ? i->second : 0;
+ }
+
+ virtual void
+ reset () const
+ {
+   for (map::const_iterator i (map_.begin ()), e (map_.end ());
+        i != e; ++i)
+   {
+     xml_schema::parser_base* p = i->second;
+     p->_reset ();
+   }
+ }
+
+private:
+  typedef std::map<std::string, xml_schema::parser_base*> map;
+  map map_;
+};
+  
+ +

The XSD/e runtime provided the default implementation for the + xml_schema::parser_map interface, + xml_schema::parser_map_impl, which is a hashmap. + It requires that you specify the number of buckets it will contain + and it does not support automatic table resizing. To obtain good + performance the elements to buckets ratio should be between 0.7 and + 0.9. It is also recommended to use prime numbers for bucket counts: + 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, + 196613, 393241. +

+ +

If C++ exceptions are disabled (Section 5.3, + "C++ Exceptions"), the xml_schema::parser_map_impl + class has the following additional error querying API. It can be used + to detect the out of memory errors after calls to the + parser_map_impl's constructor and insert() + function.

+ +
+namespace xml_schema
+{
+  class parser_map_impl: public parser_map
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    error
+    _error () const;
+
+    ...
+  };
+}
+  
+ +

To support polymorphic parsing the XSD/e runtime and generated code + maintain a number of hashmaps that contain substitution and, if + XML Schema validation is enabled (Section 5.4, + "XML Schema Validation"), inheritance information. Because + the number of elements in these hashmaps depends on the schemas + being compiled and thus is fairly static, these hashmaps do not + perform automatic table resizing and instead the number of buckets + is specified when the XSD/e runtime is configured. To obtain good + performance the elements to buckets ratio in these hashmaps should + be between 0.7 and 0.9. The recommended way to ensure this range + is to add diagnostics code to your application as shown in the + following example:

+ +
+int
+main ()
+{
+  // Check that the load in substitution and inheritance hashmaps
+  // is not too high.
+  //
+#ifndef NDEBUG
+  float load = 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;
+  }
+
+  load = 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
+
+  ...
+}
+  
+ +

Most of the code presented in this section is taken from the + polymorphism example which can be found in the + examples/cxx/parser/ directory of the XSD/e distribution. + Handling of xsi:type and substitution groups when used + on root elements requires a number of special actions as shown in + the polyroot example.

+ +

5.8 A Minimal Example

+ +

The following example is a re-implementation of the person + records example presented in Chapter 3, + "Parser Skeletons". It is intended to work + without STL, iostream, and C++ exceptions. It can be found in + the examples/cxx/parser/minimal/ directory of the + XSD/e distribution. The people.xsd schema is + compiled with the --no-stl, --no-iostream, + and --no-exceptions options. The following listing + presents the implementation of parser skeletons and the test + driver in full.

+ +
+#include <stdio.h>
+
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+  gender_pimpl ()
+    : gender_pskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  post_gender ()
+  {
+    char* s = post_string ();
+    printf ("gender: %s\n", s);
+    delete[] s;
+  }
+
+private:
+  xml_schema::string_pimpl base_impl_;
+};
+
+class person_pimpl: public person_pskel
+{
+public:
+  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
+  age (short a)
+  {
+    printf ("age: %hd\n", a);
+  }
+};
+
+class people_pimpl: public people_pskel
+{
+public:
+  virtual void
+  person ()
+  {
+    // Add an extra newline after each person record.
+    //
+    printf ("\n");
+  }
+};
+
+int
+main (int argc, char* argv[])
+{
+  // Construct the parser.
+  //
+  xml_schema::short_pimpl 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, short_p);
+  people_p.parsers (person_p);
+
+  // Open the file.
+  //
+  FILE* f = fopen (argv[1], "rb");
+
+  if (f == 0)
+  {
+    fprintf (stderr, "%s: unable to open\n", argv[1]);
+    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);
+
+  fclose (f);
+
+  // Handle errors.
+  //
+
+  if (io_error)
+  {
+    fprintf (stderr, "%s: read failure\n", argv[1]);
+    return 1;
+  }
+
+  if (e)
+  {
+    switch (e.type ())
+    {
+    case error::sys:
+      {
+        fprintf (stderr, "%s: %s\n", argv[1], e.sys_text ());
+        break;
+      }
+    case error::xml:
+      {
+        fprintf (stderr, "%s:%lu:%lu: %s\n",
+                 argv[1], e.line (), e.column (), e.xml_text ());
+        break;
+      }
+    case error::schema:
+      {
+        fprintf (stderr, "%s:%lu:%lu: %s\n",
+                 argv[1], e.line (), e.column (), e.schema_text ());
+        break;
+      }
+    case error::app:
+      {
+        fprintf (stderr, "%s:%lu:%lu: application error %d\n",
+                 argv[1], e.line (), e.column (), e.app_code ());
+        break;
+      }
+    default:
+      break;
+    }
+    return 1;
+  }
+  return 0;
+}
+  
+ + + + + +

6 Built-In XML Schema Type Parsers

+ +

The XSD/e runtime provides parser implementations for all built-in + XML Schema types as summarized in the following table. Declarations + for these types are automatically included into each generated + header file. As a result you don't need to include any headers + to gain access to these parser implementations.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
XML Schema typeParser implementation in the xml_schema namespaceParser return type
anyType and anySimpleType types
anyTypeany_type_pimplvoid
anySimpleTypeany_simple_type_pimplvoid
fixed-length integral types
bytebyte_pimplsigned char
unsignedByteunsigned_byte_pimplunsigned char
shortshort_pimplshort
unsignedShortunsigned_short_pimplunsigned short
intint_pimplint
unsignedIntunsigned_int_pimplunsigned int
longlong_pimpllong long or long
+ Section 5.5, "64-bit Integer Type"
unsignedLongunsigned_long_pimplunsigned long long or + unsigned long
+ Section 5.5, "64-bit Integer Type"
arbitrary-length integral types
integerinteger_pimpllong
nonPositiveIntegernon_positive_integer_pimpllong
nonNegativeIntegernon_negative_integer_pimplunsigned long
positiveIntegerpositive_integer_pimplunsigned long
negativeIntegernegative_integer_pimpllong
boolean types
booleanboolean_pimplbool
fixed-precision floating-point types
floatfloat_pimplfloat
doubledouble_pimpldouble
arbitrary-precision floating-point types
decimaldecimal_pimpldouble
string-based types
stringstring_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
normalizedStringnormalized_string_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
tokentoken_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
Namename_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
NMTOKENnmtoken_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
NCNamencname_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
languagelanguage_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
qualified name
QNameqname_pimplxml_schema::qname or xml_schema::qname*
+ Section 6.1, "QName Parser"
ID/IDREF types
IDid_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
IDREFidref_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
list types
NMTOKENSnmtokens_pimplxml_schema::string_sequence*
Section + 6.2, "NMTOKENS and IDREFS Parsers"
IDREFSidrefs_pimplxml_schema::string_sequence*
Section + 6.2, "NMTOKENS and IDREFS Parsers"
URI types
anyURIuri_pimplstd::string or char*
+ Section 5.1, "Standard Template Library"
binary types
base64Binarybase64_binary_pimplxml_schema::buffer*
+ Section 6.3, "base64Binary and + hexBinary Parsers"
hexBinaryhex_binary_pimplxml_schema::buffer*
+ Section 6.3, "base64Binary and + hexBinary Parsers"
date/time types
datedate_pimplxml_schema::date
Section 6.5, + "date Parser"
dateTimedate_time_pimplxml_schema::date_time
Section 6.6, + "dateTime Parser"
durationduration_pimplxml_schema::duration
Section 6.7, + "duration Parser"
gDaygday_pimplxml_schema::gday
Section 6.8, + "gDay Parser"
gMonthgmonth_pimplxml_schema::gmonth
Section 6.9, + "gMonth Parser"
gMonthDaygmonth_day_pimplxml_schema::gmonth_day
Section 6.10, + "gMonthDay Parser"
gYeargyear_pimplxml_schema::gyear
Section 6.11, + "gYear Parser"
gYearMonthgyear_month_pimplxml_schema::gyear_month
Section + 6.12, "gYearMonth Parser"
timetime_pimplxml_schema::time
Section 6.13, + "time Parser"
+ +

6.1 QName Parser

+ +

The return type of the qname_pimpl parser implementation + is either xml_schema::qname when STL is enabled + (Section 5.1, "Standard Template Library") or + xml_schema::qname* when STL is disabled. The + qname class represents an XML qualified name. When the + return type is xml_schema::qname*, the returned + object is dynamically allocated with operator new + and should eventually be deallocated with operator delete. + With STL enabled, the qname type has the following + interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (const std::string& name);
+    qname (const std::string& prefix, const std::string& name);
+
+    void
+    swap (qname&);
+
+    const std::string&
+    prefix () const;
+
+    std::string&
+    prefix ();
+
+    void
+    prefix (const std::string&);
+
+    const std::string&
+    name () const;
+
+    std::string&
+    name ();
+
+    void
+    name (const std::string&);
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

When STL is disabled and C++ exceptions are enabled + (Section 5.3, "C++ Exceptions"), the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    void
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    void
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+
+ +

The modifier functions and constructors that have the char* + argument assume ownership of the passed strings which should be allocated + with operator new char[] and will be deallocated with + operator delete[] by the qname object. + If you detach the underlying prefix or name strings, then they + should eventually be deallocated with operator delete[]. +

+ +

Finally, if both STL and C++ exceptions are disabled, the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    error
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    error
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

6.2 NMTOKENS and IDREFS Parsers

+ +

The return type of the nmtokens_pimpl and + idrefs_pimpl parser implementations is + xml_schema::string_sequence*. + The returned object is dynamically allocated with operator + new and should eventually be deallocated with + operator delete. With STL and C++ exceptions enabled + (Section 5.1, "Standard Template Library", + Section 5.3, "C++ Exceptions"), the + string_sequence type has the following interface:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    typedef std::string         value_type;
+    typedef std::string*        pointer;
+    typedef const std::string*  const_pointer;
+    typedef std::string&        reference;
+    typedef const std::string&  const_reference;
+
+    typedef size_t              size_type;
+    typedef ptrdiff_t           difference_type;
+
+    typedef std::string*        iterator;
+    typedef const std::string*  const_iterator;
+
+  public:
+    string_sequence ();
+
+    void
+    swap (string_sequence&);
+
+  private:
+    string_sequence (string_sequence&);
+
+    string_sequence&
+    operator= (string_sequence&);
+
+  public:
+    iterator
+    begin ();
+
+    const_iterator
+    begin () const;
+
+    iterator
+    end ();
+
+    const_iterator
+    end () const;
+
+    std::string&
+    front ();
+
+    const std::string&
+    front () const;
+
+    std::string&
+    back ();
+
+    const std::string&
+    back () const;
+
+    std::string&
+    operator[] (size_t);
+
+    const std::string&
+    operator[] (size_t) const;
+
+  public:
+    bool
+    empty () const;
+
+    size_t
+    size () const;
+
+    size_t
+    capacity () const;
+
+    size_t
+    max_size () const;
+
+  public:
+    void
+    clear ();
+
+    void
+    pop_back ();
+
+    iterator
+    erase (iterator);
+
+    void
+    push_back (const std::string&);
+
+    iterator
+    insert (iterator, const std::string&);
+
+    void
+    reserve (size_t);
+  };
+
+  bool
+  operator== (const string_sequence&, const string_sequence&);
+
+  bool
+  operator!= (const string_sequence&, const string_sequence&);
+}
+  
+ +

When STL is enabled and C++ exceptions are disabled, the signatures + of the push_back(), insert(), and + reserve() functions change as follows:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    ...
+
+  public:
+    error
+    push_back (const std::string&);
+
+    error
+    insert (iterator, const std::string&);
+
+    error
+    insert (iterator, const std::string&, iterator& result);
+
+    error
+    reserve (size_t);
+  };
+}
+  
+ +

When STL is disabled and C++ exceptions are enabled, the + string_sequence type has the following interface:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    typedef char*         value_type;
+    typedef char**        pointer;
+    typedef const char**  const_pointer;
+    typedef char*         reference;
+    typedef const char*   const_reference;
+
+    typedef size_t        size_type;
+    typedef ptrdiff_t     difference_type;
+
+    typedef char** iterator;
+    typedef const char* const* const_iterator;
+
+    string_sequence ();
+
+    void
+    swap (string_sequence&);
+
+  private:
+    string_sequence (string_sequence&);
+
+    string_sequence&
+    operator= (string_sequence&);
+
+  public:
+    iterator
+    begin ();
+
+    const_iterator
+    begin () const;
+
+    iterator
+    end ();
+
+    const_iterator
+    end () const;
+
+    char*
+    front ();
+
+    const char*
+    front () const;
+
+    char*
+    back ();
+
+    const char*
+    back () const;
+
+    char*
+    operator[] (size_t);
+
+    const char*
+    operator[] (size_t) const;
+
+  public:
+    bool
+    empty () const;
+
+    size_t
+    size () const;
+
+    size_t
+    capacity () const;
+
+    size_t
+    max_size () const;
+
+  public:
+    void
+    clear ();
+
+    void
+    pop_back ();
+
+    iterator
+    erase (iterator);
+
+    void
+    push_back (char*);
+
+    void
+    push_back_copy (const char*);
+
+    iterator
+    insert (iterator, char*);
+
+    void
+    reserve (size_t);
+
+    // Detach a string from the sequence at a given position.
+    // The string pointer at this position in the sequence is
+    // set to 0.
+    //
+    char*
+    detach (iterator);
+  };
+
+  bool
+  operator== (const string_sequence&, const string_sequence&);
+
+  bool
+  operator!= (const string_sequence&, const string_sequence&);
+}
+  
+ +

The push_back() and insert() functions + assume ownership of the passed string which should be allocated + with operator new char[] and will be deallocated + with operator delete[] by the string_sequence + object. These two functions free the passed object if the reallocation + of the underlying sequence buffer fails. The push_back_copy() + function makes a copy of the passed string. + If you detach the underlying element string, then it should + eventually be deallocated with operator delete[].

+ +

When both STL and C++ exceptions are disabled, the signatures + of the push_back(), push_back_copy(), + insert(), and reserve() functions change + as follows:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    ...
+
+  public:
+    error
+    push_back (char*);
+
+    error
+    push_back_copy (const char*);
+
+    error
+    insert (iterator, char*);
+
+    error
+    insert (iterator, char*, iterator& result);
+
+    error
+    reserve (size_t);
+  };
+}
+  
+ + +

6.3 base64Binary and hexBinary Parsers

+ +

The return type of the base64_binary_pimpl and + hex_binary_pimpl parser implementations is + xml_schema::buffer*. The returned object is + dynamically allocated with operator new and + should eventually be deallocated with operator delete. + With C++ exceptions enabled (Section 5.3, "C++ + Exceptions"), the buffer type has the following + interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    class bounds {}; // Out of bounds exception.
+
+  public:
+    buffer ();
+
+    explicit
+    buffer (size_t size);
+    buffer (size_t size, size_t capacity);
+    buffer (const void* data, size_t size);
+    buffer (const void* data, size_t size, size_t capacity);
+
+    enum ownership_value { assume_ownership };
+
+    // This constructor assumes ownership of the memory passed.
+    //
+    buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    void
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    bool
+    capacity (size_t);
+
+  public:
+    size_t
+    size () const;
+
+    bool
+    size (size_t);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

The last constructor and the attach() member function + make the buffer instance assume the ownership of the + memory block pointed to by the data argument and + eventually release it by calling operator delete(). + The detach() member function detaches and returns the + underlying memory block which should eventually be released by + calling operator delete(). +

+ +

The capacity() and size() modifier functions + return true if the underlying buffer has moved. The + bounds exception is thrown if the constructor or + attach() member function arguments violate the + (size <= capacity) constraint.

+ +

If C++ exceptions are disabled, the buffer type has + the following interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_bounds,
+      error_no_memory
+    };
+
+    buffer ();
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    error
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    error
+    capacity (size_t);
+
+    error
+    capacity (size_t, bool& moved);
+
+  public:
+    size_t
+    size () const;
+
+    error
+    size (size_t);
+
+    error
+    size (size_t, bool& moved);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

6.4 Time Zone Representation

+ +

The date, dateTime, gDay, + gMonth, gMonthDay, gYear, + gYearMonth, and time XML Schema built-in + types all include an optional time zone component. The following + xml_schema::time_zone base class is used to represent + this information:

+ +
+namespace xml_schema
+{
+  class time_zone
+  {
+  public:
+    time_zone ();
+    time_zone (short hours, short minutes);
+
+    bool
+    zone_present () const;
+
+    void
+    zone_reset ();
+
+    short
+    zone_hours () const;
+
+    void
+    zone_hours (short);
+
+    short
+    zone_minutes () const;
+
+    void
+    zone_minutes (short);
+  };
+
+  bool
+  operator== (const time_zone&, const time_zone&);
+
+  bool
+  operator!= (const time_zone&, const time_zone&);
+}
+  
+ +

The zone_present() accessor function returns true + if the time zone is specified. The zone_reset() modifier + function resets the time zone object to the not specified + state. If the time zone offset is negative then both hours and + minutes components are represented as negative integers.

+ +

6.5 date Parser

+ +

The return type of the date_pimpl parser implementation + is xml_schema::date which represents a year, a day, and a month + with an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class date: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date ();
+
+    date (int year, unsigned short month, unsigned short day);
+
+    date (int year, unsigned short month, unsigned short day,
+          short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const date&, const date&);
+
+  bool
+  operator!= (const date&, const date&);
+}
+  
+ +

6.6 dateTime Parser

+ +

The return type of the date_time_pimpl parser implementation + is xml_schema::date_time which represents a year, a month, a day, + hours, minutes, and seconds with an optional time zone. Its interface + is presented below. For more information on the base + xml_schema::time_zone class refer to Section + 6.4, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class date_time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date_time ();
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds);
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const date_time&, const date_time&);
+
+  bool
+  operator!= (const date_time&, const date_time&);
+}
+  
+ +

6.7 duration Parser

+ +

The return type of the duration_pimpl parser implementation + is xml_schema::duration which represents a potentially + negative duration in the form of years, months, days, hours, minutes, + and seconds. Its interface is presented below.

+ +
+namespace xml_schema
+{
+  class duration
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    duration ();
+
+    duration (bool negative,
+              unsigned int years, unsigned int months, unsigned int days,
+              unsigned int hours, unsigned int minutes, double seconds);
+
+    bool
+    negative () const;
+
+    void
+    negative (bool);
+
+    unsigned int
+    years () const;
+
+    void
+    years (unsigned int);
+
+    unsigned int
+    months () const;
+
+    void
+    months (unsigned int);
+
+    unsigned int
+    days () const;
+
+    void
+    days (unsigned int);
+
+    unsigned int
+    hours () const;
+
+    void
+    hours (unsigned int);
+
+    unsigned int
+    minutes () const;
+
+    void
+    minutes (unsigned int);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const duration&, const duration&);
+
+  bool
+  operator!= (const duration&, const duration&);
+}
+  
+ + +

6.8 gDay Parser

+ +

The return type of the gday_pimpl parser implementation + is xml_schema::gday which represents a day of the month with + an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gday: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gday ();
+
+    explicit
+    gday (unsigned short day);
+
+    gday (unsigned short day, short zone_hours, short zone_minutes);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gday&, const gday&);
+
+  bool
+  operator!= (const gday&, const gday&);
+}
+  
+ +

6.9 gMonth Parser

+ +

The return type of the gmonth_pimpl parser implementation + is xml_schema::gmonth which represents a month of the year + with an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth ();
+
+    explicit
+    gmonth (unsigned short month);
+
+    gmonth (unsigned short month,
+            short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth&, const gmonth&);
+
+  bool
+  operator!= (const gmonth&, const gmonth&);
+}
+  
+ +

6.10 gMonthDay Parser

+ +

The return type of the gmonth_day_pimpl parser implementation + is xml_schema::gmonth_day which represents a day and a month of + the year with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth_day: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth_day ();
+
+    gmonth_day (unsigned short month, unsigned short day);
+
+    gmonth_day (unsigned short month, unsigned short day,
+                short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth_day&, const gmonth_day&);
+
+  bool
+  operator!= (const gmonth_day&, const gmonth_day&);
+}
+  
+ +

6.11 gYear Parser

+ +

The return type of the gyear_pimpl parser implementation + is xml_schema::gyear which represents a year with + an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gyear: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear ();
+
+    explicit
+    gyear (int year);
+
+    gyear (int year, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+  };
+
+  bool
+  operator== (const gyear&, const gyear&);
+
+  bool
+  operator!= (const gyear&, const gyear&);
+}
+  
+ +

6.12 gYearMonth Parser

+ +

The return type of the gyear_month_pimpl parser implementation + is xml_schema::gyear_month which represents a year and a month + with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gyear_month: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear_month ();
+
+    gyear_month (int year, unsigned short month);
+
+    gyear_month (int year, unsigned short month,
+                 short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gyear_month&, const gyear_month&);
+
+  bool
+  operator!= (const gyear_month&, const gyear_month&);
+}
+  
+ + +

6.13 time Parser

+ +

The return type of the time_pimpl parser implementation + is xml_schema::time which represents hours, minutes, + and seconds with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 6.4, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    time ();
+
+    time (unsigned short hours, unsigned short minutes, double seconds);
+
+    time (unsigned short hours, unsigned short minutes, double seconds,
+          short zone_hours, short zone_minutes);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const time&, const time&);
+
+  bool
+  operator!= (const time&, const time&);
+}
+  
+ + + + + +

7 Document Parser and Error Handling

+ +

In this chapter we will discuss the xml_schema::document_pimpl + type, the error handling mechanisms provided by the mapping, as well + as how to reuse a parser after an error has occurred.

+ +

There are four categories of errors that can result from running + a parser on an XML instance: system, xml, schema, and application. + The system category contains memory allocation and file/stream + operation errors. The xml category is for XML parsing and + well-formedness checking errors. Similarly, the schema category is + for XML Schema validation errors. Finally, the application category + is for application logic errors that you may want to propagate + from parser implementations to the caller of the parser. +

+ +

The C++/Parser mapping supports two methods of reporting errors: + using C++ exceptions and with error codes. The method used depends + on whether or not you have configured the XSD/e runtime and + the generated code with C++ exceptions enabled, as described + in Section 5.3, "C++ Exceptions".

+ +

7.1 Document Parser

+ +

The xml_schema::document_pimpl parser is a root parser for + the vocabulary. As mentioned in Section 3.4, + "Connecting the Parsers Together", its interface varies depending + on the mapping configuration (Chapter 5, "Mapping + Configuration"). When STL and the iostream library are + enabled, the xml_schema::document_pimpl class has the + following interface:

+ +
+namespace xml_schema
+{
+  class parser_base;
+
+  class document_pimpl
+  {
+  public:
+    document_pimpl (parser_base&,
+                    const char* root_element_name);
+
+    document_pimpl (parser_base&,
+                    const char* root_element_namespace,
+                    const char* root_element_name);
+
+    document_pimpl (parser_base&,
+                    const std::string& root_element_name);
+
+    document_pimpl (parser_base&,
+                    const std::string& root_element_namespace,
+                    const std::string& root_element_name);
+
+
+  public:
+    // Parse a local file. The file is accessed with std::ifstream
+    // in binary mode. The std::ios_base::failure exception is used
+    // to report io errors (badbit and failbit) if exceptions are
+    // enabled. Otherwise error codes are used.
+    //
+    void
+    parse (const char* file);
+
+    void
+    parse (const std::string& file);
+
+    // Parse std::istream. std::ios_base::failure exception is used
+    // to report io errors (badbit and failbit) if exceptions are
+    // enabled. Otherwise error codes are used.
+    //
+    void
+    parse (std::istream&);
+
+    // Parse a chunk of input. You can call this function multiple
+    // times with the last call having the last argument true.
+    //
+    void
+    parse (const void* data, size_t size, bool last);
+
+    // Low-level Expat-specific parsing API.
+    //
+    void
+    parse_begin (XML_Parser);
+
+    void
+    parse_end ();
+  };
+}
+  
+ +

When the use of STL is disabled, the constructors and the parse() + function that use std::string in their signatures + are not available. When the use of iostream is disabled, the + parse() functions that parse a local file and + std::istream are not available.

+ +

When support for XML Schema polymorphism is enabled, the + overloaded document_pimpl constructors have + additional arguments which control polymorphic parsing. + For more information refer to Section 5.7, + "Support for Polymorphism". +

+ +

The first argument to all overloaded constructors is the + parser for the type of the root element. The parser_base + class is the base type for all parser skeletons. The second and + third arguments to the document_pimpl's constructors are + the root element's name and namespace.

+ +

The parse_begin() and parse_end() functions + present a low-level, Expat-specific parsing API for maximum control. + A typical use case would look like this (pseudo-code):

+ +
+xxx_pimpl root_p;
+document_pimpl doc_p (root_p, "root");
+
+root_p.pre ();
+doc_p.parse_begin (xml_parser);
+
+while (more_stuff_to_parse)
+{
+   // Call XML_Parse or XML_ParseBuffer:
+   //
+   if (XML_Parse (...) != XML_STATUS_ERROR)
+     break;
+}
+
+doc_p.parse_end ();
+result_type result (root_p.post_xxx ());
+  
+ +

Note that if your vocabulary use XML namespaces, the + XML_ParserCreateNS() functions should be used to create + the XML parser. Space (XML_Char (' ')) should be used + as a separator (the second argument to XML_ParserCreateNS()). + Furthermore, if XML_Parse or XML_ParseBuffer fail, call + parse_end() to determine the error which is indicated + either via exception or set as an error code. +

+ +

The error handling mechanisms employed by the document_pimpl + parser are described in Section 7.2, "Exceptions" + and Section 7.3, "Error Codes".

+ +

7.2 Exceptions

+ +

When C++ exceptions are used for error reporting, the system + errors are mapped to the standard exceptions. The out of memory + condition is indicated by throwing an instance + of std::bad_alloc. The stream operation errors + are reported by throwing an instance of + std::ios_base::failure.

+ +

The xml and schema errors are reported by throwing the + xml_schema::parser_xml and xml_schema::parser_schema + exceptions, respectively. These two exceptions derive from + xml_schema::parser_exception which, in turn, derives + from std::exception. As a result, you can handle + any error from these two categories by either catching + std::exception, xml_schema::parser_exception, + or individual exceptions. The further down the hierarchy you go + the more detailed error information is available to you. The + following listing shows the definitions of these exceptions:

+ +
+namespace xml_schema
+{
+  class parser_exception: public std::exception
+  {
+  public:
+    unsigned long
+    line () const;
+
+    unsigned long
+    column () const;
+
+    virtual const char*
+    text () const = 0;
+
+    ...
+  };
+
+  std::ostream&
+  operator<< (std::ostream&, const parser_exception&);
+
+
+  typedef <implementation-details> parser_xml_error;
+
+  class parser_xml: public parser_exception
+  {
+  public:
+    parser_xml_error
+    code () const;
+
+    virtual const char*
+    text () const;
+
+    virtual const char*
+    what () const throw ();
+
+    ...
+  };
+
+
+  typedef <implementation-details> parser_schema_error;
+
+  class parser_schema: public parser_exception
+  {
+  public:
+    parser_schema_error
+    code () const;
+
+    virtual const char*
+    text () const;
+
+    virtual const char*
+    what () const throw ();
+
+    ...
+  };
+}
+  
+ +

The parser_xml_error and parser_schema_error + are implementation-specific error code types. The + operator<< defined for the parser_exception + class simply prints the error description as returned by the + text() function. The following example shows + how we can catch these exceptions:

+ +
+int
+main (int argc, char* argv[])
+{
+  try
+  {
+    // Parse argv[1].
+  }
+  catch (const xml_schema::parser_exception& e)
+  {
+    cout << argv[1] << ":" << e.line () << ":" << e.column ()
+         << ": error: " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

Finally, for reporting application errors from parsing callbacks, you + can throw any exceptions of your choice. They are propagated to + the caller of the parser without any alterations.

+ +

7.3 Error Codes

+ +

When C++ exceptions are not available, error codes are used to + report error conditions. Each parser skeleton and the root + document_pimpl parser have the following member + function for querying + the error status:

+ +
+xml_schema::parser_error
+_error () const;
+  
+ +

To handle all possible error conditions, you will need to obtain + the error status after calls to: the document_pimpl's + constructor (it performs memory allocations which may fail), the + root parser pre() callback, each call to the parse() + function, and, finally, the call to the root parser + post_*() callback. The definition of + xml_schema::parser_error class is presented below:

+ +
+namespace xml_schema
+{
+  class sys_error
+  {
+  public:
+    enum value
+    {
+      none,
+      no_memory,
+      open_failed,
+      read_failed,
+      write_failed
+    };
+
+    sys_error (value);
+
+    operator value () const;
+
+    static const char*
+    text (value);
+
+    ...
+  };
+
+  typedef <implementation-details> parser_xml_error;
+  typedef <implementation-details> parser_schema_error;
+
+  class parser_error
+  {
+  public:
+    enum error_type
+    {
+      none,
+      sys,
+      xml,
+      schema,
+      app
+    };
+
+    error_type
+    type () const;
+
+    // Line and column are only available for xml, schema, and
+    // app errors.
+    //
+    unsigned long
+    line () const;
+
+    unsigned long
+    column () const;
+
+    // Returns true if there is an error so that you can write
+    // if (p.error ()) or if (error e = p.error ()).
+    //
+    typedef void (error::*bool_convertible) ();
+    operator bool_convertible () const;
+
+    // system
+    //
+    sys_error
+    sys_code () const;
+
+    const char*
+    sys_text () const;
+
+    // xml
+    //
+    parser_xml_error
+    xml_code () const;
+
+    const char*
+    xml_text () const;
+
+    // schema
+    //
+    parser_schema_error
+    schema_code () const;
+
+    const char*
+    schema_text () const;
+
+    // app
+    //
+    int
+    app_code () const;
+
+    ...
+  };
+}
+  
+ +

The parser_xml_error and parser_schema_error + are implementation-specific error code types. The + parser_error class incorporates four categories of errors + which you can query by calling the type() function. + The following example shows how to handle error conditions with + error codes. It is based on the person record example presented + in Chapter 3, "Parser Skeletons".

+ +
+int
+main (int argc, char* argv[])
+{
+  // Construct the parser.
+  //
+  xml_schema::short_pimpl 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, short_p);
+  people_p.parsers (person_p);
+
+  // Parse.
+  //
+  using xml_schema::parser_error;
+  parser_error e;
+
+  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;
+
+    doc_p.parse (argv[1]);
+    if (e = doc_p._error ())
+      break;
+
+    people_p.post_people ();
+    e = people_p._error ();
+
+  } while (false);
+
+  // Handle errors.
+  //
+  if (e)
+  {
+    switch (e.type ())
+    {
+    case parser_error::sys:
+      {
+        cerr << argv[1] << ": error: " << e.sys_text () << endl;
+        break;
+      }
+    case parser_error::xml:
+      {
+        cerr << argv[1] << ":" << e.line () << ":" << e.column ()
+             << ": error: " << e.xml_text () << endl;
+        break;
+      }
+    case parser_error::schema:
+      {
+        cerr << argv[1] << ":" << e.line () << ":" << e.column ()
+             << ": error: " << e.schema_text () << endl;
+        break;
+      }
+    case parser_error::app:
+      {
+        cerr << argv[1] << ":" << e.line () << ":" << e.column ()
+             << ": application error " << e.app_code () << endl;
+        break;
+      }
+    }
+    return 1;
+  }
+}
+  
+ +

The error type for application errors is int with + the value 0 indicated the absence of error. You can + set the application error by calling the _app_error() + function inside a parser callback. For example, if it was invalid to + have a person younger than 18 in our people catalog, then we could + have implemented this check as follows:

+ +
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  age (short a)
+  {
+    if (a < 18)
+      _app_error (1);
+  }
+
+  ...
+};
+  
+ +

You can also set a system error by calling the _sys_error() + function inside a parser callback. This function has one argument of type + xml_schema::sys_error which was presented above. For + example:

+ +
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  pre ()
+  {
+    p_ = new person ();
+
+    if (p_ == 0)
+      _sys_error (xml_schema::sys_error::no_memory);
+  }
+
+  ...
+
+private:
+  person* p_;
+};
+  
+ + +

7.4 Reusing Parsers after an Error

+ +

After a successful execution a parser returns into the initial + state and can be used to parse another document without any + extra actions. On the other hand, if an error occurred during + parsing and you would like to reuse the parser to parse another + document, you need to explicitly reset it into the initial + state as shown in the following code fragment:

+ +
+int
+main ()
+{
+  ...
+
+  std::vector<std::string> files = ...
+
+  xml_schema::document_pimpl doc_p (people_p, "people");
+
+  for (size_t i = 0; i < files.size (); ++i)
+  {
+    try
+    {
+      people_p.pre ();
+      doc_p.parse (files[i]);
+      people_p.post_people ();
+    }
+    catch (const xml_schema::parser_exception&)
+    {
+      doc_p.reset ();
+    }
+  }
+}
+  
+ +

If you do not need to reuse parsers after an error for example + because your application terminates or you create a new parser + instance in such situations, then you can avoid generating + parser reset code by specifying the --suppress-reset + XSD/e compiler option.

+ +

Your individual parser implementations may also require extra + actions in order to bring them into a usable state after an + error. To accomplish this you can override the _reset() + virtual function as shown below. Notice that when you override the + _reset() function in your implementation, you should + always call the base skeleton version to allow it to reset + its state:

+ +
+class person_pimpl: public person_pskel
+{
+public:
+  virtual void
+  pre ()
+  {
+    p_ = new person ();
+  }
+
+  virtual void
+  _reset ()
+  {
+    person_pskel::_reset ();
+    delete p_;
+    p_ = 0;
+  }
+
+  ...
+
+private:
+  person* p_;
+};
+  
+ +

Note also that the _reset() mechanism is used only when + an error has occurred. To make sure that your parser implementations + arrive at the initial state during successful execution, use the + initialization (pre() and _pre()) and + finalization (post_*() and _post()) + callbacks.

+ + + + +

Appendix A — Supported XML Schema Constructs

+ +

The Embedded C++/Parser mapping supports validation of the following + W3C XML Schema constructs in the generated code.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstructNotes
Structure
element
attribute
any
anyAttribute
all
sequence
choice
complex type, empty content
complex type, mixed content
complex type, simple content extension
complex type, simple content restrictionSimple type facets are not validated.
complex type, complex content extension
complex type, complex content restriction
list
Datatypes
byte
unsignedByte
short
unsignedShort
int
unsignedInt
long
unsignedLong
integer
nonPositiveInteger
nonNegativeInteger
positiveInteger
negativeInteger
boolean
float
double
decimal
string
normalizedString
token
Name
NMTOKEN
NCName
language
anyURI
IDIdentity constraint is not enforced.
IDREFIdentity constraint is not enforced.
NMTOKENS
IDREFSIdentity constraint is not enforced.
QName
base64Binary
hexBinary
date
dateTime
duration
gDay
gMonth
gMonthDay
gYear
gYearMonth
time
+ +
+
+ + + + diff --git a/documentation/cxx/parser/guide/makefile b/documentation/cxx/parser/guide/makefile new file mode 100644 index 0000000..964b626 --- /dev/null +++ b/documentation/cxx/parser/guide/makefile @@ -0,0 +1,12 @@ +.PHONY: all +all: cxx-parser-e-guide.ps cxx-parser-e-guide.pdf + +cxx-parser-e-guide.pdf: cxx-parser-e-guide.ps + ps2pdf14 $< + +cxx-parser-e-guide.ps: index.xhtml guide.html2ps + html2ps -f guide.html2ps -o $@ $< + +.PHONY: clean +clean: + rm -f cxx-parser-e-guide.ps cxx-parser-e-guide.pdf diff --git a/documentation/cxx/serializer/guide/figure-1.png b/documentation/cxx/serializer/guide/figure-1.png new file mode 100644 index 0000000..8700758 Binary files /dev/null and b/documentation/cxx/serializer/guide/figure-1.png differ diff --git a/documentation/cxx/serializer/guide/figure-1.svg b/documentation/cxx/serializer/guide/figure-1.svg new file mode 100644 index 0000000..68790f9 --- /dev/null +++ b/documentation/cxx/serializer/guide/figure-1.svg @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + class people_simpl{ void person ();}; + + + class person_simpl{ void pre (); string first_name (); string last_name (); void gender (); short age ();}; + + + class string_simpl{ void pre (string);}; + + + class short_simpl{ void pre (short);}; + + + class gender_simpl{ void pre ();}; + + + + + + + diff --git a/documentation/cxx/serializer/guide/guide.html2ps b/documentation/cxx/serializer/guide/guide.html2ps new file mode 100644 index 0000000..e0f9cf8 --- /dev/null +++ b/documentation/cxx/serializer/guide/guide.html2ps @@ -0,0 +1,65 @@ +@html2ps { + option { + toc: hb; + colour: 1; + hyphenate: 1; + titlepage: 1; + } + + datefmt: "%B %Y"; + + titlepage { + content: " +
+

Embedded C++/Serializer Mapping

+

Getting Started Guide

+

 

+

 

+

 

+

 

+

 

+

 

+
+

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

"; + } + + toc { + indent: 2em; + } + + header { + odd-right: $H; + even-left: $H; + } + + footer { + odd-left: $D; + odd-center: $T; + odd-right: $N; + + even-left: $N; + even-center: $T; + even-right: $D; + } +} + +body { + font-size: 12pt; + text-align: justify; +} + +pre { + font-size: 10pt; +} diff --git a/documentation/cxx/serializer/guide/index.xhtml b/documentation/cxx/serializer/guide/index.xhtml new file mode 100644 index 0000000..31a41d8 --- /dev/null +++ b/documentation/cxx/serializer/guide/index.xhtml @@ -0,0 +1,6391 @@ + + + + + + Embedded C++/Serializer Mapping Getting Started Guide + + + + + + + + + + + + + +
+
+ +
+ +
+
Embedded C++/Serializer Mapping
+
Getting Started Guide
+ +

Copyright © 2005-2009 CODE SYNTHESIS TOOLS CC

+ +

Permission is granted to copy, distribute and/or modify this + document under the terms of the + GNU Free + Documentation License, version 1.2; with no Invariant Sections, + no Front-Cover Texts and no Back-Cover Texts. +

+ +

This document is available in the following formats: + XHTML, + PDF, and + PostScript.

+ +
+ +

Table of Contents

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Preface + + + +
About This Document
More Information
+
1Introduction + + + +
1.1Mapping Overview
1.2Benefits
+
2Hello World Example + + + + + +
2.1Writing Schema
2.2Translating Schema to C++
2.3Implementing Application Logic
2.4Compiling and Running
+
3Serializer Skeletons + + + + + +
3.1Implementing the Gender Serializer
3.2Implementing the Person Serializer
3.3Implementing the People Serializer
3.4Connecting the Serializers Together
+
4Type Maps + + + + +
4.1Object Model
4.2Type Map File Format
4.3Serializer Implementations
+
5Serializer Callbacks + + + + + + +
5.1Optional Callback
5.2Sequence Callback
5.3Choice Callback
5.4Element Wildcard Callbacks
5.5Attribute Wildcard Callbacks
+
6Mapping Configuration + + + + + + + + + +
6.1Standard Template Library
6.2Input/Output Stream Library
6.3C++ Exceptions
6.4XML Schema Validation
6.564-bit Integer Type
6.6Serializer Reuse
6.7Support for Polymorphism
6.8A Minimal Example
+
7Built-In XML Schema Type Serializers + + + + + + + + + + + + + + + + +
7.1Floating-Point Type Serializers
7.2String-Based Type Serializers
7.3QName Serializer
7.4NMTOKENS and IDREFS Serializers
7.5base64Binary and hexBinary Serializers
7.6Time Zone Representation
7.7date Serializer
7.8dateTime Serializer
7.9duration Serializer
7.10gDay Serializer
7.11gMonth Serializer
7.12gMonthDay Serializer
7.13gYear Serializer
7.14gYearMonth Serializer
7.15time Serializer
+
8Document Serializer and Error Handling + + + + + +
8.1Document Serializer
8.2Exceptions
8.3Error Codes
8.4Reusing Serializers after an Error
+
Appendix A — Supported XML Schema Constructs
+
+ +

Preface

+ +

About This Document

+ +

The goal of this document is to provide you with an + understanding of the C++/Serializer programming model and allow you + to efficiently evaluate XSD/e against your project's technical + requirements. As such, this document is intended for embedded + C++ developers and software architects who are looking for an + embedded XML processing solution. Prior experience with XML + and C++ is required to understand this document. Basic + understanding of XML Schema is advantageous but not expected + or required. +

+ + +

More Information

+ +

Beyond this guide, you may also find the following sources of + information useful:

+ +
    +
  • XSD/e + Compiler Command Line Manual
  • + +
  • The INSTALL file in the XSD/e distribution provides + build instructions for various platforms.
  • + +
  • The examples/cxx/serializer/ directory in the XSD/e + distribution contains a collection of examples and a README + file with an overview of each example.
  • + +
  • The xsde-users + mailing list is the place to ask technical questions about XSD/e and the + Embedded C++/Serializer mapping. Furthermore, the + archives + may already have answers to some of your questions.
  • + +
+ + + +

1 Introduction

+ +

Welcome to CodeSynthesis XSD/e and the Embedded C++/Serializer mapping. + XSD/e is a validating XML parser/serializer generator for mobile and + embedded systems. Embedded C++/Serializer is a W3C XML Schema to C++ + mapping that represents an XML vocabulary as a set of serializer + skeletons which you can implement to perform XML serialization as + required by your application logic. +

+ +

1.1 Mapping Overview

+ +

The Embedded C++/Serializer mapping provides event-driven, + stream-oriented XML serialization, XML Schema validation, + and C++ data binding. It was specifically designed and + optimized for mobile and embedded systems where hardware + constraints require high efficiency and economical use of + resources. As a result, the generated serializers are 2-10 + times faster than general-purpose validating XML serializers + while at the same time maintaining extremely low static and + dynamic memory footprints. For example, a validating serializer + executable can be as small as 60KB in size. The size can be + further reduced by disabling support for XML Schema validation. +

+ +

The generated code and the runtime library are also highly-portable + and, in their minimal configuration, can be used without STL, RTTI, + iostream, C++ exceptions, and C++ templates.

+ +

To speed up application development, the C++/Serializer mapping + can be instructed to generate sample serializer implementations + and a test driver which can then be filled with the application + logic code. The mapping also provides a wide range of + mechanisms for controlling and customizing the generated code.

+ +

The next chapter shows how to create a simple application + that uses the Embedded C++/Serializer mapping to validate + and serialize simple data to an XML document. The following + chapters describe the Embedded C++/Serializer mapping in more + detail.

+ +

1.2 Benefits

+ +

Traditional XML serialization APIs such as Document Object Model (DOM) + or XML Writer as well as general-purpose XML Schema validators have + a number of drawbacks that make them less suitable for creating + mobile and embedded XML processing applications. These drawbacks + include: +

+ +
    +
  • Text-based representation results in inefficient use of + resources.
  • + +
  • Extra validation code that is not used by the application.
  • + +
  • Generic representation of XML in terms of elements, attributes, + and text forces an application developer to write a substantial + amount of bridging code that identifies and transforms pieces + of information produced by the application logic to the text + encoding used in XML.
  • + +
  • Resulting applications are hard to debug, change, and + maintain.
  • +
+ +

In contrast, statically-typed, vocabulary-specific serializer + skeletons produced by the Embedded C++/Serializer mapping use + native data types (for example, integers are passed as + integers, not as text) and include validation code only for + XML Schema constructs that are used in the application. This + results in efficient use of resources and compact object code.

+ +

Furthermore, the serializer skeletons allow you to operate in your + domain terms instead of the generic elements, attributes, and + text. Automatic code generation frees you for more + interesting tasks (such as doing something useful with the + information that needs to be stored in XML) and + minimizes the effort needed to adapt your applications to changes + in the document structure. To summarize, the C++/Serializer mapping + has the following key advantages over generic XML serialization APIs:

+ +
    +
  • Ease of use. The generated code hides all the complexity + associated with recreating the document structure, maintaining the + state, and converting the data from types suitable for + manipulation by the application logic to the text representation + used in XML.
  • + +
  • Natural representation. The generated serializer skeletons + implement serializer callbacks as virtual functions with names + corresponding to elements and attributes in XML. As a result, + you serialize the data using your domain vocabulary instead + of generic elements, attributes, and text. +
  • + +
  • Concise code. With a separate serializer skeleton for each + XML Schema type, the application implementation is simpler + and thus easier to read and understand.
  • + +
  • Safety. The data is passed by serializer callbacks as + statically typed objects. The serializer callbacks themselves + are virtual functions. This helps catch programming errors + at compile-time rather than at runtime.
  • + +
  • Maintainability. Automatic code generation minimizes the + effort needed to adapt the application to changes in the + document structure. With static typing, the C++ compiler + can pin-point the places in the application code that need to be + changed.
  • + +
  • Efficiency. The generated serializer skeletons use native + data types and combine validation and data-to-text + conversion in a single step. This makes them much more efficient + than traditional architectures with separate stages for validation + and data conversion.
  • +
+ + + + + +

2 Hello World Example

+ +

In this chapter we will examine how to create a very simple XML + document using the XSD/e-generated C++/Serializer skeletons. + + All the code presented in this chapter is based on the hello + example which can be found in the examples/cxx/serializer/ + directory of the XSD/e distribution.

+ +

2.1 Writing Schema

+ +

First, we need to get an idea about the structure of the XML + document that we are going to create. The sample XML that + we will try to produce with our Hello application looks like + this:

+ +
+<hello>
+
+  <greeting>Hello</greeting>
+
+  <name>sun</name>
+  <name>earth</name>
+  <name>world</name>
+
+</hello>
+      
+ +

Then we can write a description of the above XML in the + XML Schema language and save it into hello.xsd:

+ +
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="hello">
+    <xs:sequence>
+      <xs:element name="greeting" type="xs:string"/>
+      <xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="hello" type="hello"/>
+
+</xs:schema>
+      
+ +

Even if you are not familiar with the XML Schema language, it + should be easy to connect declarations in hello.xsd + to elements in the sample XML document above. The hello + type is defined as a sequence of the nested greeting + and name elements. Note that the term sequence in XML + Schema means that elements should appear in a particular order + as opposed to appearing multiple times. The name + element has its maxOccurs property set to + unbounded which means it can appear multiple times + in an XML document. Finally, the globally-defined hello + element prescribes the root element for our vocabulary. For an + easily-approachable introduction to XML Schema refer to + XML Schema Part 0: + Primer.

+ +

The above schema is a specification of our vocabulary; it tells + everybody what valid XML instances of our vocabulary should look + like. The next step is to compile this schema to generate C++ + serializer skeletons.

+ +

2.2 Translating Schema to C++

+ +

Now we are ready to translate our hello.xsd to C++ + serializer skeletons. To do this we invoke the XSD/e compiler + from a terminal (UNIX) or a command prompt (Windows): +

+ +
+$ xsde cxx-serializer hello.xsd
+  
+ +

The XSD/e compiler produces two C++ files: hello-sskel.hxx + and hello-sskel.cxx. The following code fragment is taken + from hello-sskel.hxx; it should give you an idea about what + gets generated: +

+ +
+class hello_sskel
+{
+public:
+  // Serializer callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual std::string
+  greeting () = 0;
+
+  virtual bool
+  name_next () = 0;
+
+  virtual std::string
+  name () = 0;
+
+  virtual void
+  post ();
+
+  // Serializer construction API.
+  //
+  void
+  greeting_serializer (xml_schema::string_sskel&);
+
+  void
+  name_serializer (xml_schema::string_sskel&);
+
+  void
+  serializers (xml_schema::string_sskel& /* greeting */,
+               xml_schema::string_sskel& /* name */);
+
+private:
+  ...
+};
+  
+ +

The first five member functions shown above are called serializer + callbacks. You would normally override them in your implementation + of the serializer. Let's go through all of them one by one.

+ +

The pre() function is an initialization callback. It is + called when a new element of type hello is about + to be serialized. You would normally use this function to initialize + data structures, such as iterators, which will be used during + serialization. As we will see in subsequent chapters, there is + also a way to pass an argument to this function which may be + useful if you are serializing an in-memory data structure + to XML. The default implementation of the initialization callback + does nothing.

+ +

The post() function is a finalization callback. It is + called when serialization of the element is completed. If necessary, + you can use this function to perform cleanups of data structures + initialized in pre() or during serialization. + The default implementation of the finalization callback also does + nothing. +

+ +

The greeting() and name() functions are + called when the greeting and name elements + are about to be serialized and the values for these elements need + to be provided. Because the name element can be + repeated several times (note the maxOccurs="unbounded" + attribute in the schema), the serializer skeleton also has the + name_next() function which is called before + name() to check if another name element + needs to be serialized.

+ +

The last three functions are for connecting serializers to each other. + For example, there is a predefined serializer for built-in XML Schema + type string in the XSD/e runtime. We will be using it to + serialize the values of greeting and name + elements, as shown in the next section.

+ +

2.3 Implementing Application Logic

+ +

At this point we have all the parts we need to create our + sample XML document. The first step is to implement the + serializer: +

+ +
+#include <string>
+#include <vector>
+#include "hello-sskel.hxx"
+
+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 std::string
+  greeting ()
+  {
+    return "Hello";
+  }
+
+  virtual bool
+  name_next ()
+  {
+    return i_ != names_.end ();
+  }
+
+  virtual std::string
+  name ()
+  {
+    return *i_++;
+  }
+
+private:
+  typedef std::vector<std::string> names;
+
+  names names_;
+  names::iterator i_;
+};
+  
+ +

We use the hello_simpl's constructor to initialize + a vector of names. Then, in the pre() initialization + callback, we initialize an iterator to point to the beginning of the + names vector. The greeting() callback + simply returns the string representing our greeting. The + name_next() callback checks if we reached the + end of the names vector and returns false + if that's the case. The name() callback returns + the next name from the names vector and advances the iterator. + Note that name() is not called if name_next() + returned false. Finally, we left post() with the + default implementations since we don't have anything to cleanup.

+ +

Now it is time to put this serializer implementation to work:

+ +
+#include <iostream>
+
+using namespace std;
+
+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 document.
+    //
+    xml_schema::document_simpl doc_s (hello_s, "hello");
+
+    hello_s.pre ();
+    doc_s.serialize (cout);
+    hello_s.post ();
+  }
+  catch (const xml_schema::serializer_exception& e)
+  {
+    cerr << "error: " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

The first part of this code snippet instantiates individual serializers + and assembles them into a complete vocabulary serializer. + xml_schema::string_simpl is an implementation of a + serializer for built-in XML Schema type string. It is + provided by the XSD/e runtime along with serializers for other built-in + types (for more information on the built-in serializers see + Chapter 7, "Built-In XML Schema Type Serializers"). + We use string_simpl to serialize the greeting + and name elements as indicated by the calls to + greeting_serializer() and name_serializer(). +

+ +

Then we instantiate a document serializer (doc_s). The + first argument to its constructor is the serializer for the root + element (hello_s in our case). The second argument is + the root element name. +

+ +

The final piece is the calls to pre(), + serialize(), and post(). The call to + serialize() performs the actual XML serialization + with the result written to std::cout. The calls + to pre() and post() make sure that + the serializer for the root element can perform proper + initialization and cleanup.

+ +

While our serializer implementation and test driver are pretty small and + easy to write by hand, for bigger XML vocabularies it can be a + substantial effort. To help with this task XSD/e can automatically + generate sample serializer implementations and a test driver from your + schemas. To request the generation of a sample implementation with + empty function bodies specify the --generate-empty-impl + option. To request the generation of a test driver you can use the + --generate-test-driver option. For more information + on these options refer to the + XSD/e + Compiler Command Line Manual.

+ +

2.4 Compiling and Running

+ +

After saving all the parts from the previous section in + driver.cxx, we are ready to compile and run + our first application. On UNIX this can be done with the + following commands: +

+ +
+$ c++ -I.../libxsde -c driver.cxx hello-sskel.cxx
+$ c++ -o driver driver.o hello-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+<hello>
+  <greeting>Hello</greeting>
+  <name>sun</name>
+  <name>moon</name>
+  <name>world</name>
+</hello>
+  
+ +

Here .../libxsde represents the path to the + libxsde directory in the XSD/e distribution.

+ +

+ We can also test XML Schema validation. We can "forget" to + add any names to the vector so that name_next() + returns false on the first call:

+ +
+struct hello_simpl: hello_sskel
+{
+  hello_simpl ()
+  {
+    /*
+    names_.push_back ("sun");
+    names_.push_back ("moon");
+    names_.push_back ("world");
+    */
+  }
+  ...
+};
+  
+ +

This will violate our vocabulary specification which requires + at least one name element to be present. If we + make the above change and recompile our application, we will + get the following output:

+ +
+$ ./driver
+error: expected element not encountered
+  
+ + + + + +

3 Serializer Skeletons

+ +

As we have seen in the previous chapter, the XSD/e compiler generates + a serializer skeleton class for each type defined in XML Schema. In + this chapter we will take a closer look at different functions + that comprise a serializer skeleton as well as the way to connect + our implementations of these serializer skeletons to create a complete + vocabulary serializer.

+ +

In this and subsequent chapters we will use the following + schema that describes a collection of person records. We + save it in people.xsd:

+ +
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:simpleType name="gender">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="male"/>
+      <xs:enumeration value="female"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="first-name" type="xs:string"/>
+      <xs:element name="last-name" type="xs:string"/>
+      <xs:element name="gender" type="gender"/>
+      <xs:element name="age" type="xs:short"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="people">
+    <xs:sequence>
+      <xs:element name="person" type="person" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="people" type="people"/>
+
+</xs:schema>
+  
+ +

A sample XML instance to go along with this schema could look like + this:

+ +
+<people>
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+</people>
+  
+ +

Compiling people.xsd with the XSD/e compiler results + in three serializer skeletons being generated: gender_sskel, + person_sskel, and people_sskel. We are going + to examine and implement each of them in the subsequent sections.

+ +

In the previous chapter we used pre-initialized, static data to + create an XML document. In this chapter we will use the standard + input (std::cin) as the source of data. This approach + reflects a common design theme where the data to be serialized is + computed on the fly instead of being stored in, for example, an + in-memory object model. The next chapter will examine mechanisms + provided by the C++/Serializer mapping for serializing in-memory + object models.

+ +

3.1 Implementing the Gender Serializer

+ +

The generated gender_sskel serializer skeleton looks + like this:

+ +
+class gender_sskel: public xml_schema::string_sskel
+{
+public:
+  gender_sskel (xml_schema::string_sskel* base_impl)
+
+  // Serializer callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual void
+  post ();
+};
+  
+ +

Notice that gender_sskel inherits from + xml_schema::string_sskel which is a serializer + skeleton for built-in XML Schema type string + and is predefined in the XSD/e runtime library. This is an example + of the general rule that serializer skeletons follow: if a type + in XML Schema inherits from another then there will be an + equivalent inheritance between the corresponding serializer + skeleton classes. The gender_sskel class also + declares a constructor which expects a pointer to the base + serializer skeleton. We will discuss the purpose of this + constructor shortly.

+ +

The pre() and post() callbacks should look + familiar from the previous chapter. Let's now implement this + serializer. Our implementation will simply query the gender + value from the standard input stream (std::cin):

+ + +
+#include <string>
+#include <iostream>
+
+using namespace std;
+
+class gender_simpl: public gender_sskel
+{
+public:
+  gender_simpl ()
+    : gender_sskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  pre ()
+  {
+    string g;
+    cerr << "gender (male/female): ";
+    getline (cin, g);
+    base_impl_.pre (g);
+  }
+
+private:
+  xml_schema::string_simpl base_impl_;
+};
+  
+ +

While the code is quite short, there is a lot going on. First, + notice that we define a member variable base_impl_ + of type xml_schema::string_simpl and then pass + it to the gender_sskel's constructor. We have + encountered xml_schema::string_simpl already; it is an + implementation of the xml_schema::string_sskel serializer + skeleton for built-in XML Schema type string. By + passing base_impl_ to the gender_sskel's + constructor we provide an implementation for the part of the + serializer skeleton that is inherited from string_sskel.

+ +

This is another common theme in the C++/Serializer programming model: + reusing implementations of the base serializers in the derived ones. + In our case, string_simpl will do all the dirty work of + serializing the data which we pass to it with the call to + base_impl_.pre(). For more information on serializer + implementation reuse refer to Section 6.6, + "Serializer Reuse".

+ +

In case you are curious, here are the definitions for + xml_schema::string_sskel and + xml_schema::string_simpl:

+ +
+namespace xml_schema
+{
+  class string_sskel: public serializer_simple_content
+  {
+  public:
+    virtual void
+    pre (const std::string&) = 0;
+  };
+
+  class string_simpl: public string_sskel
+  {
+  public:
+    virtual void
+    pre (const std::string&);
+
+    virtual void
+    _serialize_content ();
+
+  protected:
+    std::string value_;
+  };
+}
+  
+ +

There are two new pieces in this code that we haven't seen yet. + Those are the xml_schema::serializer_simple_content + class and the _serialize_content() function. + The serializer_simple_content class is defined in + the XSD/e runtime and is a base class for all serializer skeletons + that conform to the simple content model in XML Schema. Types with + the simple content model cannot have nested elements—only + text and attributes. There is also the + xml_schema::serializer_complex_content class which + corresponds to the complex content mode (types with nested elements, + for example, person from people.xsd).

+ +

The _serialize_content() function is a low-level + serializer callback that is called to perform actual content + serialization (that is to output text or nested elements). There + is also the _serialize_attributes() callback which + is called to serialize attributes in complex types. You will seldom + need to use these callbacks directly. Using implementations for the + built-in serializers provided by the XSD/e runtime is usually a + simpler and more convenient alternative.

+ +

Another bit of information that is useful to know about is + the _pre() and _post() serialization + callbacks. Remember we talked about the pre() and + post() callbacks in the previous chapter? The + _pre() and _post have very + similar but somewhat different roles. As a result, each + serializer skeleton has four special callbacks:

+ +
+  virtual void
+  pre ();
+
+  virtual void
+  _pre ();
+
+  virtual void
+  _post ();
+
+  virtual void
+  post ();
+  
+ +

pre() and _pre() are initialization + callbacks. They get called in that order before a new instance of the type + is about to be serialized. The difference between pre() and + _pre() is conventional: pre() can + be completely overridden by a derived serializer. The derived + serializer can also override _pre() but has to always call + the original version. This allows you to partition initialization + into customizable and required parts.

+ +

Similarly, _post() and post() are + finalization callbacks with exactly the same semantics: + post() can be completely overridden by the derived + serializer while the original _post() should always be + called. +

+ +

At this point you might be wondering why some pre() + callbacks, for example string_sskel::pre(), have an + argument with which they receive the data they need to serialize while + others, for example gender_sskel::pre(), have no such + argument. This is a valid concern and it will be addressed in the + next chapter.

+ +

3.2 Implementing the Person Serializer

+ +

The generated person_sskel serializer skeleton looks like + this:

+ +
+class person_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  // Serializer callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual std::string
+  first_name () = 0;
+
+  virtual std::string
+  last_name () = 0;
+
+  virtual void
+  gender ();
+
+  virtual short
+  age () = 0;
+
+  virtual void
+  post ();
+
+  // Serializer construction API.
+  //
+  void
+  first_name_serializer (xml_schema::string_sskel&);
+
+  void
+  last_name_serializer (xml_schema::string_sskel&);
+
+  void
+  gender_serializer (gender_sskel&);
+
+  void
+  age_serializer (xml_schema::short_sskel&);
+
+  void
+  serializers (xml_schema::string_sskel& /* first-name */,
+               xml_schema::string_sskel& /* last-name */,
+               gender_sskel&             /* gender */,
+               xml_schema::short_sskel&  /* age */);
+};
+  
+ + +

As you can see, we have a serializer callback for each of the nested + elements found in the person XML Schema type. + The implementation of this serializer is straightforward:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual string
+  first_name ()
+  {
+    string fn;
+    cerr << "first name: ";
+    getline (cin, fn);
+    return fn;
+  }
+
+  virtual std::string
+  last_name ()
+  {
+    string ln;
+    cerr << "last name: ";
+    getline (cin, ln);
+    return ln;
+  }
+
+  virtual short
+  age ()
+  {
+    short a;
+    cerr << "age: ";
+    cin >> a;
+    return a;
+  }
+};
+  
+ +

Notice that we didn't need to override the gender() + callback because all the work is done by gender_simpl.

+ +

3.3 Implementing the People Serializer

+ +

The generated people_sskel serializer skeleton looks like + this:

+ +
+class people_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  // Serializer callbacks. Override them in your implementation.
+  //
+  virtual void
+  pre ();
+
+  virtual bool
+  person_next () = 0;
+
+  virtual void
+  person ();
+
+  virtual void
+  post ();
+
+  // Serializer construction API.
+  //
+  void
+  person_serializer (person_sskel&);
+
+  void
+  serializers (person_sskel& /* person */);
+};
+  
+ +

The person_next() callback will be called before serializing + each person element. Our implementation of + person_next() asks the user whether to serialize + another person record:

+ +
+class people_simpl: public people_sskel
+{
+public:
+  virtual bool
+  person_next ()
+  {
+    string s;
+    cerr << "serialize another person record (y/n): ";
+    cin >> ws; // Skip leading whitespaces.
+    getline (cin, s);
+    return s == "y";
+  }
+};
+  
+ +

Now it is time to put everything together.

+ + +

3.4 Connecting the Serializers Together

+ +

At this point we have all the individual serializers implemented + and can proceed to assemble them into a complete serializer + for our XML vocabulary. The first step is to instantiate + all the individual serializers that we will need:

+ +
+xml_schema::short_simpl short_s;
+xml_schema::string_simpl string_s;
+
+gender_simpl gender_s;
+person_simpl person_s;
+people_simpl people_s;
+  
+ +

Notice that our schema uses two built-in XML Schema types: + string for the first-name and + last-name elements as well as short + for age. We will use predefined serializers that + come with the XSD/e runtime to serialize these types. The next + step is to connect all the individual serializers. We do this + with the help of functions defined in the serializer + skeletons and marked with the "Serializer Construction API" + comment. One way to do it is to connect each individual + serializers by calling the *_serializer() functions:

+ +
+person_s.first_name_serializer (string_s);
+person_s.last_name_serializer (string_s);
+person_s.gender_serializer (gender_s);
+person_s.age_serializer (short_s);
+
+people_s.person_serializer (person_s);
+  
+ +

You might be wondering what happens if you do not provide + a serializer by not calling one of the *_serializer() + functions. In that case the corresponding XML fragment will be + skipped.

+ +

An alternative, shorter, way to connect the serializers is by using + the serializers() functions which connects all the + serializers for a given type at once:

+ +
+person_s.serializers (string_s, string_s, gender_s, short_s);
+people_s.serializers (person_s);
+  
+ +

The following figure illustrates the resulting connections. Notice + the correspondence between return types of element callbacks and + argument types of the pre() functions that are connected + by the arrows.

+ + +
+ +

The last step is the construction of the document serializer and + invocation of the complete serializer to produce an XML + document:

+ +
+xml_schema::document_simpl doc_s (people_s, "people");
+
+std::ostringstream os;
+
+people_s.pre ();
+doc_s.serialize (os);
+people_s.post ();
+
+cout << os.str ();
+  
+ +

Note that we first serialize the document into an + std::ostringstream object and then write + the result to the standard output stream. This is done + to prevent the input prompts and output XML from interleaving. + However, writing XML directly to std::cout in + this example is a great way to observe the moments in the XML + document construction process at which serializer callbacks are + being called.

+ +

Let's consider xml_schema::document_simpl in + more detail. While the exact definition of this class + varies depending on the mapping configuration, here is + the part relevant to our example:

+ +
+namespace xml_schema
+{
+  class document_simpl
+  {
+  public:
+    document_simpl (xml_schema::serializer_base&,
+                    const std::string& root_element_name);
+
+    document_simpl (xml_schema::serializer_base&,
+                    const std::string& root_element_namespace,
+                    const std::string& root_element_name);
+
+    void
+    serialize (std::ostream&);
+  };
+}
+  
+ +

xml_schema::document_simpl is a root serializer for + the vocabulary. The first argument to its constructors is the + serializer for the type of the root element (people_simpl + in our case). Because a type serializer is only concerned with + the element's content and not with the element's name, we need + to specify the root element name somewhere. That's + what is passed as the second and third arguments to the + document_simpl's constructors.

+ +

There is also a number of overloaded serialize() + function defined in the document_simpl class. + At the moment we are only interested in the version that + writes XML to a standard output stream. For more information + on the xml_schema::document_simpl class + refer to Chapter 8, "Document Serializer and Error + Handling".

+ +

Let's now consider a step-by-step list of actions that happen + as we serialize the following sample XML document:

+ +
+<people>
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+</people>
+  
+ + +
    +
  1. people_s.pre() is called from + main(). We did not provide any implementation + for this callback so this call is a no-op.
  2. + +
  3. doc_s.serialize(os) is called from + main(). The document serializer + writes out the <people> opening tag + and calls _pre() on the root element + type serializer (people_s) which is + also a no-op. Serialization is delegated to + people_s.
  4. + +
  5. The people_s serializer calls person_next() + to determine if another person element + needs to be serialized. Our implementation ask the user + (who answers "y") and returns true.
  6. + +
  7. The people_s serializer calls person() + which is a no-op. It then calls pre() on + person_s (no-op), writes out the + <person> opening tag, and calls _pre() + on person_s (no-op). Serialization is delegated to + person_s.
  8. + +
  9. The person_s serializer calls first_name() + that returns a first name which it asks the user to enter. + person_s then calls pre() on + string_s and passes the name returned from + first_name() as its argument. It then writes + out the <first-name> opening tag and calls + _pre() on string_s. Serialization + is delegated to string_s.
  10. + +
  11. The _serialize_content() callback is called on + string_s which writes out the string passed + to it in the pre() call.
  12. + +
  13. Control is returned to person_s which + calls _post() on string_s, writes + out the </first-name> closing tag, and calls + post() on string_s.
  14. + +
  15. Steps analogous to 5-7 are performed for the last-name, + gender, and age elements.
  16. + +
  17. Control is returned to people_s + which calls _post() on person_s (no-op), + writes out the </person> closing tag, and calls + post() on person_s (no-op).
  18. + +
  19. The people_s serializer calls person_next() + to determine if another person element + needs to be serialized. Our implementation ask the user + (who answers "n") and returns false.
  20. + +
  21. Control is returned to doc_s which calls + _post() on people_s (no-op) and + writes out the </people> closing tag.
  22. + +
  23. Control is returned to main() which + calls post() on people_s (no-op).
  24. +
+ + + + + +

4 Type Maps

+ +

There are many useful things you can do inside serializer callbacks as they + are right now. There are, however, times when you want to propagate + some information from one serializer to another or from the caller of + the serializer. One common task that would greatly benefit from such a + possibility is serializing a tree-like in-memory object model to XML. + During execution, each individual serializer would be responsible + for disaggregating and serializing a specific portion of the tree + and delegating the rest to its sub-serializers.

+ +

In this chapter we will discuss the mechanisms offered by the + C++/Serializer mapping for passing information between individual + serializers and see how to use them to serialize a sample object + model for our people vocabulary.

+ +

4.1 Object Model

+ +

An object model for our person record example could + look like this (saved in the people.hxx file):

+ +
+#include <string>
+#include <vector>
+
+enum gender
+{
+  male,
+  female
+};
+
+class person
+{
+public:
+  person (const std::string& first,
+          const std::string& last,
+          ::gender gender,
+          short age)
+    : first_ (first), last_ (last),
+      gender_ (gender), age_ (age)
+  {
+  }
+
+  const std::string&
+  first () const
+  {
+    return first_;
+  }
+
+  const std::string&
+  last () const
+  {
+    return last_;
+  }
+
+  ::gender
+  gender () const
+  {
+    return gender_;
+  }
+
+  short
+  age () const
+  {
+    return age_;
+  }
+
+private:
+  std::string first_;
+  std::string last_;
+  ::gender gender_;
+  short age_;
+};
+
+typedef std::vector<person> people;
+  
+ +

While it is clear which serializer is responsible for which part of + the object model, it is not exactly clear how, for + example, person_simpl will pass gender + to gender_simpl. You might have noticed that + string_simpl manages to receive its value from the + first_name() callback. Let's + see how we can utilize the same mechanism to propagate our + own data.

+ +

There is a way to tell the XSD/e compiler that you want to + exchange data between serializers. More precisely, for each + type defined in XML Schema, you can tell the compiler two things. + First, the argument type of the pre() callback + in the serializer skeleton generated for this type. And, second, + the return type for callbacks corresponding to elements and + attributes of this type. For example, for XML Schema type + gender we can specify the argument type for + pre() in the gender_sskel + skeleton and the return type for the gender() callback + in the person_sskel skeleton. As you might have guessed, + the generated code will then pass the return value from an + element or attribute callback (person_sskel::gender() + in our case) to the pre() callback of the corresponding + serializer skeleton (gender_sskel::pre() in our case).

+ +

The way to tell the XSD/e compiler about these XML Schema to + C++ mappings is with type map files. Here is a simple type + map for the gender type from the previous paragraph.

+ +
+include "people.hxx";
+gender ::gender ::gender;
+  
+ +

The first line indicates that the generated code must include + people.hxx in order to get the definition for the + gender type. The second line specifies that both + argument and return types for the gender + XML Schema type should be the ::gender C++ enum + (we use fully-qualified C++ names to avoid name clashes). + The next section will describe the type map format in more detail. + We save this type map in people.map and + then translate our schemas with the --type-map + option to let the XSD/e compiler know about our type map:

+ +
+$ xsde cxx-serializer --type-map people.map people.xsd
+  
+ +

If we now look at the generated people-sskel.hxx, + we will see the following changes in the gender_sskel and + person_sskel skeletons:

+ +
+#include "people.hxx"
+
+class gender_sskel: public xml_schema::string_sskel
+{
+  virtual void
+  pre (::gender) = 0;
+
+  ...
+};
+
+class person_sskel: public xml_schema::serializer_complex_content
+{
+  virtual ::gender
+  gender () = 0;
+
+  ...
+};
+  
+ +

Notice that #include "people.hxx" was added to + the generated header file from the type map to provide the + definition for the gender enum.

+ +

4.2 Type Map File Format

+ +

Type map files are used to define a mapping between XML Schema + and C++ types. The compiler uses this information + to determine argument types of pre() + callbacks in serializer skeletons corresponding to XML Schema + types as well as return types for callbacks corresponding + to elements and attributes of these types.

+ +

The compiler has a set of predefined mapping rules that map + the built-in XML Schema types to suitable C++ types (discussed + below) and all other types to void. + By providing your own type maps you can override these predefined + rules. The format of the type map file is presented below: +

+ +
+namespace <schema-namespace> [<cxx-namespace>]
+{
+  (include <file-name>;)*
+  ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)*
+}
+  
+ +

Both <schema-namespace> and + <schema-type> are regex patterns while + <cxx-namespace>, + <cxx-ret-type>, and + <cxx-arg-type> are regex pattern + substitutions. All names can be optionally enclosed in + " ", for example, to include white-spaces.

+ +

<schema-namespace> determines XML + Schema namespace. Optional <cxx-namespace> + is prefixed to every C++ type name in this namespace declaration. + <cxx-ret-type> is a C++ type name that is + used as a return type for the element and attribute callbacks corresponding + to this schema type. Optional <cxx-arg-type> + is an argument type for the pre() callback in the serializer + skeleton for this schema type. If <cxx-arg-type> + is not specified, it defaults to <cxx-ret-type> + if <cxx-ret-type> ends with * or + & (that is, it is a pointer or a reference) and + const <cxx-ret-type>& + otherwise. + <file-name> is a file name either in the + " " or < > format + and is added with the #include directive to + the generated code.

+ +

The # character starts a comment that ends + with a new line or end of file. To specify a name that contains + # enclose it in " ". + For example:

+ +
+namespace http://www.example.com/xmlns/my my
+{
+  include "my.hxx";
+
+  # Pass apples by value.
+  #
+  apple apple;
+
+  # Pass oranges as pointers.
+  #
+  orange orange_t*;
+}
+  
+ +

In the example above, for the + http://www.example.com/xmlns/my#orange + XML Schema type, the my::orange_t* C++ type will + be used as both return and argument types.

+ +

Several namespace declarations can be specified in a single + file. The namespace declaration can also be completely + omitted to map types in a schema without a namespace. For + instance:

+ +
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+  orange "const orange_t*";
+}
+  
+ +

The compiler has a number of predefined mapping rules for + the built-in XML Schema types which can be presented as the + following map files:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  boolean bool bool;
+
+  byte "signed char" "signed char";
+  unsignedByte "unsigned char" "unsigned char";
+
+  short short short;
+  unsignedShort "unsigned short" "unsigned short";
+
+  int int int;
+  unsignedInt "unsigned int" "unsigned int";
+
+  long "long long" "long long";
+  unsignedLong "unsigned long long" "unsigned long long";
+
+  integer long long;
+
+  negativeInteger long long;
+  nonPositiveInteger long long;
+
+  positiveInteger "unsigned long" "unsigned long";
+  nonNegativeInteger "unsigned long" "unsigned long";
+
+  float float float;
+  double double double;
+  decimal double double;
+
+  NMTOKENS "const xml_schema::string_sequence*";
+  IDREFS "const xml_schema::string_sequence*";
+
+  base64Binary "const xml_schema::buffer*";
+  hexBinary "const xml_schema::buffer*";
+
+  date xml_schema::date;
+  dateTime xml_schema::date_time;
+  duration xml_schema::duration;
+  gDay xml_schema::gday;
+  gMonth xml_schema::gmonth;
+  gMonthDay xml_schema::gmonth_day;
+  gYear xml_schema::gyear;
+  gYearMonth xml_schema::gyear_month;
+  time xml_schema::time;
+}
+  
+ +

If STL is enabled (Section 6.1, "Standard Template + Library"), the following mapping is used for the string-based + XML Schema built-in types:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  include <string>;
+
+  string std::string;
+  normalizedString std::string;
+  token std::string;
+  Name std::string;
+  NMTOKEN std::string;
+  NCName std::string;
+  ID std::string;
+  IDREF std::string;
+  language std::string;
+  anyURI std::string;
+
+  QName xml_schema::qname;
+}
+  
+ +

Otherwise, a C string-based mapping is used:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  string "const char*";
+  normalizedString "const char*";
+  token "const char*";
+  Name "const char*";
+  NMTOKEN "const char*";
+  NCName "const char*";
+  ID "const char*";
+  IDREF "const char*";
+  language "const char*";
+  anyURI "const char*";
+
+  QName "const xml_schema::qname*";
+}
+  
+ +

For more information about the mapping of the built-in XML Schema types + to C++ types refer to Chapter 7, "Built-In XML Schema Type + Serializers". The last predefined rule maps anything that wasn't + mapped by previous rules to void:

+ +
+namespace .*
+{
+  .* void void;
+}
+  
+ + +

When you provide your own type maps with the + --type-map option, they are evaluated first. This + allows you to selectively override any + of the predefined rules. Note also that if you change the mapping + of a built-in XML Schema type then it becomes your responsibility + to provide the corresponding serializer skeleton and implementation + in the xml_schema namespace. You can include the + custom definitions into the generated header file using the + --hxx-prologue-* options.

+ +

4.3 Serializer Implementations

+ +

With the knowledge from the previous section, we can proceed + with creating a type map that maps types in the people.xsd + schema to our object model classes in + people.hxx. In fact, we already have the beginning + of our type map file in people.map. Let's extend + it with the rest of the types:

+ +
+include "people.hxx";
+
+gender ::gender ::gender;
+person "const ::person&";
+people "const ::people&";
+  
+ +

A few things to note about this type map. We decided to pass + the person and people objects by + constant references in order to avoid unnecessary copying. + We can do this because we know that our object model is + present for the duration of serialization. We also did not + provide any mappings for built-in XML Schema types + string and short because they + are handled by the predefined rules and we are happy with + the result. Note also that all C++ types are fully qualified. + This is done to avoid potential name conflicts in the generated + code. Now we can recompile our schema and move on to implementing + the serializers:

+ +
+$ xsde cxx-serializer --type-map people.map people.xsd
+  
+ +

Here is the implementation of our three serializers in full. One + way to save typing when implementing your own serializers is + to open the generated code and copy the signatures of serializer + callbacks into your code. Or you could always auto generate the + sample implementations and fill them with your code.

+ +
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+  gender_simpl ()
+    : gender_sskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  pre (gender g)
+  {
+    base_impl_.pre (gender_strings[g]);
+  }
+
+private:
+  xml_schema::string_simpl base_impl_;
+};
+
+class person_simpl: public person_sskel
+{
+public:
+  virtual void
+  pre (const person& p)
+  {
+    p_ = &p;
+  }
+
+  virtual std::string
+  first_name ()
+  {
+    return p_->first ();
+  }
+
+  virtual std::string
+  last_name ()
+  {
+    return p_->last ();
+  }
+
+  virtual ::gender
+  gender ()
+  {
+    return p_->gender ();
+  }
+
+  virtual short
+  age ()
+  {
+    return p_->age ();
+  }
+
+private:
+  const person* p_;
+};
+
+class people_simpl: public people_sskel
+{
+public:
+  virtual void
+  pre (const people& p)
+  {
+    p_ = &p;
+    i_ = p_->begin ();
+  }
+
+  virtual bool
+  person_next ()
+  {
+    return i_ != p_->end ();
+  }
+
+  virtual const ::person&
+  person ()
+  {
+    return *i_++;
+  }
+
+private:
+  const people* p_;
+  people::const_iterator i_;
+};
+  
+ +

This code fragment should look familiar by now. Just note that + all the pre() callbacks now have arguments. Here is the + implementation of the test driver for this example:

+ +
+#include <iostream>
+
+using namespace std;
+
+int
+main ()
+{
+  // Create a sample object model.
+  //
+  people ppl;
+
+  ppl.push_back (person ("John", "Doe", male, 32));
+  ppl.push_back (person ("Jane", "Doe", female, 28));
+
+  // Construct the serializer.
+  //
+  xml_schema::short_simpl 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, short_s);
+  people_s.serializers (person_s);
+
+  // Create the XML document.
+  //
+  xml_schema::document_simpl doc_s (people_s, "people");
+
+  people_s.pre (ppl);
+  doc_s.serialize (cout);
+  people_s.post ();
+}
+  
+ +

The serializer creation and assembly part is exactly the same as in + the previous chapter. The serialization part is a bit different: + people_simpl::pre() now has an argument which is the + complete object model. Also we write the resulting XML directly + to the standard output stream instead of first storing it in a string. + We can now save the last two code fragments to driver.cxx + and proceed to compile and test our new application:

+ + +
+$ c++ -I.../libxsde -c driver.cxx people-sskel.cxx
+$ c++ -o driver driver.o people-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+<people>
+  <person>
+    <first-name>John</first-name>
+    <last-name>Doe</last-name>
+    <gender>male</gender>
+    <age>32</age>
+  </person>
+  <person>
+    <first-name>Jane</first-name>
+    <last-name>Doe</last-name>
+    <gender>female</gender>
+    <age>28</age>
+  </person>
+</people>
+  
+ + + + +

5 Serializer Callbacks

+ +

In previous chapters we have learned that for each attribute + and element in a schema type there is a callback in a serializer + skeleton with the same name and which optionally returns + this element's or attribute's value. We've also seen that + elements that can appear multiple times + (maxOccurs="unbounded") have an additional + serializer callback in the form:

+ +
+virtual bool
+<name>_next ();
+  
+ +

Where <name> stands for the element's name. In + this chapter we will discuss other additional serializer + callbacks that are generated for certain XML Schema constructs. + We will also learn that besides elements and attributes, serializer + callback can be generated for the all, choice, + and sequence compositors as well as the any + and anyAttribute wildcards.

+ +

When additional serializer callback are generated for elements + and attributes, their names are derived from element's and + attribute's names. Compositors and wildcards, on the other + hand, do not have names and as a result the serializer + callback names for these constructs are based on synthesized + names in the form: all for the all + compositor, sequence, sequence1, + etc., for the sequence compositors, choice, + choice1, etc., for the choice compositors, + any, any1, etc., for the any + wildcards, and any_attribute, any_attribute1, + etc., for the anyAttribute wildcards. For example:

+ +
+<xs:complexType name="coordinates">
+  <xs:sequence maxOccurs="unbounded">
+    <xs:element name="lat" type="xs:float"/>
+    <xs:element name="lon" type="xs:float"/>
+  </xs:sequence>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class coordinates_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  virtual bool
+  sequence_next ();
+
+  virtual float
+  lan () = 0;
+
+  virtual float
+  lon () = 0;
+
+  virtual void
+  post ();
+
+  ...
+};
+  
+ + +

5.1 Optional Callback

+ +

For elements, compositors, and element wildcards with the minimal + occurrence constraint equals 0 (minOccurs="0") + and the maximum occurrence constraint equals 1 + (maxOccurs="1") as well as for optional attributes, the + optional callback is generated in the form:

+ +
+virtual bool
+<name>_present ();
+  
+ +

This callback is called before any other callbacks for this schema + construct and if it returns false no further callback + calls corresponding to this construct are made and the corresponding + XML fragment is omitted. For example:

+ +
+<xs:complexType name="name">
+  <xs:sequence minOccurs="0">
+    <xs:element name="first" type="xs:string"/>
+    <xs:element name="initial" type="xs:string" minOccurs="0"/>
+    <xs:element name="last" type="xs:string"/>
+  </xs:sequence>
+  <xs:attribute name="lang" type="xs:language"/>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  virtual bool
+  lang_present ();
+
+  virtual std::string
+  lang () = 0;
+
+  virtual bool
+  sequence_present ();
+
+  virtual std::string
+  first () = 0;
+
+  virtual bool
+  initial_present ();
+
+  virtual std::string
+  initial () = 0;
+
+  virtual std::string
+  last () = 0;
+
+  virtual void
+  post ();
+
+  ...
+};
+  
+ +

5.2 Sequence Callback

+ +

For elements, compositors, and element wildcards with the the maximum + occurrence constraint greater than 1 (for example, + maxOccurs="unbounded") the sequence callback is + generated in the form:

+ +
+virtual bool
+<name>_next ();
+  
+ +

This callback is called before each new item of the sequence is + about to be serialized. Returning false from this + callback indicates that no more items in the sequence need to + be serialized. For example:

+ +
+<xs:complexType name="names">
+  <xs:sequence maxOccurs="unbounded">
+    <xs:element name="first" type="xs:string"/>
+    <xs:element name="last" type="xs:string"/>
+    <xs:element name="pseudonym" type="xs:string" maxOccurs="3"/>
+  </xs:sequence>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class names_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  virtual bool
+  sequence_next () = 0;
+
+  virtual std::string
+  first () = 0;
+
+  virtual std::string
+  last () = 0;
+
+  virtual bool
+  pseudonym_next () = 0;
+
+  virtual std::string
+  pseudonym () = 0;
+
+  virtual void
+  post ();
+};
+  
+ +

5.3 Choice Callback

+ +

The choice compositor allows an XML document to contain one + of several element or compositor options. In the Embedded + C++/Serializer mapping, these options are called choice + arms and are identified by the arm tags. For + example:

+ +
+<xs:complexType name="name">
+  <xs:choice>
+    <xs:element name="full-name" type="xs:string"/>
+    <xs:sequence>
+      <xs:element name="first-name" type="xs:string"/>
+      <xs:element name="last-name" type="xs:string"/>
+    </xs:sequence>
+  </xs:choice>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  enum choice_arm_tag
+  {
+    full_name_tag,
+    sequence_tag
+  };
+
+  virtual choice_arm_tag
+  choice_arm () = 0;
+
+  virtual std::string
+  full_name () = 0;
+
+  virtual std::string
+  first_name () = 0;
+
+  virtual std::string
+  last_name () = 0;
+
+  virtual void
+  post ();
+};
+  
+ +

The arm tags enum name (choice_arm_tag above) is derived + from the choice compositor name (that is, choice, + choice1, etc.) by adding the _arm_tag + suffix. The tag names themselves are derived from the corresponding + elements, compositors, or element wildcards.

+ +

The choice compositor callback has a name in the form + choice_tag() (or choice1_tag(), etc., for + subsequent choice compositors in the type). It returns + the arm tag which identifies the choice arm that should be + serialized. For example, if a name_sskel implementation + returns full_name_tag from the choice_arm() + callback, then the first choice arm is chosen and + the full_name() callback is then called. Otherwise + the first_name and last_name() callbacks + are called.

+ + +

5.4 Element Wildcard Callbacks

+ +

An element wildcard allows an arbitrary element from the specified + namespace list to be present in an XML instance. Element wildcards + can have the same cardinality constraints as elements and, as as a + result, the optional or sequence callbacks can be generated. For + example:

+ +
+<xs:complexType name="name">
+  <xs:sequence>
+    <xs:element name="first" type="xs:string"/>
+    <xs:element name="last" type="xs:string"/>
+    <xs:any namespace="##other" processContents="skip" minOccurs="0"/>
+  </xs:sequence>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  virtual std::string
+  first () = 0;
+
+  virtual std::string
+  last () = 0;
+
+  virtual bool
+  any_present ();
+
+  virtual void
+  any (std::string& ns, std::string& name);
+
+  virtual void
+  serialize_any ();
+
+  virtual void
+  post ();
+};
+  
+ +

The any() callback is called to obtain the element + name and namespace. If validation is enabled, the namespace is + checked against the allowed list. Then an element with these name + and namespace is created and the serialize_any() + callback is called to allow you to serialize the element's attributes + and content. There are two common ways to serialize a wildcard + element. The first approach is to use a serializer implementation. + This approach is shown in the wildcard example which + is part of the XSD/e distribution. The other approach is to use + the low-level XML serialization API that is available to every + serializer implementation via the + xml_schema::serializer_base base serializer:

+ +
+namespace xml_schema
+{
+  class serializer_base
+  {
+  public:
+    void
+    _start_element (const char* name);
+
+    void
+    _start_element (const char* ns, const char* name);
+
+    void
+    _end_element ();
+
+    void
+    _start_attribute (const char* name);
+
+    void
+    _start_attribute (const char* ns, const char* name);
+
+    void
+    _end_attribute ();
+
+    void
+    _attribute (const char* name, const char* value);
+
+    void
+    _attribute (const char* ns, const char* name, const char* value);
+
+    void
+    _characters (const char*);
+
+    void
+    _characters (const char*, size_t);
+
+    void
+    _declare_namespace (const char* ns, const char* prefix);
+
+    void
+    _declare_default_namespace (const char* ns);
+
+    void
+    _clear_default_namespace ();
+  };
+}
+  
+ +

The following example shows how we could implement the + name_sskel skeleton using this approach:

+ +
+class name_simpl: public name_sskel
+{
+public:
+  virtual std::string
+  first ()
+  {
+    return "John";
+  }
+
+  virtual ::std::string
+  last ()
+  {
+    return "Doe";
+  }
+
+  virtual bool
+  any_present ()
+  {
+    return true;
+  }
+
+  virtual void
+  any (std::string& ns, std::string& name)
+  {
+    ns = "http://www.example.com/extension";
+    name = "pseudonyms";
+  }
+
+  virtual void
+  serialize_any ()
+  {
+    _attribute ("id", "jd");
+
+    _start_element ("pseudonym");
+    _characters ("Johnny Doer");
+    _end_element ();
+
+    _start_element ("pseudonym");
+    _characters ("Johnty Doo");
+    _end_element ();
+  }
+};
+  
+ + +

5.5 Attribute Wildcard Callbacks

+ +

An attribute wildcard allows an arbitrary number of attributes from + the specified namespace list to be present in an XML instance. As a + result, the serializer callbacks for an attribute wildcard resemble + those of an element with maxOccurs="unbounded". For + example:

+ +
+<xs:complexType name="name">
+  <xs:sequence>
+    <xs:element name="first" type="xs:string"/>
+    <xs:element name="last" type="xs:string"/>
+  </xs:sequence>
+  <xs:anyAttribute namespace="##any" processContents="skip"/>
+</xs:complexType>
+  
+ +

The above schema fragment, when compiled, results in the following + serializer skeleton:

+ +
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+  virtual void
+  pre ();
+
+  virtual bool
+  any_attribute_next ();
+
+  virtual void
+  any_attribute (std::string& ns, std::string& name);
+
+  virtual void
+  serialize_any_attribute ();
+
+  virtual std::string
+  first () = 0;
+
+  virtual std::string
+  last () = 0;
+
+  virtual void
+  post ();
+};
+  
+ +

Every time the any_attribute_next() callback returns + true, any_attribute() is called to obtain + the attribute name and namespace. If validation is enabled, the + namespace is checked against the allowed list. Then an attribute + with these name and namespace is created and the + serialize_any_attribute() callback is called to allow + you to write the attribute value, for example using one of the + serializer implementations (see the wildcard example + on how to do it) or the low-level _characters() function + (for more information about the low-level XML serialization + API see the previous section). The following example show + how we could implement the name_sskel skeleton + using the latter approach:

+ +
+class name_simpl: public name_sskel
+{
+public:
+  virtual void
+  pre ()
+  {
+    id_written_ = false;
+  }
+
+  virtual bool
+  any_attribute_next ()
+  {
+    return !id_written_;
+  }
+
+  virtual void
+  any_attribute (std::string& ns, std::string& name)
+  {
+    ns = "";
+    name = "id";
+  }
+
+  virtual void
+  serialize_any_attribute ()
+  {
+    _characters ("jd");
+    id_written_ = true;
+  }
+
+  virtual std::string
+  first ()
+  {
+    return "John";
+  }
+
+  virtual ::std::string
+  last ()
+  {
+    return "Doe";
+  }
+
+private:
+  bool id_written_;
+};
+  
+ + + + + +

6 Mapping Configuration

+ +

The Embedded C++/Serializer mapping has a number of configuration + parameters that determine the overall properties and behavior + of the generated code, such as the use of Standard Template + Library (STL), Input/Output Stream Library (iostream), C++ + exceptions, XML Schema validation, 64-bit integer types, serializer + implementation reuse styles, and support for XML Schema polymorphism. + Previous chapters assumed that the use of STL, iostream, C++ + exceptions, and XML Schema validation were enabled. + This chapter will discuss the changes in the Embedded C++/Serializer + programming model that result from the changes to these configuration + parameters. A complete example that uses the minimal mapping + configuration is presented at the end of this chapter.

+ +

In order to enable or disable a particular feature, the corresponding + configuration parameter should be set accordingly in the XSD/e runtime + library as well as specified during schema compilation with the XSD/e + command line options as described in the + XSD/e + Compiler Command Line Manual. +

+ +

The Embedded C++/Serializer mapping always expects character data + supplied by the application to be in the UTF-8 encoding. The + underlying XML serializer used by the Embedded C++/Serializer + mapping produces the resulting XML in the UTF-8 encoding as + well.

+ +

6.1 Standard Template Library

+ +

To disable the use of STL you will need to configure the XSD/e + runtime without support for STL as well as pass the + --no-stl option to the XSD/e compiler when + translating your schemas. When STL is disabled, all string-based + XML Schema types are mapped to C-style const char* + instead of std::string, as described in + Section 4.2, "Type Map File Format". The + following code fragment shows changes in the + signatures of the first_name() and last_name() + callbacks from the person record example.

+ +
+class person_sskel
+{
+public:
+  virtual const char*
+  first_name ();
+
+  virtual const char*
+  last_name ();
+
+  ...
+};
+  
+ +

When STL is disabled, the serializer implementations for the string-based + built-in XML Schema types can be instructed to release the string + after serialization using operator delete[]. For more + information on how to do this refer to Section 7.2, + "String-Based Type Serializers". +

+ +

6.2 Input/Output Stream Library

+ +

To disable the use of iostream you will need to configure the + XSD/e runtime library without support for iostream as well as + pass the --no-iostream option to the XSD/e compiler + when translating your schemas. When iostream is disabled, the + following serialize() function in the + xml_schema::document_simpl class become unavailable:

+ +
+void
+serialize (std::ostream&);
+  
+ +

See Section 8.1, "Document Serializer" + for more information.

+ +

6.3 C++ Exceptions

+ +

To disable the use of C++ exceptions, you will need to configure + the XSD/e runtime without support for exceptions as well as pass + the --no-exceptions option to the XSD/e compiler + when translating your schemas. When C++ exceptions are disabled, + the error conditions are indicated with error codes instead of + exceptions, as described in Section 8.3, + "Error Codes". +

+ +

6.4 XML Schema Validation

+ +

To disable support for XML Schema validation, you will need to + configure the XSD/e runtime accordingly as well as pass + the --suppress-validation option to the XSD/e compiler + when translating your schemas. Disabling XML Schema validation + allows to further increase the serialization performance and + reduce footprint in cases where the data being serialized is + known to be valid. +

+ +

6.5 64-bit Integer Type

+ +

By default the 64-bit long and unsignedLong + XML Schema built-in types are mapped to the 64-bit long long + and unsigned long long fundamental C++ types. To + disable the use of these types in the mapping you will need to + configure the XSD/e runtime accordingly as well as pass + the --no-long-long option to the XSD/e compiler + when translating your schemas. When the use of 64-bit integral + C++ types is disabled the long and + unsignedLong XML Schema built-in types are mapped + to long and unsigned long fundamental + C++ types.

+ +

6.6 Serializer Reuse

+ +

When one type in XML Schema inherits from another, it is + often desirable to be able to reuse the serializer implementation + corresponding to the base type in the serializer implementation + corresponding to the derived type. XSD/e provides support + for two serializer reuse styles: the so-called mixin + (generated when the --reuse-style-mixin option + is specified) and tiein (generated by default) styles.

+ +

The compiler can also be instructed not to generate any support + for serializer reuse with the --reuse-style-none option. + This is mainly useful to further reduce the generated code size + when your vocabulary does not use inheritance or when you plan + to implement each serializer from scratch. Note also that the + XSD/e runtime should be configured in accordance with the + serializer reuse style used in the generated code. The remainder + of this section discusses the mixin and tiein serializer reuse + styles in more detail.

+ + +

To provide concrete examples for each reuse style we will use the + following schema fragment:

+ +
+<xs:complexType name="person">
+  <xs:sequence>
+    <xs:element name="first-name" type="xs:string"/>
+    <xs:element name="last-name" type="xs:string"/>
+    <xs:element name="age" type="xs:short"/>
+  </xs:sequence>
+</xs:complexType>
+
+<xs:complexType name="emplyee">
+  <complexContent>
+    <extension base="person">
+      <xs:sequence>
+        <xs:element name="position" type="xs:string"/>
+        <xs:element name="salary" type="xs:unsignedLong"/>
+      </xs:sequence>
+    </extension>
+  </complexContent>
+</xs:complexType>
+  
+ +

The mixin serializer reuse style uses the C++ mixin idiom that + relies on multiple and virtual inheritance. Because + virtual inheritance can result in a significant object + code size increase, this reuse style should be considered + when such an overhead is acceptable and/or the vocabulary + consists of only a handful of types. When the mixin reuse + style is used, the generated serializer skeletons use virtual + inheritance, for example:

+ +
+class person_sskel: public virtual serializer_complex_content
+{
+  ...
+};
+
+class employee_sskel: public virtual person_sskel
+{
+  ...
+};
+  
+ + +

When you implement the base serializer you also need to use + virtual inheritance. The derived serializer is implemented + by inheriting from both the derived serializer skeleton and + the base serializer implementation (that is, mixing in + the base serializer implementation), for example:

+ +
+class person_simpl: public virtual person_sskel
+{
+  ...
+};
+
+class employee_simpl: public employee_sskel,
+                      public person_simpl
+{
+  ...
+};
+  
+ + +

The tiein serializer reuse style uses delegation and normally + results in a significantly smaller object code while being + almost as convenient to use as the mixin style. When the + tiein reuse style is used, the generated derived serializer + skeleton declares a constructor which allows you to specify + the implementation of the base serializer:

+ +
+class person_sskel: public serializer_complex_content
+{
+  ...
+};
+
+class employee_sskel: public person_sskel
+{
+public:
+  employee_sskel (person_sskel* base_impl)
+
+  ...
+};
+  
+ +

If you pass the implementation of the base serializer to this + constructor then the generated code will transparently + forward all the callbacks corresponding to the base serializer + skeleton to this implementation. You can also pass + 0 to this constructor in which case you will + need to implement the derived serializer from scratch. The + following example shows how we could implement the + person and employee serializers + using the tiein style:

+ +
+class person_simpl: public person_sskel
+{
+  ...
+};
+
+class employee_simpl: public employee_sskel
+{
+public:
+  employee_simpl ()
+    : employee_sskel (&base_impl_)
+  {
+  }
+
+  ...
+
+private:
+  person_simpl base_impl_;
+};
+  
+ +

Note that you cannot use the tied in base serializer + instance (base_impl_ in the above code) for + serializing anything except the derived type.

+ +

The ability to override the base serializer callbacks in the + derived serializer is also available in the tiein style. For + example, the following code fragment shows how we can + override the age() callback if we didn't + like the implementation provided by the base serializer:

+ +
+class employee_simpl: public employee_sskel
+{
+public:
+  employee_simpl ()
+    : employee_sskel (&base_impl_)
+  {
+  }
+
+  virtual short
+  age ()
+  {
+    ...
+  }
+
+  ...
+
+private:
+  person_simpl base_impl_;
+};
+  
+ +

In the above example the age element will be + handled by emplyee_simpl while the first-name + and last-name callbacks will still go to + base_impl_.

+ +

It is also possible to inherit from the base serializer implementation + instead of declaring it as a member variable. This can be useful + if you need to access protected members in the base implementation + or need to override a virtual function that is not part of + the serializer skeleton interface. Note, however, that in this case + you will need to resolve a number of ambiguities with explicit + qualifications or using-declarations. For example:

+ + +
+class person_simpl: public person_sskel
+{
+public:
+  virtual void
+  pre (person* p)
+  {
+    person_ = p;
+  }
+
+  ...
+
+protected:
+  person* person_;
+};
+
+class employee_simpl: public employee_sskel,
+                      public person_simpl
+{
+public:
+  employee_simpl ()
+    : employee_sskel (static_cast<person_simpl*> (this))
+  {
+  }
+
+  // Resolve ambiguities.
+  //
+  using emplyee_sskel::serializers;
+
+  virtual void
+  pre (employee* e)
+  {
+    person_simpl::pre (e);
+  }
+
+  virtual std::string
+  position ()
+  {
+    return static_cast<employee*> (person_)->position ();
+  }
+
+  virtual unsigned int
+  salary ()
+  {
+    return static_cast<employee*> (person_)->salary ();
+  }
+};
+  
+ +

6.7 Support for Polymorphism

+ +

By default the XSD/e compiler generates non-polymorphic code. If your + vocabulary uses XML Schema polymorphism in the form of xsi:type + and/or substitution groups, then you will need to configure the XSD/e + runtime with support for polymorphism, compile your schemas with the + --generate-polymorphic option to produce polymorphism-aware + code, as well as pass true as the last argument to the + xml_schema::document's constructors. If some of your + schemas do not require support for polymorphism then you can compile + them with the --runtime-polymorphic option and still + use the XSD/e runtime configured with polymorphism support. +

+ +

When using the polymorphism-aware generated code, you can specify + several serializers for a single element by passing a serializer map + instead of an individual serializer to the serializer connection function + for the element. One of the serializers will then be looked up and used + depending on the user-provided type information that can optionally be + set in the callback function for the element. Consider the following + schema as an example:

+ +
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:complexType name="person">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <!-- substitution group root -->
+  <xs:element name="person" type="person"/>
+
+  <xs:complexType name="superman">
+    <xs:complexContent>
+      <xs:extension base="person">
+        <xs:attribute name="can-fly" type="xs:boolean"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="superman"
+              type="superman"
+              substitutionGroup="person"/>
+
+  <xs:complexType name="batman">
+    <xs:complexContent>
+      <xs:extension base="superman">
+        <xs:attribute name="wing-span" type="xs:unsignedInt"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:complexType name="supermen">
+    <xs:sequence>
+      <xs:element ref="person" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="supermen" type="supermen"/>
+
+</xs:schema>
+  
+ +

Conforming XML documents can use the superman + and batman types in place of the person + type either by specifying the type with the xsi:type + attributes or by using the elements from the substitution + group, for instance:

+ +
+<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <person>
+    <name>John Doe</name>
+  </person>
+
+  <superman can-fly="false">
+    <name>James "007" Bond</name>
+  </superman>
+
+  <person can-fly="true" wing-span="10" xsi:type="batman">
+    <name>Bruce Wayne</name>
+  </person>
+
+</supermen>
+  
+ +

The C++ object model for this vocabulary might look as follows:

+ +
+#include <string>
+#include <vector>
+
+enum type_id
+{
+  person_type,
+  superman_type,
+  batman_type
+};
+
+class person
+{
+public:
+  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_;
+};
+
+class superman: public person
+{
+public:
+  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_;
+};
+
+class batman: public superman
+{
+public:
+  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.
+//
+class supermen: public std::vector<person*>
+{
+public:
+  ~supermen ()
+  {
+    for (iterator i = begin (); i != end (); ++i)
+      delete *i;
+  }
+};
+  
+ +

Here we choose to provide our own type information. We can instead + use the standard C++ typeid/type_info + mechanism if it is available. The type map corresponding to this + object model is presented below. Notice that the superman + and batman objects are passed as a reference to + person:

+ +
+person   "const ::person&";
+superman "const ::person&";
+batman   "const ::person&";
+supermen "const ::supermen&";
+  
+ +

The serializer implementations that serialize the above + C++ object model to XML are presented next:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual void
+  pre (const person& p)
+  {
+    person_ = &p;
+  }
+
+  virtual std::string
+  name ()
+  {
+    return person_->name ();
+  }
+
+  // Derived serializer implementations need access to this
+  // member variable.
+  //
+public:
+  const person* person_;
+};
+
+class superman_simpl: public superman_sskel
+{
+public:
+  superman_simpl ()
+    : superman_sskel (&base_impl_)
+  {
+  }
+
+  virtual bool
+  can_fly ()
+  {
+    return superman_ ().can_fly ();
+  }
+
+  const superman&
+  superman_ ()
+  {
+    return *static_cast<const superman*> (base_impl_.person_);
+  }
+
+private:
+  person_simpl base_impl_;
+};
+
+class batman_simpl: public batman_sskel
+{
+public:
+  batman_simpl ()
+    : batman_sskel (&base_impl_)
+  {
+  }
+
+  virtual unsigned int
+  wing_span ()
+  {
+    return batman_ ().wing_span ();
+  }
+
+  const batman&
+  batman_ ()
+  {
+    return static_cast<const batman&> (base_impl_.superman_ ());
+  }
+
+private:
+  superman_simpl base_impl_;
+};
+
+class supermen_simpl: public supermen_sskel
+{
+public:
+  virtual void
+  pre (const supermen& s)
+  {
+    supermen_ = &s;
+    i_ = s.begin ();
+  }
+
+  virtual bool
+  person_next ()
+  {
+    return i_ != supermen_->end ();
+  }
+
+  virtual const ::person&
+  person ()
+  {
+    const ::person& p = **i_++;
+    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;
+  }
+
+private:
+  const supermen* supermen_;
+  supermen::const_iterator i_;
+};
+  
+ +

Most of the code in these serializer implementations is the same + as in the non-polymorphic case. The only part that explicitly deals + with polymorphism is the person() callback in the + superman_simpl class. In it we are translating + the type information as provided by the C++ object mode to + the type information used in the default implementation of + the serializer map (we will talk more about serializer maps + as well as the _static_type() function shortly). + The type_id() function from + xml_schema::serializer_context allows you to + specify optional type information which is used to look up + the corresponding serializer. Its argument is of type + const void* which allows you to pass + application-specific type information as an opaque pointer.

+ +

The following code fragment shows how to connect the serializers + together and then use them to serialize a sample object model. + Notice that for the person element in the + instance_s serializer we specify a serializer map + instead of a specific serializer and we pass true as + the last argument to the document serializer constructor to indicate + that we are serializing potentially-polymorphic XML documents:

+ +
+int
+main ()
+{
+  // 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);
+
+  supermen_s.pre (sm);
+  doc_s.serialize (std::cout);
+  supermen_s.post ();
+}
+  
+ +

When polymorphism-aware code is generated, each element's + *_serializer() function is overloaded to also accept + an object of the xml_schema::serializer_map type. + For example, the supermen_sskel class from the + above example looks like this:

+ +
+class supermen_sskel: public xml_schema::serializer_complex_content
+{
+public:
+
+  ...
+
+  // Serializer construction API.
+  //
+  void
+  serializers (person_sskel&);
+
+  // Individual element serializers.
+  //
+  void
+  person_serializer (person_sskel&);
+
+  void
+  person_serializer (xml_schema::serializer_map&);
+
+  ...
+};
+  
+ +

Note that you can specify both the individual (static) serializer and + the serializer map. The individual serializer will be used when the static + element type and the dynamic type of the object being serialized are + the same. This is the case when the type_id() function + hasn't been called or the type information pointer is set to + 0. Because the individual serializer for an element + is cached and no map lookup is necessary, it makes sense to specify + both the individual serializer and the serializer map when most of + the objects being serialized are of the static type and optimal + performance is important. The following code fragment shows how + to change the above example to set both the individual serializer + and the serializer map:

+ +
+int
+main ()
+{
+  ...
+
+  // Here we are specifying several serializers that can be
+  // used to serialize the person element.
+  //
+  person_map.insert (superman_s);
+  person_map.insert (batman_s);
+
+  supermen_s.person_serializer (person_s);
+  supermen_s.person_serializer (person_map);
+
+  ...
+}
+  
+ + +

The xml_schema::serializer_map interface and its + default implementation, xml_schema::serializer_map_impl, + are presented below:

+ +
+namespace xml_schema
+{
+  class serializer_map
+  {
+  public:
+    virtual serializer_base*
+    find (const void* type_id) const = 0;
+
+    virtual void
+    reset () const = 0;
+  };
+
+  class serializer_map_impl: public serializer_map
+  {
+  public:
+    serializer_map_impl (size_t buckets);
+
+    // Note that the type_id string is not copied so it should
+    // be valid for the lifetime of the map.
+    //
+    void
+    insert (const char* type_id, serializer_base&);
+
+    // This version of insert is a shortcut that uses the string
+    // returned by the serializer's _dynamic_type() function.
+    //
+    void
+    insert (serializer_base&);
+
+    virtual serializer_base*
+    find (const void* type_id) const;
+
+    virtual void
+    reset () const;
+
+  private:
+    serializer_map_impl (const serializer_map_impl&);
+
+    serializer_map_impl&
+    operator= (const serializer_map_impl&);
+
+    ...
+  };
+}
+  
+ +

The type_id argument in the find() virtual + function is the application-specific type information for the object + being serialized that is specified using the type_id() + function in the element callback. It is passed as an opaque + const void*. The reset() virtual function + is used to reset the serializers contained in the map (as opposed to + resetting or clearing the map itself). For more information on serializer + resetting refer to Section 8.4, "Reusing Serializers + after an Error".

+ +

The XSD/e runtime provided the default implementation for the + xml_schema::serializer_map interface, + xml_schema::serializer_map_impl, which uses a C string + (const char*) as type information. One way to + obtain a serializer's dynamic type in the form + "<name> <namespace>" with the space and the + namespace part absent if the type does not have a namespace + is to call the _dynamic_type() function on this + serializer. The static type can be obtained by calling the static + _static_type() function, for example + person_sskel::_static_type(). Both functions return + a C string (const char*) which is valid for as long + as the application is running.

+ +

The default serializer map implementation is a hashmap. It requires + that you specify the number of buckets it will contain and it does + not support automatic table resizing. To obtain good performance the + elements to buckets ratio should be between 0.7 and 0.9. It is also + recommended to use prime numbers for bucket counts: + 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, + 196613, 393241. +

+ +

If C++ exceptions are disabled (Section 5.3, + "C++ Exceptions"), the xml_schema::serializer_map_impl + class has the following additional error querying API. It can be used + to detect the out of memory errors after calls to the + serializer_map_impl's constructor and insert() + functions.

+ +
+namespace xml_schema
+{
+  class serializer_map_impl: public serializer_map
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    error
+    _error () const;
+
+    ...
+  };
+}
+  
+ +

You can also provide your own serializer map implementation which uses + custom type information. The following example shows how we can + implement our own serializer map for the above example that uses + the type information provided by the C++ object model:

+ +
+#include <map>
+
+class person_serializer_map: public xml_schema::serializer_map
+{
+public:
+ void
+ insert (person_sskel& p)
+ {
+   const char* dt = p._dynamic_type ();
+   type_id ti;
+
+   if (strcmp (dt, person_sskel::_static_type ()) == 0)
+     ti = person_type;
+   else if (strcmp (dt, superman_sskel::_static_type ()) == 0)
+     ti = superman_type;
+   else if (strcmp (dt, batman_sskel::_static_type ()) == 0)
+     ti = batman_type;
+   else
+     return;
+
+   map_[ti] = &p;
+ }
+
+ virtual xml_schema::serializer_base*
+ find (const char* x) const
+ {
+   const person* p = static_cast<const person*> (x);
+   map::const_iterator i = map_.find (p->type ());
+   return i != map_.end () ? i->second : 0;
+ }
+
+ virtual void
+ reset () const
+ {
+   for (map::const_iterator i (map_.begin ()), e (map_.end ());
+        i != e; ++i)
+   {
+     person_sskel* s = i->second;
+     s->_reset ();
+   }
+ }
+
+private:
+  typedef std::map<type_id, person_sskel*> map;
+  map map_;
+};
+  
+ +

Our custom implementation of the serializer map expects that + we pass the actual object to the find() function. + To account for this will need to change the + supermen_simpl::person() callback as follows:

+ +
+  virtual const ::person&
+  person ()
+  {
+    const ::person& p = **i_++;
+    _context ().type_id (&p);
+    return p;
+  }
+  
+ + +

To support polymorphic serialization the XSD/e runtime and generated + code maintain a number of hashmaps that contain substitution and, if + XML Schema validation is enabled (Section 5.4, + "XML Schema Validation"), inheritance information. Because + the number of elements in these hashmaps depends on the schemas + being compiled and thus is fairly static, these hashmaps do not + perform automatic table resizing and instead the number of buckets + is specified when the XSD/e runtime is configured. To obtain good + performance the elements to buckets ratio in these hashmaps should + be between 0.7 and 0.9. The recommended way to ensure this range + is to add diagnostics code to your application as shown in the + following example:

+ +
+int
+main ()
+{
+  // Check that the load in substitution and inheritance hashmaps
+  // is not too high.
+  //
+#ifndef NDEBUG
+  float load = 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 = 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;
+  }
+
+  load = 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
+
+  ...
+}
+  
+ +

Most of the code presented in this section is taken from the + polymorphism example which can be found in the + examples/cxx/serializer/ directory of the XSD/e distribution. + Handling of xsi:type and substitution groups when used + on root elements requires a number of special actions as shown in + the polyroot example.

+ +

6.8 A Minimal Example

+ +

The following example is a re-implementation of the person + records example presented in Chapter 4, + "Type Maps". It is intended to work without STL, + iostream, and C++ exceptions. It can be found in the + examples/cxx/serializer/minimal/ directory of the + XSD/e distribution. The people.xsd schema is + compiled with the --no-stl, --no-iostream, + and --no-exceptions options. The object model + types in people.hxx have also been reimplemented + in order not to use STL types:

+ +
+#include <stddef.h> // 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_;
+};
+  
+ + +

The following listing presents the implementation of serializer + skeletons and the test driver in full:

+ +
+#include <stdio.h>
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+  gender_simpl ()
+    : gender_sskel (&base_impl_)
+  {
+  }
+
+  virtual void
+  pre (gender g)
+  {
+    base_impl_.pre (gender_strings[g]);
+  }
+
+private:
+  public xml_schema::string_simpl base_impl_;
+};
+
+class person_simpl: public person_sskel
+{
+public:
+  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_;
+};
+
+class people_simpl: public people_sskel
+{
+public:
+  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_;
+};
+
+class writer: public xml_schema::writer
+{
+public:
+  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;
+      }
+    case error::schema:
+      {
+        fprintf (stderr, "error: %s\n", e.schema_text ());
+        break;
+      }
+    case error::app:
+      {
+        fprintf (stderr, "application error: %d\n", e.app_code ());
+        break;
+      }
+    default:
+      break;
+    }
+
+    return 1;
+  }
+
+  return 0;
+}
+  
+ + + + + +

7 Built-In XML Schema Type Serializers

+ +

The XSD/e runtime provides serializer implementations for all built-in + XML Schema types as summarized in the following table. Declarations + for these types are automatically included into each generated + header file. As a result you don't need to include any headers + to gain access to these serializer implementations.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
XML Schema typeSerializer implementation in the xml_schema namespaceSerializer argument type
anyType and anySimpleType types
anyTypeany_type_simplvoid
anySimpleTypeany_simple_type_simplvoid
fixed-length integral types
bytebyte_simplsigned char
unsignedByteunsigned_byte_simplunsigned char
shortshort_simplshort
unsignedShortunsigned_short_simplunsigned short
intint_simplint
unsignedIntunsigned_int_simplunsigned int
longlong_simpllong long or long
+ Section 6.5, "64-bit Integer Type"
unsignedLongunsigned_long_simplunsigned long long or + unsigned long
+ Section 6.5, "64-bit Integer Type"
arbitrary-length integral types
integerinteger_simpllong
nonPositiveIntegernon_positive_integer_simpllong
nonNegativeIntegernon_negative_integer_simplunsigned long
positiveIntegerpositive_integer_simplunsigned long
negativeIntegernegative_integer_simpllong
boolean types
booleanboolean_simplbool
fixed-precision floating-point types
floatfloat_simplfloat
+ Section 7.1, "Floating-Point Type Serializers"
doubledouble_simpldouble
+ Section 7.1, "Floating-Point Type Serializers"
arbitrary-precision floating-point types
decimaldecimal_simpldouble
+ Section 7.1, "Floating-Point Type Serializers"
string-based types
stringstring_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
normalizedStringnormalized_string_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
tokentoken_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
Namename_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
NMTOKENnmtoken_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
NCNamencname_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
languagelanguage_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
qualified name
QNameqname_simplconst xml_schema::qname& or
+ const xml_schema::qname*
+ Section 7.3, "QName Serializer"
ID/IDREF types
IDid_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
IDREFidref_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
list types
NMTOKENSnmtokens_simplconst xml_schema::string_sequence*
Section + 7.4, "NMTOKENS and IDREFS Serializers"
IDREFSidrefs_simplconst xml_schema::string_sequence*
Section + 7.4, "NMTOKENS and IDREFS Serializers"
URI types
anyURIuri_simplconst std::string& or
const char*
+ Section 7.2, "String-Based Type Serializers"
binary types
base64Binarybase64_binary_simplconst xml_schema::buffer*
+ Section 7.5, "base64Binary and + hexBinary Serializers"
hexBinaryhex_binary_simplconst xml_schema::buffer*
+ Section 7.5, "base64Binary and + hexBinary Serializers"
date/time types
datedate_simplconst xml_schema::date&
+ Section 7.7, "date Serializer"
dateTimedate_time_simplconst xml_schema::date_time&
+ Section 7.8, "dateTime Serializer"
durationduration_simplconst xml_schema::duration&
+ Section 7.9, "duration Serializer"
gDaygday_simplconst xml_schema::gday&
+ Section 7.10, "gDay Serializer"
gMonthgmonth_simplconst xml_schema::gmonth&
+ Section 7.11, "gMonth Serializer"
gMonthDaygmonth_day_simplconst xml_schema::gmonth_day&
+ Section 7.12, "gMonthDay Serializer"
gYeargyear_simplconst xml_schema::gyear&
+ Section 7.13, "gYear Serializer"
gYearMonthgyear_month_simplconst xml_schema::gyear_month&
+ Section 7.14, "gYearMonth Serializer"
timetime_simplconst xml_schema::time&
+ Section 7.15, "time Serializer"
+ +

7.1 Floating-Point Type Serializers

+ +

The serializer implementations for the float, + double, and decimal built-in + XML Schema types allow you to specify the resulting + notation (fixed or scientific) as well as precision. + This is done by passing the corresponding arguments + to their constructors:

+ +
+namespace xml_schema
+{
+  class float_simpl: public float_sskel
+  {
+    enum notation
+    {
+      notation_auto,
+      notation_fixed,
+      notation_scientific
+    };
+
+    float_simpl (notation = notation_auto,
+                 unsigned int precision = FLT_DIG);
+
+    virtual void
+    pre (float);
+
+    ...
+  };
+
+  class double_simpl: public double_sskel
+  {
+    enum notation
+    {
+      notation_auto,
+      notation_fixed,
+      notation_scientific
+    };
+
+    double_simpl (notation = notation_auto,
+                  unsigned int precision = DBL_DIG);
+
+    virtual void
+    pre (double);
+
+    ...
+  };
+
+  class decimal_simpl: public decimal_sskel
+  {
+    decimal_simpl (unsigned int precision = DBL_DIG);
+
+    virtual void
+    pre (double);
+
+    ...
+  };
+}
+  
+ +

By default the notation for the float and double + types is automatically selected to produce the shortest representation. + Note that the decimal values are always serialized in + the fixed-point notation.

+ +

7.2 String-Based Type Serializers

+ +

When STL is enabled (Section 6.1, "Standard Template + Library"), the serializer argument type for the string, + normalizedString, token, + Name, NMTOKEN, NCName, + ID, IDREF, language, + and anyURI built-in XML Schema types is + const std::string&. When STL is disabled, the value + is passed as a constant C-string: const char*. + In this case, you can also instruct the serializer + implementations for string-based types to release the + string with operator delete[] by passing + true to their constructors. For instance, + using the person records example from the previous chapter:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual const char*
+  first_name ()
+  {
+    char* r = new char[5];
+    strcpy (r, "John");
+    return r;
+  }
+
+  virtual const char*
+  last_name ()
+  {
+    char* r = new char[4];
+    strcpy (r, "Doe");
+    return r;
+  }
+
+  ...
+};
+
+int
+main ()
+{
+  // Construct the serializer.
+  //
+  xml_schema::unsigned_short_simpl unsigned_short_s;
+  xml_schema::string_simpl string_s (true); // Release the string passed.
+
+  gender_simpl gender_s;
+  person_simpl person_s;
+  people_simpl people_s;
+
+  person_s.serializers (string_s, string_s, gender_s, unsigned_short_s);
+
+  ...
+}
+  
+ +

7.3 QName Serializer

+ +

The argument type of the qname_simpl serializer + implementation is either const xml_schema::qname& + when STL is enabled (Section 6.1, "Standard Template + Library") or const xml_schema::qname* when STL + is disabled. The qname class represents an XML + qualified name. When the argument type is const + xml_schema::qname*, you can optionally instruct the + serializer to release the qname object with operator + delete by passing true to its + constructor.

+ +

With STL enabled, the qname type has the following + interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (const std::string& name);
+    qname (const std::string& prefix, const std::string& name);
+
+    void
+    swap (qname&);
+
+    const std::string&
+    prefix () const;
+
+    std::string&
+    prefix ();
+
+    void
+    prefix (const std::string&);
+
+    const std::string&
+    name () const;
+
+    std::string&
+    name ();
+
+    void
+    name (const std::string&);
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

When STL is disabled and C++ exceptions are enabled + (Section 6.3, "C++ Exceptions"), the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    void
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    void
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+
+ +

The modifier functions and constructors that have the char* + argument assume ownership of the passed strings which should be allocated + with operator new char[] and will be deallocated with + operator delete[] by the qname object. + If you detach the underlying prefix or name strings, then they + should eventually be deallocated with operator delete[]. +

+ +

Finally, if both STL and C++ exceptions are disabled, the + qname type has the following interface:

+ +
+namespace xml_schema
+{
+  class qname
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    qname ();
+
+    explicit
+    qname (char* name);
+    qname (char* prefix, char* name);
+
+    void
+    swap (qname&);
+
+  private:
+    qname (const qname&);
+
+    qname&
+    operator= (const qname&);
+
+  public:
+    char*
+    prefix ();
+
+    const char*
+    prefix () const;
+
+    void
+    prefix (char*);
+
+    error
+    prefix_copy (const char*);
+
+    char*
+    prefix_detach ();
+
+  public:
+    char*
+    name ();
+
+    const char*
+    name () const;
+
+    void
+    name (char*);
+
+    error
+    name_copy (const char*);
+
+    char*
+    name_detach ();
+  };
+
+  bool
+  operator== (const qname&, const qname&);
+
+  bool
+  operator!= (const qname&, const qname&);
+}
+  
+ +

7.4 NMTOKENS and IDREFS Serializers

+ +

The argument type of the nmtokens_simpl and + idrefs_simpl serializer implementations is + const xml_schema::string_sequence*. You can + optionally instruct these serializers to release the + string_sequence object with operator delete + by passing true to their constructors. With STL and C++ exceptions enabled + (Section 6.1, "Standard Template Library", + Section 6.3, "C++ Exceptions"), the + string_sequence type has the following interface:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    typedef std::string         value_type;
+    typedef std::string*        pointer;
+    typedef const std::string*  const_pointer;
+    typedef std::string&        reference;
+    typedef const std::string&  const_reference;
+
+    typedef size_t              size_type;
+    typedef ptrdiff_t           difference_type;
+
+    typedef std::string*        iterator;
+    typedef const std::string*  const_iterator;
+
+  public:
+    string_sequence ();
+
+    void
+    swap (string_sequence&);
+
+  private:
+    string_sequence (string_sequence&);
+
+    string_sequence&
+    operator= (string_sequence&);
+
+  public:
+    iterator
+    begin ();
+
+    const_iterator
+    begin () const;
+
+    iterator
+    end ();
+
+    const_iterator
+    end () const;
+
+    std::string&
+    front ();
+
+    const std::string&
+    front () const;
+
+    std::string&
+    back ();
+
+    const std::string&
+    back () const;
+
+    std::string&
+    operator[] (size_t);
+
+    const std::string&
+    operator[] (size_t) const;
+
+  public:
+    bool
+    empty () const;
+
+    size_t
+    size () const;
+
+    size_t
+    capacity () const;
+
+    size_t
+    max_size () const;
+
+  public:
+    void
+    clear ();
+
+    void
+    pop_back ();
+
+    iterator
+    erase (iterator);
+
+    void
+    push_back (const std::string&);
+
+    iterator
+    insert (iterator, const std::string&);
+
+    void
+    reserve (size_t);
+  };
+
+  bool
+  operator== (const string_sequence&, const string_sequence&);
+
+  bool
+  operator!= (const string_sequence&, const string_sequence&);
+}
+  
+ +

When STL is enabled and C++ exceptions are disabled, the signatures + of the push_back(), insert(), and + reserve() functions change as follows:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    ...
+
+  public:
+    error
+    push_back (const std::string&);
+
+    error
+    insert (iterator, const std::string&);
+
+    error
+    insert (iterator, const std::string&, iterator& result);
+
+    error
+    reserve (size_t);
+  };
+}
+  
+ +

When STL is disabled and C++ exceptions are enabled, the + string_sequence type has the following interface:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    typedef char*         value_type;
+    typedef char**        pointer;
+    typedef const char**  const_pointer;
+    typedef char*         reference;
+    typedef const char*   const_reference;
+
+    typedef size_t        size_type;
+    typedef ptrdiff_t     difference_type;
+
+    typedef char** iterator;
+    typedef const char* const* const_iterator;
+
+    string_sequence ();
+
+    void
+    swap (string_sequence&);
+
+  private:
+    string_sequence (string_sequence&);
+
+    string_sequence&
+    operator= (string_sequence&);
+
+  public:
+    iterator
+    begin ();
+
+    const_iterator
+    begin () const;
+
+    iterator
+    end ();
+
+    const_iterator
+    end () const;
+
+    char*
+    front ();
+
+    const char*
+    front () const;
+
+    char*
+    back ();
+
+    const char*
+    back () const;
+
+    char*
+    operator[] (size_t);
+
+    const char*
+    operator[] (size_t) const;
+
+  public:
+    bool
+    empty () const;
+
+    size_t
+    size () const;
+
+    size_t
+    capacity () const;
+
+    size_t
+    max_size () const;
+
+  public:
+    void
+    clear ();
+
+    void
+    pop_back ();
+
+    iterator
+    erase (iterator);
+
+    void
+    push_back (char*);
+
+    void
+    push_back_copy (const char*);
+
+    iterator
+    insert (iterator, char*);
+
+    void
+    reserve (size_t);
+
+    // Detach a string from the sequence at a given position.
+    // The string pointer at this position in the sequence is
+    // set to 0.
+    //
+    char*
+    detach (iterator);
+  };
+
+  bool
+  operator== (const string_sequence&, const string_sequence&);
+
+  bool
+  operator!= (const string_sequence&, const string_sequence&);
+}
+  
+ +

The push_back() and insert() functions + assume ownership of the passed string which should be allocated + with operator new char[] and will be deallocated + with operator delete[] by the string_sequence + object. These two functions free the passed object if the reallocation + of the underlying sequence buffer fails. The push_back_copy() + function makes a copy of the passed string. + If you detach the underlying element string, then it should + eventually be deallocated with operator delete[].

+ +

When both STL and C++ exceptions are disabled, the signatures + of the push_back(), push_back_copy(), + insert(), and reserve() functions change + as follows:

+ +
+namespace xml_schema
+{
+  class string_sequence
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_no_memory
+    };
+
+    ...
+
+  public:
+    error
+    push_back (char*);
+
+    error
+    push_back_copy (const char*);
+
+    error
+    insert (iterator, char*);
+
+    error
+    insert (iterator, char*, iterator& result);
+
+    error
+    reserve (size_t);
+  };
+}
+  
+ + +

7.5 base64Binary and hexBinary Serializers

+ +

The argument type of the base64_binary_simpl and + hex_binary_simpl serializer implementations is + const xml_schema::buffer*. You can optionally + instruct these serializers to release the buffer + object with operator delete by passing true + to their constructors. With C++ exceptions enabled (Section + 6.3, "C++ Exceptions"), the buffer type has the + following interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    class bounds {}; // Out of bounds exception.
+
+  public:
+    buffer ();
+
+    explicit
+    buffer (size_t size);
+    buffer (size_t size, size_t capacity);
+    buffer (const void* data, size_t size);
+    buffer (const void* data, size_t size, size_t capacity);
+
+    enum ownership_value { assume_ownership };
+
+    // This constructor assumes ownership of the memory passed.
+    //
+    buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    void
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    bool
+    capacity (size_t);
+
+  public:
+    size_t
+    size () const;
+
+    bool
+    size (size_t);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

The last constructor and the attach() member function + make the buffer instance assume the ownership of the + memory block pointed to by the data argument and + eventually release it by calling operator delete(). + The detach() member function detaches and returns the + underlying memory block which should eventually be released by + calling operator delete(). +

+ +

The capacity() and size() modifier functions + return true if the underlying buffer has moved. The + bounds exception is thrown if the constructor or + attach() member function arguments violate the + (size <= capacity) constraint.

+ +

If C++ exceptions are disabled, the buffer type has + the following interface:

+ +
+namespace xml_schema
+{
+  class buffer
+  {
+  public:
+    enum error
+    {
+      error_none,
+      error_bounds,
+      error_no_memory
+    };
+
+    buffer ();
+
+  private:
+    buffer (const buffer&);
+
+    buffer&
+    operator= (const buffer&);
+
+  public:
+    error
+    attach (void* data, size_t size, size_t capacity);
+
+    void*
+    detach ();
+
+    void
+    swap (buffer&);
+
+  public:
+    size_t
+    capacity () const;
+
+    error
+    capacity (size_t);
+
+    error
+    capacity (size_t, bool& moved);
+
+  public:
+    size_t
+    size () const;
+
+    error
+    size (size_t);
+
+    error
+    size (size_t, bool& moved);
+
+  public:
+    const char*
+    data () const;
+
+    char*
+    data ();
+
+    const char*
+    begin () const;
+
+    char*
+    begin ();
+
+    const char*
+    end () const;
+
+    char*
+    end ();
+  };
+
+  bool
+  operator== (const buffer&, const buffer&);
+
+  bool
+  operator!= (const buffer&, const buffer&);
+}
+  
+ +

7.6 Time Zone Representation

+ +

The date, dateTime, gDay, + gMonth, gMonthDay, gYear, + gYearMonth, and time XML Schema built-in + types all include an optional time zone component. The following + xml_schema::time_zone base class is used to represent + this information:

+ +
+namespace xml_schema
+{
+  class time_zone
+  {
+  public:
+    time_zone ();
+    time_zone (short hours, short minutes);
+
+    bool
+    zone_present () const;
+
+    void
+    zone_reset ();
+
+    short
+    zone_hours () const;
+
+    void
+    zone_hours (short);
+
+    short
+    zone_minutes () const;
+
+    void
+    zone_minutes (short);
+  };
+
+  bool
+  operator== (const time_zone&, const time_zone&);
+
+  bool
+  operator!= (const time_zone&, const time_zone&);
+}
+  
+ +

The zone_present() accessor function returns true + if the time zone is specified. The zone_reset() modifier + function resets the time zone object to the not specified + state. If the time zone offset is negative then both hours and + minutes components are represented as negative integers.

+ +

7.7 date Serializer

+ +

The argument type of the date_simpl serializer implementation + is const xml_schema::date&. The date class + represents a year, a day, and a month with an optional time zone. Its + interface is presented below. For more information on the base + xml_schema::time_zone class refer to Section + 7.6, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class date: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date ();
+
+    date (int year, unsigned short month, unsigned short day);
+
+    date (int year, unsigned short month, unsigned short day,
+          short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const date&, const date&);
+
+  bool
+  operator!= (const date&, const date&);
+}
+  
+ +

7.8 dateTime Serializer

+ +

The argument type of the date_time_simpl serializer + implementation is const xml_schema::date_time&. + The date_time class represents a year, a month, a day, + hours, minutes, and seconds with an optional time zone. Its interface + is presented below. For more information on the base + xml_schema::time_zone class refer to Section + 7.6, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class date_time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    date_time ();
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds);
+
+    date_time (int year, unsigned short month, unsigned short day,
+               unsigned short hours, unsigned short minutes,
+               double seconds, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const date_time&, const date_time&);
+
+  bool
+  operator!= (const date_time&, const date_time&);
+}
+  
+ +

7.9 duration Serializer

+ +

The argument type of the duration_simpl serializer + implementation is const xml_schema::duration&. + The duration class represents a potentially + negative duration in the form of years, months, days, hours, minutes, + and seconds. Its interface is presented below.

+ +
+namespace xml_schema
+{
+  class duration
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    duration ();
+
+    duration (bool negative,
+              unsigned int years, unsigned int months, unsigned int days,
+              unsigned int hours, unsigned int minutes, double seconds);
+
+    bool
+    negative () const;
+
+    void
+    negative (bool);
+
+    unsigned int
+    years () const;
+
+    void
+    years (unsigned int);
+
+    unsigned int
+    months () const;
+
+    void
+    months (unsigned int);
+
+    unsigned int
+    days () const;
+
+    void
+    days (unsigned int);
+
+    unsigned int
+    hours () const;
+
+    void
+    hours (unsigned int);
+
+    unsigned int
+    minutes () const;
+
+    void
+    minutes (unsigned int);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const duration&, const duration&);
+
+  bool
+  operator!= (const duration&, const duration&);
+}
+  
+ + +

7.10 gDay Serializer

+ +

The argument type of the gday_simpl serializer + implementation is const xml_schema::gday& The + gday class represents a day of the month with + an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 7.6, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gday: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gday ();
+
+    explicit
+    gday (unsigned short day);
+
+    gday (unsigned short day, short zone_hours, short zone_minutes);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gday&, const gday&);
+
+  bool
+  operator!= (const gday&, const gday&);
+}
+  
+ +

7.11 gMonth Serializer

+ +

The argument type of the gmonth_simpl serializer + implementation is const xml_schema::gmonth&. The + gmonth class represents a month of the year with + an optional time zone. Its interface is presented below. For + more information on the base xml_schema::time_zone + class refer to Section 7.6, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth ();
+
+    explicit
+    gmonth (unsigned short month);
+
+    gmonth (unsigned short month,
+            short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth&, const gmonth&);
+
+  bool
+  operator!= (const gmonth&, const gmonth&);
+}
+  
+ +

7.12 gMonthDay Serializer

+ +

The argument type of the gmonth_day_simpl serializer + implementation is const xml_schema::gmonth_day&. + The gmonth_day class represents a day and a month of + the year with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 7.6, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gmonth_day: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gmonth_day ();
+
+    gmonth_day (unsigned short month, unsigned short day);
+
+    gmonth_day (unsigned short month, unsigned short day,
+                short zone_hours, short zone_minutes);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+
+    unsigned short
+    day () const;
+
+    void
+    day (unsigned short);
+  };
+
+  bool
+  operator== (const gmonth_day&, const gmonth_day&);
+
+  bool
+  operator!= (const gmonth_day&, const gmonth_day&);
+}
+  
+ +

7.13 gYear Serializer

+ +

The argument type of the gyear_simpl serializer + implementation is const xml_schema::gyear&. The + gyear class represents a year with an optional + time zone. Its interface is presented below. For more information + on the base xml_schema::time_zone class refer to + Section 7.6, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class gyear: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear ();
+
+    explicit
+    gyear (int year);
+
+    gyear (int year, short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+  };
+
+  bool
+  operator== (const gyear&, const gyear&);
+
+  bool
+  operator!= (const gyear&, const gyear&);
+}
+  
+ +

7.14 gYearMonth Serializer

+ +

The argument type of the gyear_month_simpl serializer + implementation is const xml_schema::gyear_month&. + The gyear_month class represents a year and a month + with an optional time zone. Its interface is presented below. + For more information on the base xml_schema::time_zone + class refer to Section 7.6, "Time Zone + Representation".

+ +
+namespace xml_schema
+{
+  class gyear_month: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    gyear_month ();
+
+    gyear_month (int year, unsigned short month);
+
+    gyear_month (int year, unsigned short month,
+                 short zone_hours, short zone_minutes);
+
+    int
+    year () const;
+
+    void
+    year (int);
+
+    unsigned short
+    month () const;
+
+    void
+    month (unsigned short);
+  };
+
+  bool
+  operator== (const gyear_month&, const gyear_month&);
+
+  bool
+  operator!= (const gyear_month&, const gyear_month&);
+}
+  
+ + +

7.15 time Serializer

+ +

The argument type of the time_simpl serializer implementation + is const xml_schema::time&. The time class + represents hours, minutes, and seconds with an optional time zone. Its + interface is presented below. For more information on the base + xml_schema::time_zone class refer to Section + 7.6, "Time Zone Representation".

+ +
+namespace xml_schema
+{
+  class time: public time_zone
+  {
+  public:
+    // The default constructor creates an uninitialized object.
+    // Use modifiers to initialize it.
+    //
+    time ();
+
+    time (unsigned short hours, unsigned short minutes, double seconds);
+
+    time (unsigned short hours, unsigned short minutes, double seconds,
+          short zone_hours, short zone_minutes);
+
+    unsigned short
+    hours () const;
+
+    void
+    hours (unsigned short);
+
+    unsigned short
+    minutes () const;
+
+    void
+    minutes (unsigned short);
+
+    double
+    seconds () const;
+
+    void
+    seconds (double);
+  };
+
+  bool
+  operator== (const time&, const time&);
+
+  bool
+  operator!= (const time&, const time&);
+}
+  
+ + + + + +

8 Document Serializer and Error Handling

+ +

In this chapter we will discuss the xml_schema::document_simpl + type, the error handling mechanisms provided by the mapping, as well as + how to reuse a serializer after an error has occurred.

+ +

There are four categories of errors that can result from running + a serializer to produce an XML instance: system, xml, schema, and + application. The system category contains memory allocation and + input/output operation errors. The xml category is for XML serialization + and well-formedness checking errors. Similarly, the schema category is + for XML Schema validation errors. Finally, the application category + is for application logic errors that you may want to propagate + from serializer implementations to the caller of the serializer. +

+ +

The C++/Serializer mapping supports two methods of reporting errors: + using C++ exceptions and with error codes. The method used depends + on whether or not you have configured the XSD/e runtime and + the generated code with C++ exceptions enabled, as described + in Section 6.3, "C++ Exceptions".

+ +

8.1 Document Serializer

+ +

The xml_schema::document_simpl serializer is a root + serializer for the vocabulary. As mentioned in Section + 3.4, "Connecting the Serializer Together", its interface varies + depending on the mapping configuration (Chapter 6, "Mapping + Configuration"). When STL, C++ exceptions, and the iostream library + are enabled, the xml_schema::document_simpl class has the + following interface:

+ +
+namespace xml_schema
+{
+  class serializer_base;
+
+  class writer
+  {
+  public:
+    // The first write function is called to write a '\0'-terminated
+    // string. Its default implementation calls the second versions:
+    // write (s, strlen (s)). These functions use exceptions to
+    // indicate a write failure.
+    //
+    virtual void
+    write (const char* s);
+
+    virtual void
+    write (const char* s, size_t n) = 0;
+
+    virtual void
+    flush () = 0;
+  };
+
+  class document_simpl
+  {
+  public:
+    document_simpl (serializer_base&,
+                    const char* root_element_name);
+
+    document_simpl (serializer_base&,
+                    const char* root_element_namespace,
+                    const char* root_element_name);
+
+    document_simpl (serializer_base&,
+                    const std::string& root_element_name);
+
+    document_simpl (serializer_base&,
+                    const std::string& root_element_namespace,
+                    const std::string& root_element_name);
+
+  public:
+    void
+    add_prefix (const char* prefix, const char* namespace_);
+
+    void
+    add_default_prefix (const char* namespace_);
+
+    void
+    add_schema (const char* namespace_, const char* location);
+
+    void
+    add_no_namespace_schema (const char* location);
+
+    void
+    add_prefix (const std::string& prefix,
+                const std::string& namespace_);
+
+    void
+    add_default_prefix (const std::string& namespace_);
+
+    void
+    add_schema (const std::string& namespace_,
+                const std::string& location);
+
+    void
+    add_no_namespace_schema (const std::string& location);
+
+  public:
+    // Serialize to std::ostream. The std::ios_base::failure
+    // exception is used to report io errors (badbit and failbit)
+    // if C++ exceptions are enabled. Otherwise error codes are
+    // used.
+    //
+    void
+    serialize (std::ostream&);
+
+  public:
+    // Serialize by calling writer::write() and writer::flush() to
+    // output XML.
+    //
+    void
+    serialize (writer&);
+
+    // Serialize by calling the write and flush functions. If the
+    // unbounded write function is not provided, the bounded version
+    // is called: write_bound_func (s, strlen (s)). user_data is
+    // passed as a first argument to these functions. These functions
+    // use exceptions to indicate a write failure.
+    //
+    typedef void (*write_func) (void*, const char*);
+    typedef void (*write_bound_func) (void*, const char*, size_t);
+    typedef void (*flush_func) (void*);
+
+    void
+    serialize (write_bound_func, flush_func, void* user_data);
+
+    void
+    serialize (write_func, write_bound_func, flush_func, void* user_data);
+
+  public:
+    // Low-level, genx-specific serialization. With this method
+    // it is your responsibility to call genxStartDoc*() and
+    // genxEndDocument().
+    //
+    void
+    serialize (genxWriter);
+  };
+}
+  
+ +

When the use of STL is disabled, the constructors, as well as + the add_prefix() and add_schema() + functions that use std::string in their signatures + are not available. When the use of iostream is disabled, the + serialize() functions that serializes to + std::ostream is not available.

+ +

When C++ exceptions are disabled, the write() and + flush() virtual functions in the writer + interface as well as write_func, + write_bound_func, and flush_func + function pointers use bool return type + for error reporting. These functions should return true + if the operation was successful and false otherwise. + The relevant parts in the writer and + document_simpl interfaces change as follows:

+ +
+namespace xml_schema
+{
+  class serializer_base;
+
+  class writer
+  {
+  public:
+    // The first write function is called to write a '\0'-terminated
+    // string. Its default implementation calls the second versions:
+    // write (s, strlen (s)). These functions return true if the
+    // operation was successful and false otherwise.
+    //
+    // indicate a write failure.
+    //
+    virtual bool
+    write (const char* s);
+
+    virtual bool
+    write (const char* s, size_t n) = 0;
+
+    virtual bool
+    flush () = 0;
+  };
+
+  class document_simpl
+  {
+    ...
+
+    // Serialize by calling the write and flush functions. If the
+    // unbounded write function is not provided, the bounded version
+    // is called: write_bound_func (s, strlen (s)). user_data is
+    // passed as a first argument to these functions. These functions
+    // return true if the operation was successful and false otherwise.
+    //
+    typedef bool (*write_func) (void*, const char*);
+    typedef bool (*write_bound_func) (void*, const char*, size_t);
+    typedef bool (*flush_func) (void*);
+
+    ...
+
+  public:
+    const serializer_error&
+    _error () const;
+  };
+}
+  
+ +

For more information on error handling with C++ exceptions and + error codes see Section 8.2, "Exceptions" + and Section 8.3, "Error Codes" below.

+ +

When support for XML Schema polymorphism is enabled, the + overloaded document_simpl constructors have + additional arguments which control polymorphic serialization. + For more information refer to Section 6.7, + "Support for Polymorphism". +

+ +

The first argument to all overloaded constructors is the + serializer for the type of the root element. The + serializer_base class is the base type for all + serializer skeletons. The second and third arguments to the + document_simpl's constructors are the root element's + name and namespace.

+ +

The add_prefix() and add_default_prefix() + functions allow you to establish custom prefixes for XML + namespaces. If none is provided, and namespaces are used + by your vocabulary, the serializer will automatically + assign namespace prefixes in an implementation-specific + manner. For example:

+ +
+xml_schema::document_simpl doc_s (
+  root_s,
+  "http://www.example.com/example",
+  "root");
+
+doc_s.add_prefix ("ex", "http://www.example.com/example");
+  
+ +

The resulting XML will have the following namespace declaration:

+ +
+<ex:root xmlns:ex="http://www.example.com/example" ...>
+  ...
+</ex:root>
+  
+ +

Similarly, the add_schema() and + add_no_namespace_schema() functions allow you to embed + schema location information for a particular namespace into resulting + XML. The schema location information is placed into the + xsi:schemaLocation and + xsi:noNamespaceSchemaLocation attributes. For example:

+ +
+xml_schema::document_simpl doc_s (
+  root_s,
+  "http://www.example.com/example",
+  "root");
+
+doc_s.add_prefix ("ex", "http://www.example.com/example");
+doc_s.add_schema ("http://www.example.com/example", "example.xsd");
+  
+ +

The resulting XML will have the following namespace declaration:

+ +
+<ex:root
+  xmlns:ex="http://www.example.com/example"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.example.com/example example.xsd" ...>
+  ...
+</ex:root>
+  
+ +

8.2 Exceptions

+ +

When C++ exceptions are used for error reporting, the system + errors are mapped to the standard exceptions. The out of memory + condition is indicated by throwing an instance + of std::bad_alloc. The stream operation errors + are reported by throwing an instance of + std::ios_base::failure.

+ +

The xml and schema errors are reported by throwing the + xml_schema::serializer_xml and + xml_schema::serializer_schema + exceptions, respectively. These two exceptions derive from + xml_schema::serializer_exception which, in turn, derives + from std::exception. As a result, you can handle + any error from these two categories by either catching + std::exception, xml_schema::serializer_exception, + or individual exceptions. The further down the hierarchy you go + the more detailed error information is available to you. The + following listing shows the definitions of these exceptions:

+ +
+namespace xml_schema
+{
+  class serializer_exception: public std::exception
+  {
+  public:
+    virtual const char*
+    text () const = 0;
+
+    ...
+  };
+
+  std::ostream&
+  operator<< (std::ostream&, const serializer_exception&);
+
+
+  typedef <implementation-details> serializer_xml_error;
+
+  class serializer_xml: public serializer_exception
+  {
+  public:
+    serializer_xml_error
+    code () const;
+
+    virtual const char*
+    text () const;
+
+    virtual const char*
+    what () const throw ();
+
+    ...
+  };
+
+
+  typedef <implementation-details> serializer_schema_error;
+
+  class serializer_schema: public serializer_exception
+  {
+  public:
+    serializer_schema_error
+    code () const;
+
+    virtual const char*
+    text () const;
+
+    virtual const char*
+    what () const throw ();
+
+    ...
+  };
+}
+  
+ +

The serializer_xml_error and + serializer_schema_error are implementation-specific error + code types. The operator<< defined for the + serializer_exception class simply prints the error + description as returned by the text() function. The + following example shows how we can catch these exceptions:

+ +
+int
+main ()
+{
+  try
+  {
+    // Serialize.
+  }
+  catch (const xml_schema::serializer_exception& e)
+  {
+    cout << "error: " << e.text () << endl;
+    return 1;
+  }
+}
+  
+ +

Finally, for reporting application errors from serializer callbacks, + you can throw any exceptions of your choice. They are propagated + to the caller of the serializer without any alterations.

+ +

8.3 Error Codes

+ +

When C++ exceptions are not available, error codes are used to + report error conditions. Each serializer skeleton and the root + document_simpl serializer have the following member + function for querying the error status:

+ +
+xml_schema::serializer_error
+_error () const;
+  
+ +

To handle all possible error conditions, you will need to obtain + the error status after calls to: the document_simpl's + constructor (it performs memory allocations which may fail), + calls to add_prefix() and add_schema() + functions if any, the call to the root serializer pre() + callback, the call to the serialize() function, and, + finally, the call to the root serializer post() callback. + The definition of xml_schema::serializer_error class + is presented below:

+ +
+namespace xml_schema
+{
+  class sys_error
+  {
+  public:
+    enum value
+    {
+      none,
+      no_memory,
+      open_failed,
+      read_failed,
+      write_failed
+    };
+
+    sys_error (value);
+
+    operator value () const;
+
+    static const char*
+    text (value);
+
+    ...
+  };
+
+  typedef <implementation-details> serializer_xml_error;
+  typedef <implementation-details> serializer_schema_error;
+
+  class serializer_error
+  {
+  public:
+    enum error_type
+    {
+      none,
+      sys,
+      xml,
+      schema,
+      app
+    };
+
+    error_type
+    type () const;
+
+    // Returns true if there is an error so that you can write
+    // if (s.error ()) or if (error e = s.error ()).
+    //
+    typedef void (error::*bool_convertible) ();
+    operator bool_convertible () const;
+
+    // system
+    //
+    sys_error
+    sys_code () const;
+
+    const char*
+    sys_text () const;
+
+    // xml
+    //
+    serializer_xml_error
+    xml_code () const;
+
+    const char*
+    xml_text () const;
+
+    // schema
+    //
+    serializer_schema_error
+    schema_code () const;
+
+    const char*
+    schema_text () const;
+
+    // app
+    //
+    int
+    app_code () const;
+
+    ...
+  };
+}
+  
+ +

The serializer_xml_error and + serializer_schema_error are implementation-specific + error code types. The serializer_error class incorporates + four categories of errors which you can query by calling the + type() function. The following example shows how to + handle error conditions with error codes. It is based on the + person record example presented in Chapter 3, "Serializer + Skeletons".

+ +
+int
+main ()
+{
+  // Construct the serializer.
+  //
+  xml_schema::short_simpl 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, short_s);
+  people_s.serializers (person_s);
+
+  // Serialize.
+  //
+  using xml_schema::serializer_error;
+  serializer_error e;
+
+  do
+  {
+    xml_schema::document_simpl doc_s (people_s, "people");
+    if (e = doc_s._error ())
+      break;
+
+    people_s.pre ();
+    if (e = people_s._error ())
+      break;
+
+    doc_s.serialize (cout);
+    if (e = doc_s._error ())
+      break;
+
+    people_s.post ();
+    e = people_s._error ();
+
+  } while (false);
+
+  // Handle errors.
+  //
+  if (e)
+  {
+    switch (e.type ())
+    {
+    case serializer_error::sys:
+      {
+        cerr << "system error: " << e.sys_text () << endl;
+        break;
+      }
+    case serializer_error::xml:
+      {
+        cerr << "xml error: " << e.xml_text () << endl;
+        break;
+      }
+    case serializer_error::schema:
+      {
+        cerr << "schema error: " << e.schema_text () << endl;
+        break;
+      }
+    case serializer_error::app:
+      {
+        cerr << "application error: " << e.app_code () << endl;
+        break;
+      }
+    }
+    return 1;
+  }
+}
+  
+ +

The error type for application errors is int with + the value 0 indicated the absence of error. You can + set the application error by calling the _app_error() + function inside a serializer callback. For example, if it was invalid + to have a person younger than 18 in our people catalog, then we + could have implemented this check as follows:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual short
+  age ()
+  {
+    short a = ...;
+
+    if (a < 18)
+      _app_error (1);
+
+    return a;
+  }
+};
+  
+ +

You can also set a system error by calling the _sys_error() + function inside a serializer callback. This function has one argument of + type xml_schema::sys_error which was presented above. + For example:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual const char*
+  first_name ()
+  {
+    char* r = new char[5];
+
+    if (r == 0)
+    {
+      _sys_error (xml_schema::sys_error::no_memory);
+      return 0;
+    }
+
+    strcpy (r, "John");
+    return r;
+  }
+};
+  
+ +

8.4 Reusing Serializers after an Error

+ +

After a successful execution a serializer returns into the initial + state and can be used to serialize another document without any + extra actions. On the other hand, if an error occurred during + serialization and you would like to reuse the serializer to serialize another + document, you need to explicitly reset it into the initial + state as shown in the following code fragment:

+ +
+int
+main ()
+{
+  ...
+
+  xml_schema::document_simpl doc_s (people_s, "people");
+
+  for (size_t i = 0; i < 4; ++i)
+  {
+    try
+    {
+      people_s.pre ();
+      doc_s.serialize (cout);
+      people_s.post ();
+    }
+    catch (const xml_schema::serializer_exception&)
+    {
+      doc_s.reset ();
+    }
+  }
+}
+  
+ +

If you do not need to reuse serializers after an error for example + because your application terminates or you create a new serializer + instance in such situations, then you can avoid generating + serializer reset code by specifying the --suppress-reset + XSD/e compiler option.

+ +

Your individual serializer implementations may also require extra + actions in order to bring them into a usable state after an + error. To accomplish this you can override the _reset() + virtual function as shown below. Notice that when you override the + _reset() function in your implementation, you should + always call the base skeleton version to allow it to reset + its state:

+ +
+class person_simpl: public person_sskel
+{
+public:
+  virtual void
+  pre (person* p)
+  {
+    p_ = p;
+  }
+
+  virtual void
+  post ()
+  {
+    delete p_;
+    p_ = 0;
+  }
+
+  virtual void
+  _reset ()
+  {
+    person_sskel::_reset ();
+    delete p_;
+    p_ = 0;
+  }
+
+  ...
+
+private:
+  person* p_;
+};
+  
+ +

Note also that the _reset() mechanism is used only when + an error has occurred. To make sure that your serializer implementations + arrive at the initial state during successful execution, use the + initialization (pre() and _pre()) and + finalization (post_*() and _post()) + callbacks.

+ + + + + +

Appendix A — Supported XML Schema Constructs

+ +

The Embedded C++/Serializer mapping supports validation of the following + W3C XML Schema constructs in the generated code.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstructNotes
Structure
element
attribute
any
anyAttribute
all
sequence
choice
complex type, empty content
complex type, mixed content
complex type, simple content extension
complex type, simple content restrictionSimple type facets are not validated.
complex type, complex content extension
complex type, complex content restriction
list
Datatypes
byte
unsignedByte
short
unsignedShort
int
unsignedInt
long
unsignedLong
integer
nonPositiveInteger
nonNegativeInteger
positiveInteger
negativeInteger
boolean
float
double
decimal
string
normalizedString
token
Name
NMTOKEN
NCName
language
anyURI
IDIdentity constraint is not enforced.
IDREFIdentity constraint is not enforced.
NMTOKENS
IDREFSIdentity constraint is not enforced.
QName
base64Binary
hexBinary
date
dateTime
duration
gDay
gMonth
gMonthDay
gYear
gYearMonth
time
+ +
+
+ + + + diff --git a/documentation/cxx/serializer/guide/makefile b/documentation/cxx/serializer/guide/makefile new file mode 100644 index 0000000..8524f4f --- /dev/null +++ b/documentation/cxx/serializer/guide/makefile @@ -0,0 +1,12 @@ +.PHONY: all +all: cxx-serializer-e-guide.ps cxx-serializer-e-guide.pdf + +cxx-serializer-e-guide.pdf: cxx-serializer-e-guide.ps + ps2pdf14 $< + +cxx-serializer-e-guide.ps: index.xhtml guide.html2ps + html2ps -f guide.html2ps -o $@ $< + +.PHONY: clean +clean: + rm -f cxx-serializer-e-guide.ps cxx-serializer-e-guide.pdf diff --git a/documentation/default.css b/documentation/default.css new file mode 100644 index 0000000..bb3805b --- /dev/null +++ b/documentation/default.css @@ -0,0 +1,319 @@ +html { + margin : 0; + padding : 0; + background : white; +} + +body { + font-family : "Lucida Grande", Verdana, "Bitstream Vera Sans", sans-serif; + font-weight : normal; + font-size : 13px; + line-height : 19px; + + color : black; + + margin : 0 2em 0 2em; + padding : 0; +} + + +body { + min-width: 40em; +} + +#container { + max-width : 46em; + margin : 0 auto; + padding : 0 1em 0 1em; +} + + + +/* + * Footer + * + */ +#footer { + color : #3a84a7; + + padding : 1em 0 0.5em 0; + + font-size : 10px; + line-height : 15px; + + text-align: center; +} + +#footer a:link, #footer a:visited { + + color:#1d6699; + text-decoration: underline; +} + +#footer a { + margin-left: 0.7em; + margin-right: 0.7em; +} + +#footer p { + padding: 0; + margin: 0.3em 0 0 0; +} + +/* Distribution terms. */ +#footer #terms { + text-align: justify; + + font-size : 110%; + font-family : monospace; + + padding : 1em 0 0.5em 0; +} + + +/* + * Content + * + */ + +#content { + padding : 0em 0.1em 0 1.3em; + margin : 1.4em 0 0 0; +} + +#content p, +#content ol, +#content ul, +#content dl { + text-align: justify; +} + +#content h1 { + margin-left: -0.89em; +} + +a:link { + color:#0536d2; +} + + +/* + * Headings + * + */ + +h1, h2, h3, h4, h5, h6 { + font-weight : 500; +} + +h1 { font-size : 155%; } +h2 { font-size : 130%; } +h3 { font-size : 125%; } +h4 { font-size : 110%; } +h5 { font-size : 106%; } +h6 { font-size : 100%; } + +h1 { margin : 1.8em 0 0.8em 0;} +h2 { margin-top : 1.4em;} +h3 { margin-top : 1em;} + +p.indent { + margin-left : 1.5em; +} + + +/* + * Fix for IE 5.5 table font problem + * + */ + +table { + font-size : 13px; +} + + +/* + * table of content + * + */ + +ul.toc li { + padding : .4em 0em 0em 0em; +} + + +/* Toc links don't need to show when they are visited. */ +.toc a:visited { + color:#0536d2; +} + + +/* + * lists + * + */ + + +/* list of links */ +ul.menu { + list-style-type : none; +} + +ul.menu li { + padding-top : 0.3em; + padding-bottom : 0.3em; +} + + + +/* @@ I should probably use child selector here */ +/* list with multiline list-elements */ +ul.multiline li, ol.multiline li, dl.multiline dd { + padding-top : 0.16em; + padding-bottom : 0.16em; + + font-size : 11px; + line-height : 15px; +} + + + +/* C++ code snippet */ +pre.cxx { + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + + +/* make code snippet */ +pre.make { + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + + +/* terminal output */ +pre.term { + margin-top : 0em; + margin-bottom : 2em; + + margin-left : 1em; +} + + +/* Images */ +div.center { + text-align: center; +} + +/* Document info. */ +#docinfo { + margin-top: 4em; + border-top: 1px dashed #000000; + font-size: 70%; +} + + +/* Footnote */ + +#footnote { + margin-top : 2.5em; +} + +#footnote hr, hr.footnote { + margin-left: 0; + margin-bottom: 0.6em; + width: 8em; + border-top: 1px solid #000000; + border-right: none; + border-bottom: none; + border-left: none; + +} + +#footnote ol { + margin-left: 0; + padding-left: 1.45em; +} + +#footnote li { + text-align : left; + font-size : 11px; + line-height : 15px; + + padding : .4em 0 .4em 0; +} + + +/* Normal table with borders, etc. */ + +table.std { + margin: 2em 0 2em 0; + + border-collapse : collapse; + border : 1px solid; + border-color : #000000; + + font-size : 11px; + line-height : 14px; +} + +table.std th, table.std td { + border : 1px solid; + padding : 0.6em 0.8em 0.6em 0.8em; +} + +table.std th { + background : #cde8f6; +} + +table.std td { + text-align: left; +} + + +/* + * "item | description" table. + * + */ + +table.description { + border-style : none; + border-collapse : separate; + border-spacing : 0; + + font-size : 13px; + + margin : 0.6em 0 0.6em 0; + padding : 0 0 0 0; +} + +table.description tr { + padding : 0 0 0 0; + margin : 0 0 0 0; +} + +table.description * td, table.description * th { + border-style : none; + margin : 0 0 0 0; + vertical-align : top; +} + +table.description * th { + font-weight : normal; + padding : 0.4em 1em 0.4em 0; + text-align : left; + white-space : nowrap; + background : none; +} + +table.description * td { + padding : 0.4em 0 0.4em 1em; + text-align : justify; +} diff --git a/documentation/makefile b/documentation/makefile new file mode 100644 index 0000000..420cbcc --- /dev/null +++ b/documentation/makefile @@ -0,0 +1,18 @@ +# file : documentation/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 + +install := $(out_base)/.install + +.PHONY: $(install) + +$(install): + $(call install-dir,$(src_base)/cxx,$(install_doc_dir)/xsde/cxx) + $(call install-data,$(src_base)/default.css,$(install_doc_dir)/xsde/default.css) + $(call install-data,$(src_base)/xsde.xhtml,$(install_doc_dir)/xsde/xsde.xhtml) + $(call install-data,$(src_base)/xsde.1,$(install_man_dir)/man1/xsde.1) + +$(call include,$(bld_root)/install.make) diff --git a/documentation/xsde.1 b/documentation/xsde.1 new file mode 100644 index 0000000..1f72eef --- /dev/null +++ b/documentation/xsde.1 @@ -0,0 +1,1940 @@ +.\" Process this file with +.\" groff -man -Tascii xsde.1 +.\" +.TH XSD/e 1 "February 2009" "XSD/e 3.0.0" +.SH NAME +xsde \- W3C XML Schema to C++ Compiler for Embedded Systems +.\" +.\" +.\" +.\"-------------------------------------------------------------------- +.SH SYNOPSIS +.\"-------------------------------------------------------------------- +.B xsde +.I command +.B [ +.I options +.B ] +.I file +.B [ +.I file +.B ...] +.in +.B xsde help +.B [ +.I command +.B ] +.in +.B xsde version +.\" +.\" +.\" +.\"-------------------------------------------------------------------- +.SH DESCRIPTION +.\"-------------------------------------------------------------------- +.B xsde +generates vocabulary-specific, statically-typed C++ mapping from W3C XML +Schema definitions. Particular mapping to produce is selected by a +.IR command . +Each mapping has a number of mapping-specific +.I options +that should appear, if any, after the +.IR command . +Input files should be W3C XML Schema definitions. The exact set of the +generated files depends on the selected mapping and options. +.\" +.\" +.\" +.\"-------------------------------------------------------------------- +.SH COMMANDS +.\"-------------------------------------------------------------------- +.IP \fBcxx-hybrid\fR +Generate the Embedded C++/Hybrid mapping. For each input file in the +form +.B name.xsd +the following C++ files are generated: +.B name.hxx +(object model header file), +.B name.ixx +(object model inline file, generated only if the +.B --generate-inline +option is specified), +.B name.cxx +(object model source file), and +.B name-fwd.hxx +(object model forward declaration file, generated only if the +.B --generate-forward +option is specified). + +If the +.B --generate-parser +option is specified, the Embedded C++/Parser mapping is invoked and the +.BR name-pskel.hxx , +.BR name-pskel.ixx , +and +.B name-pskel.cxx +parser skeleton files are generated, as described below. Additionally, +the following parser implementation files are generated: +.B name-pimpl.hxx +(parser implementation header file) and +.B name-pimpl.cxx +(parser implementation source file). + +If the +.B --generate-serializer +option is specified, the Embedded C++/Serializer mapping is invoked and the +.BR name-sskel.hxx , +.BR name-sskel.ixx , +and +.B name-sskel.cxx +serializer skeleton files are generated, as described below. Additionally, +the following serializer implementation files are generated: +.B name-simpl.hxx +(serializer implementation header file) and +.B name-simpl.cxx +(serializer implementation source file). + +.IP \fBcxx-parser\fR +Generate the Embedded C++/Parser mapping. For each input file in the form +.B name.xsd +the following C++ files are generated: +.B name-pskel.hxx +(parser skeleton header file), +.B name-pskel.ixx +(parser skeleton inline file, generated only if the +.B --generate-inline +option is specified), and +.B name-pskel.cxx +(parser skeleton source file). If the +.B --generate-noop-impl +or +.B --generate-print-impl +option is specified, the following additional sample implementation files +are generated: +.B name-pimpl.hxx +(parser implementation header file) and +.B name-pimpl.cxx +(parser implementation source file). If the +.B --generate-test-driver +option is specified, the additional +.B name-pdriver.cxx +test driver file is generated. + +.IP \fBcxx-parser\fR +Generate the Embedded C++/Serializer mapping. For each input file in the form +.B name.xsd +the following C++ files are generated: +.B name-sskel.hxx +(serializer skeleton header file), +.B name-sskel.ixx +(serializer skeleton inline file, generated only if the +.B --generate-inline +option is specified), and +.B name-sskel.cxx +(serializer skeleton source file). If the +.B --generate-empty-impl +option is specified, the following additional sample implementation files +are generated: +.B name-simpl.hxx +(serializer implementation header file) and +.B name-simpl.cxx +(serializer implementation source file). If the +.B --generate-test-driver +option is specified, the additional +.B name-sdriver.cxx +test driver file is generated. + +.IP \fBhelp\fR +Print usage information and exit. Use +.PP +.RS +.RS 3 +.B xsde help +.I command +.RE +.PP +for command-specific help. +.RE +.IP \fBversion\fR +Print version and exit. +.\"-------------------------------------------------------------------- +.SH OPTIONS +.\"-------------------------------------------------------------------- +Command-specific +.IR options , +if any, should appear after the corresponding +.IR command . + +.\" +.\" Common options +.\" +.SS common options + +.IP "\fB\--output-dir \fIdir\fR" +Write generated files to +.I dir +instead of the current directory. + +.IP "\fB\--no-stl\fR" +Generate code that does not use the Standard Template Library (STL). + +.IP "\fB\--no-iostream\fR" +Generate code that does not use the standard input/output stream +library (iostream). + +.IP "\fB\--no-exceptions\fR" +Generate code that does not use C++ exceptions. + +.IP "\fB\--no-long-long\fR" +Generate code that does not use the +.B long long +and +.B unsigned long long +types. The 64 bit +.B long +and +.B unsignedLong +built-in XML Schema types are then mapped to +.B long +and +.B unsigned +.BR long . + +.IP "\fB\--generate-inline\fR" +Generate simple functions inline. This option triggers creation of the +inline file. + +.IP "\fB\--namespace-map \fIxns\fB=\fIcns" +Map XML Schema namespace +.I xns +to C++ namespace +.IR cns . +Repeat this option to specify mapping for more than one XML Schema namespace. +For example, the following option: + +.B --namespace-map http://example.com/foo/bar=foo::bar + +will map the +.B http://example.com/foo/bar +XML Schema namespace to the +.B foo::bar +C++ namespace. +. +.IP "\fB\--namespace-regex \fIregex\fR" +Add +.I regex +to the list of regular expressions used to translate XML Schema namespace +names to C++ namespace names. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +Any character can be used as a delimiter instead of +.BR / . +Escaping of the delimiter character in +.I pattern +or +.I replacement +is not supported. + +All regular expressions are pushed into a stack with the last specified +expression considered first. The first match that succeeds is used. Regular +expressions are applied to a string in the form + +.I filename namespace + +For example, + +.B XMLSchema.xsd http://www.w3.org/2001/XMLSchema + +The +.I filename +for the current translation unit is empty. For example, if you have file +.B hello.xsd +with namespace +.B http://example.com/hello +and you run +.B xsde +on this file, then the string in question would be: + +.B \ http://example.com/hello + +Note the leading space. + +The following three steps are performed for each regular expression until +the match is found: +.RS +.RS 3 +.TP 3 +1. +The expression is applied and if the result is empty the next expression +is considered. +.TP 3 +2. +All +.B / +are replaced with +.BR :: . +.TP 3 +3. +The result is verified to be a valid C++ scope name (e.g., +.BR foo::bar ). +If this test succeeds, the result is used as a C++ namespace name. +.RE +.PP +As an example, the following expression maps XML Schema namespaces in the +form +.B http://example.com/foo/bar +to C++ namespaces in the form +.BR foo::bar : +.PP +.B "%.* http://example.com/(.+)%$1%" + +See also the REGEX AND SHELL QUOTING section below. +.RE + +.IP "\fB\--namespace-regex-trace\fR" +Trace the process of applying regular expressions specified with +the +.B --namespace-regex +option. Use this option to find out why your regular expressions +don't do what you expected them to do. + +\" +\" Reserved names. +\" + +.IP "\fB\--reserved-name \fIname\fR[\fB=\fIrep\fR]" +Add +.I name +to the list of names that should not be used as identifiers. The name +can optionally be followed by +.B = +and the replacement name that should be used instead. All C++ keywords +are already in this list. + +.IP "\fB\--include-with-brackets\fR" +Use angle brackets (<>) instead of quotes ("") in generated +.B #include +directives. + +.IP "\fB\--include-prefix \fIprefix\fR" +Add +.I prefix +to generated +.B #include +directive paths. + +For example, if you had the following import element in your schema + +.B + +and compiled this fragment with +.B --include-prefix schemas/\fR, +then the include directive in the generated code would be: + +.B #include "schemas/base.hxx" + +.IP "\fB\--include-regex \fIregex\fR" +Add +.I regex +to the list of regular expressions used to transform +.B #include +directive paths. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +Any character can be used as a delimiter instead of +.BR / . +Escaping of the delimiter character in +.I pattern +or +.I replacement +is not supported. + +All regular expressions are pushed into a stack with the last specified +expression considered first. The first match that succeeds is used. + +As an example, the following expression transforms paths in the form +.B schemas/foo/bar +to paths in the form +.BR generated/foo/bar : + +.B "%schemas/(.+)%generated/$1%" + +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--include-regex-trace\fR" +Trace the process of applying regular expressions specified with +the +.B --include-regex +option. Use this option to find out why your regular expressions +don't do what you expected them to do. + +.IP "\fB\--guard-prefix \fIprefix\fR" +Add +.I prefix +to generated header inclusion guards. The prefix is transformed to upper +case and all characters that are illegal in a preprocessor macro name are +replaced with underscores. If this option is not specified then the +directory part of the input schema file is used as a prefix. + +.IP "\fB\--hxx-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B .hxx +to construct the name of the header file. Note that this suffix is also +used to construct names for included/imported schemas. +.IP "\fB\--ixx-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B .ixx +to construct the name of the inline file. +.IP "\fB\--cxx-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B .cxx +to construct the name of the source file. +.IP "\fB\--fwd-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B -fwd.hxx +to construct the name of the forward declaration file (C++/Hybrid +mapping only). + +.IP "\fB\--hxx-regex \fIregex\fR" +Use the provided expression to construct the name of the header file. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +This expression is also used to construct names for included/imported schemas. + +For the C++/Hybrid mapping, the +.I regex +argument can be optionally prefixed with a file key in the form +.IB key = regex\fR. +The valid values for +.I key +are +.B pskel +(parser skeleton files), +.B pimpl +(parser implementation files), +.B sskel +(serializer skeleton files), +.B simpl +(serializer implementation files), and +.B * +(all files). If +.I key +is empty or not present then the expression is used for the object model +files only. + +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--ixx-regex \fIregex\fR" +Use the provided expression to construct the name of the inline file. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +For the C++/Hybrid mapping, the +.I regex +argument can be optionally prefixed with a file key. See the +.B --hxx-regex +option for details. +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--cxx-regex \fIregex\fR" +Use the provided expression to construct the name of the source file. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +For the C++/Hybrid mapping, the +.I regex +argument can be optionally prefixed with a file key. See the +.B --hxx-regex +option for details. +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--fwd-regex \fIregex\fR" +Use the provided expression to construct the name of the forward +declaration file (C++/Hybrid mapping only). +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--hxx-prologue \fItext\fR" +Insert +.I text +at the beginning of the header file. + +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key in the form +.IB key = text\fR. +The valid values for +.I key +are +.B pskel +(parser skeleton files), +.B pimpl +(parser implementation files), +.B sskel +(serializer skeleton files), +.B simpl +(serializer implementation files), and +.B * +(all files). If +.I key +is empty or not present then the text is used for the object model files only. + +.IP "\fB\--ixx-prologue \fItext\fR" +Insert +.I text +at the beginning of the inline file. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--cxx-prologue \fItext\fR" +Insert +.I text +at the beginning of the source file. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--fwd-prologue \fItext\fR" +Insert +.I text +at the beginning of the forward declaration file (C++/Hybrid mapping only). + +.IP "\fB\--prologue \fItext\fR" +Insert +.I text +at the beginning of each generated file for which there is no file-specific +prologue. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--hxx-epilogue \fItext\fR" +Insert +.I text +at the end of the header file. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--ixx-epilogue \fItext\fR" +Insert +.I text +at the end of the inline file. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--cxx-epilogue \fItext\fR" +Insert +.I text +at the end of the source file. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--fwd-epilogue \fItext\fR" +Insert +.I text +at the end of the forward declaration file (C++/Hybrid mapping only). + +.IP "\fB\--epilogue \fItext\fR" +Insert +.I text +at the end of each generated file for which there is no file-specific +epilogue. +For the C++/Hybrid mapping, the +.I text +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue +option for details. + +.IP "\fB\--hxx-prologue-file \fIfile\fR" +Insert the content of the +.I file +at the beginning of the header file. + +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key in the form +.IB key = file\fR. +The valid values for +.I key +are +.B pskel +(parser skeleton files), +.B pimpl +(parser implementation files), +.B sskel +(serializer skeleton files), +.B simpl +(serializer implementation files), and +.B * +(all files). If +.I key +is empty or not present then the file is used for the object model files only. + +.IP "\fB\--ixx-prologue-file \fIfile\fR" +Insert the content of the +.I file +at the beginning of the inline file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--cxx-prologue-file \fIfile\fR" +Insert the content of the +.I file +at the beginning of the source file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--fwd-prologue-file \fIfile\fR" +Insert the content of the +.I file +at the beginning of the forward declaration file (C++/Hybrid mapping only). + +.IP "\fB\--prologue-file \fIfile\fR" +Insert the content of the +.I file +at the beginning of each generated file for which there is no file-specific +prologue file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--hxx-epilogue-file \fIfile\fR" +Insert the content of the +.I file +at the end of the header file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--ixx-epilogue-file \fIfile\fR" +Insert the content of the +.I file +at the end of the inline file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--cxx-epilogue-file \fIfile\fR" +Insert the content of the +.I file +at the end of the source file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--fwd-epilogue-file \fIfile\fR" +Insert the content of the +.I file +at the end of the forward declaration file (C++/Hybrid mapping only). + +.IP "\fB\--epilogue-file \fIfile\fR" +Insert the content of the +.I file +at the end of each generated file for which there is no file-specific +epilogue file. +For the C++/Hybrid mapping, the +.I file +argument can be optionally prefixed with a file key. See the +.B --hxx-prologue-file +option for details. + +.IP "\fB\--disable-warning \fIwarn\fR" +Disable printing warning with id +.IR warn . +If +.B all +is specified for the warning id then all warnings are disabled. + +.IP "\fB\--show-sloc\fR" +Show the number of generated physical source lines of code (SLOC). + +.IP "\fB\--sloc-limit \fInum\fR" +Check that the number of generated physical source lines of code (SLOC) +does not exceed +.I num. + +.IP "\fB\--options-file \fIfile\fR" +Read additional options from +.IR file . +Each option should appear on a separate line optionally followed by +space and an argument. Empty lines and lines starting with +.B # +are ignored. The semantics of providing options in a file is equivalent +to providing the same set of options in the same order in the command +line at the point where the +.B --options-file +option is specified except that shell escaping and quoting is not +required. Repeat this option to specify more than one options files. + +.IP "\fB\--proprietary-license\fR" +Indicate that the generated code is licensed under a proprietary license +instead of the GPL. + +.IP "\fB\--preserve-anonymous\fR" +Preserve anonymous types. By default anonymous types are +automatically named with names derived from the enclosing +elements/attributes. Because mappings implemented by this +compiler require all types to be named, this option is only +useful if you want to make sure your schemas don't have +anonymous types. + +.IP "\fB\--show-anonymous\fR" +Show elements and attributes that are of anonymous types. This option +only makes sense together with the +.B --preserve-anonymous +option. + +.IP "\fB\--anonymous-regex \fIregex\fR" +Add +.I regex +to the list of regular expressions used to derive names for anonymous +types from the enclosing attributes/elements. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +Any character can be used as a delimiter instead of +.BR / . +Escaping of the delimiter character in +.I pattern +or +.I replacement +is not supported. + +All regular expressions are pushed into a stack with the last +specified expression considered first. The first match that +succeeds is used. Regular expressions are applied to a string +in the form + +.I filename namespace xpath + +For example, + +.B hello.xsd http://example.com/hello element + +.B hello.xsd http://example.com/hello type/element + +The +.I filename +for the current translation unit is empty. For example, if you have file +.B hello.xsd +with namespace +.B http://example.com/hello +and you run +.B xsde +on this file, then the string in question would be: + +.B \ http://example.com/hello element + +Note the leading space. + +As an example, the following expression makes all the derived +names start with capital letters. This could be useful when +your naming convention requires type names to start with +capital letters: + +.B %.* .* (.+/)*(.+)%\\\\u$2% + +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--anonymous-regex-trace\fR" +Trace the process of applying regular expressions specified with +the +.B --anonymous-regex +option. Use this option to find out why your regular expressions +don't do what you expected them to do. + +.IP "\fB\--location-map \fIol\fB=\fInl" +Map the original schema location +.I ol +that is specified in the XML Schema include or import elements to new +schema location +.IR nl . +Repeat this option to map more than one schema location. For example, +the following option maps the +.B http://example.com/foo.xsd +URL to the +.B foo.xsd +local file. + +.B --location-map http://example.com/foo.xsd=foo.xsd + +.IP "\fB\--location-regex \fIregex\fR" +Add +.I regex +to the list of regular expressions used to map schema locations that are +specified in the XML Schema include or import elements. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +Any character can be used as a delimiter instead of +.BR / . +Escaping of the delimiter character in +.I pattern +or +.I replacement +is not supported. All regular expressions are pushed into a stack with the +last specified expression considered first. The first match that succeeds +is used. + +For example, the following expression maps URL locations in the form +.B http://example.com/foo/bar.xsd +to local files in the form +.BR bar.xsd : + +.B %http://.+/(.+)%$1% + +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--location-regex-trace\fR" +Trace the process of applying regular expressions specified with +the +.B --location-regex +option. Use this option to find out why your regular expressions +don't do what you expected them to do. + +.IP "\fB\--file-per-type\fR" +Generate a separate set of C++ files for each type defined in XML Schema. +Note that in this mode you only need to compile the root schema(s) and the +code will be generated for all included and imported schemas. This +compilation mode is primarily useful when some of your schemas cannot be +compiled separately or have cyclic dependencies which involve type +inheritance. + +.IP "\fB\--type-file-regex \fIregex\fR" +Add +.I regex +to the list of regular expressions used to translate type names to file +names when the +.B --type-per-file +option is specified. +.I regex +is a perl-like regular expression in the form +.BI / pattern / replacement /\fR. +Any character can be used as a delimiter instead of +.BR / . +Escaping of the delimiter character in +.I pattern +or +.I replacement +is not supported. All regular expressions are pushed into a stack with +the last specified expression considered first. The first match that +succeeds is used. Regular expressions are applied to a string +in the form + +.I namespace type-name + +For example, the following expression maps type +.B foo +that is defined in the +.B http://example.com/bar +namespace to file name +.BR bar-foo : + +.B %http://example.com/(.+) (.+)%$1-$2% + +See also the REGEX AND SHELL QUOTING section below. + +.IP "\fB\--type-file-regex-trace\fR" +Trace the process of applying regular expressions specified with +the +.B --type-file-regex +option. Use this option to find out why your regular expressions +don't do what you expected them to do. + +.IP "\fB\--file-list \fIfile\fR" +Write a list of generated C++ files to +.IR file . +This option is primarily useful in the file-per-type compilation mode +.RB ( --file-per-type ) +to create a list of generated C++ files, for example, as a makefile fragment. + +.IP "\fB\--file-list-prologue \fItext\fR" +Insert +.I text +at the beginning of the file list. As a convenience, all occurrences of the +\\n character sequence in +.I text +are replaced with new lines. This option can, for example, be used to assign +the generated file list to a makefile variable. + +.IP "\fB\--file-list-epilogue \fItext\fR" +Insert +.I text +at the end of the file list. As a convenience, all occurrences of the +\\n character sequence in +.I text +are replaced with new lines. + +.IP "\fB\--file-list-delim \fItext\fR" +Delimit file names written to the file list with +.I text +instead of new lines. As a convenience, all occurrences of the \\n character +sequence in +.I text +are replaced with new lines. + +.\" +.\" C++/Hybrid options +.\" +.SS cxx-hybrid command options + +.IP "\fB\--generate-parser\fR" +Generate XML parsing code. + +.IP "\fB\--generate-serializer\fR" +Generate XML serialization code. + +.IP "\fB\--generate-aggregate\fR" +Generate parser/serializer aggregates for root elements and/or +types. See also the +.B --root-element-* +and +.B --root-type +options. + +.IP "\fB\--suppress-validation\fR" +Suppress the generation of validation code in parser and serializer. + +.IP "\fB\--suppress-parser-val\fR" +Suppress the generation of validation code in parser. + +.IP "\fB\--suppress-serializer-val\fR" +Suppress the generation of validation code in serializer. + +.IP "\fB\--generate-forward\fR" +Generate forward declaration file. + +.IP "\fB\--generate-xml-schema\fR" +Generate C++ header files as if the schema being compiled defines +the XML Schema namespace. In particular, the resulting files will +have definitions for all object model types, parser skeletons and +implementations, as well as serializer skeletons and implementations +corresponding to the XML Schema built-in types. The schema file +provided to the compiler need not exist and is only used to derive +the names of the resulting header files. Use the +.B --extern-xml-schema +option to include these file in the generated files for other schemas. + +.IP "\fB\--extern-xml-schema \fIfile\fR" +Include header files derived from +.I file +instead of generating the XML Schema namespace mapping inline. The +provided file need not exist and is only used to derive the names +of the included header files. Use the +.B --generate-xml-schema +option to generate these header files. + +.IP "\fB\--suppress-reset\fR" +Suppress the generation of parser and serializer reset code. +Reset support allows you to reuse parsers and serializers +after an error. + +.IP "\fB\--reuse-style-mixin\fR" +Generate code that supports the mixin base parser/serializer +implementation reuse style. Note that this reuse style +relies on virtual inheritance and may result in a substantial +object code size increase for large vocabularies. By default +the tiein reuse style is used. + +.IP "\fB\--custom-data \fItype\fR" +Add the ability to store custom data to the C++ class generated +for XML Schema type +.IR type . +To add custom data to a nested compositor class use the qualified +name starting from the XML Schema type containing the compositor, +for example, +.BR foo::sequence::choise1 . + +.IP "\fB\--custom-parser \fItype\fR[\fB=\fIbase\fR[\fB/\fIinclude\fR]]" +Use a custom parser implementation instead of the generated version. +The +.I type +component is the XML Schema type name being customized. Optional +.I base +is a C++ name that should be given to the generated version. It is +normally used as a base for the custom implementation. Optional +.I include +is the header file that defines the custom implementation. It is +.BR #include 'ed +into the generated code immediately after (if +.B base +is specified) or instead of the generated version. + +.IP "\fB\--custom-serializer \fItype\fR[\fB=\fIbase\fR[\fB/\fIinclude\fR]]" +Use a custom serializer implementation instead of the generated version. +The +.I type +component is the XML Schema type name being customized. Optional +.I base +is a C++ name that should be given to the generated version. It is +normally used as a base for the custom implementation. Optional +.I include +is the header file that defines the custom implementation. It is +.BR #include 'ed +into the generated code immediately after (if +.B base +is specified) or instead of the generated version. + +.IP "\fB\--root-element-first\fR" +Treat only the first global element as a document root. This +determines for which elements parser and serializer aggregates +are generated. By default all global elements are considered +document roots. See also the +.B --generate-aggregate +option. + +.IP "\fB\--root-element-last\fR" +Treat only the last global element as a document root. This +determines for which elements parser and serializer aggregates +are generated. By default all global elements are considered +document roots. See also the +.B --generate-aggregate +option. + +.IP "\fB\--root-element-all\fR" +Treat all global elements as document roots (the default +behavior). This determines for which elements parser and +serializer aggregates are generated. By explicitly specifying +this option you can suppress the warning that is issued if +more than one global element is defined. See also the +.B --generate-aggregate +option. + +.IP "\fB\--root-element-none\fR" +Do not treat any global elements as document roots. This +determines for which elements parser and serializer aggregates +are generated. By default all global elements are considered +document roots. See also the +.B --generate-aggregate +option. + +.IP "\fB\--root-element \fIelement\fR" +Treat only +.I element +as a document root. This +determines for which elements parser and serializer aggregates +are generated. Repeat this option to specify more than one root +element. See also the +.B --generate-aggregate +option. + +.IP "\fB\--root-type \fItype\fR" +Generate parser/serializer aggregate for +.IR type . +Repeat this option to specify more than one type. See also the +.B --generate-aggregate +option. + +.IP "\fB\--pskel-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _pskel +to construct the names of generated parser skeletons. + +.IP "\fB\--sskel-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _sskel +to construct the names of generated serializer skeletons. + +.IP "\fB\--pskel-file-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B -pskel +to construct the names of generated parser skeleton files. + +.IP "\fB\--sskel-file-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B -sskel +to construct the names of generated serializer skeleton files. + +.IP "\fB\--pimpl-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _pimpl +to construct the names of generated parser implementations. + +.IP "\fB\--simpl-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _simpl +to construct the names of generated serializer implementations. + +.IP "\fB\--pimpl-file-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B -pimpl +to construct the names of generated parser implementation files. + +.IP "\fB\--simpl-file-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B -simpl +to construct the names of generated serializer implementation files. + +.IP "\fB\--paggr-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _paggs +to construct the names of generated parser aggregates. + +.IP "\fB\--saggr-type-suffix \fIsuffix\fR" +Use +.I suffix +instead of the default +.B _saggr +to construct the names of generated serializer aggregates. + +.\" +.\" C++/Parser options +.\" +.SS cxx-parser command options + +.IP "\fB\--type-map \fImapfile\fR" +Read XML Schema to C++ type mapping information from +.I mapfile +Repeat this option to specify several type maps. Type maps are +considered in order of appearance and the first match is used. +By default all user-defined types are mapped to +.BR void . +See the TYPE MAP section below for more information. + +.IP "\fB\--reuse-style-mixin\fR" +Generate code that supports the mixin base parser implementation reuse +style. Note that this reuse style relies on virtual inheritance and may +result in a substantial object code size increase for large vocabularies. +By default support for the tiein style is generated. + +.IP "\fB\--reuse-style-none\fR" +Do not generate any support for base parser implementation reuse. By +default support for the tiein style is generated. + +.IP "\fB\--suppress-validation\fR" +Suppress the generation of validation code. + +.IP "\fB\--generate-polymorphic\fR" +Generate polymorphism-aware code. Specify this option if you use substitution +groups or +.BR xsi:type . + +.IP "\fB\--runtime-polymorphic\fR" +Generate non-polymorphic code that uses the runtime library configured with +polymorphism support. + +.IP "\fB\--suppress-reset\fR" +Suppress the generation of parser reset code. Reset support allows you to reuse +parsers after an error. + +.IP "\fB\--generate-noop-impl\fR" +Generate a sample parser implementation that does nothing (no operation). +The sample implementation can then be filled with the application-specific +code. For an input file in the form +.B name.xsd +this option triggers the generation of the two additional C++ files in the form: +.B name-pimpl.hxx +(parser implementation header file) and +.B name-pimpl.cxx +(parser implementation source file). + +.IP "\fB\--generate-print-impl\fR" +Generate a sample parser implementation that prints the XML data to STDOUT. +For an input file in the form +.B name.xsd +this option triggers the generation of the two additional C++ files in the form: +.B name-pimpl.hxx +(parser implementation header file) and +.B name-pimpl.cxx +(parser implementation source file). + +.IP "\fB\--generate-test-driver\fR" +Generate a test driver for the sample parser implementation. For an input +file in the form +.B name.xsd +this option triggers the generation of an additional C++ file in the form +.BR name-pdriver.cxx . + +.IP "\fB\--force-overwrite\fR" +Force overwriting of the existing implementation and test driver files. +Use this option only if you do not mind loosing the changes you have made +in the sample implementation or test driver files. + +.IP "\fB\--root-element-first\fR" +Indicate that the first global element is the document root. This information +is used to generate the test driver for the sample implementation. + +.IP "\fB\--root-element-last\fR" +Indicate that the last global element is the document root. This information +is used to generate the test driver for the sample implementation. + +.IP "\fB\--root-element \fIelement\fR" +Indicate that +.I element +is the document root. This information is used to generate the test driver +for the sample implementation. + +.IP "\fB\--generate-xml-schema\fR" +Generate a C++ header file as if the schema being compiled defines the +XML Schema namespace. In particular, the resulting file will have +definitions for all parser skeletons and implementations corresponding +to the XML Schema built-in types. The schema file provided to the compiler +need not exist and is only used to derive the name of the resulting header +file. Use the +.B --extern-xml-schema +option to include this file in the generated files for other schemas. + +.IP "\fB\--extern-xml-schema \fIfile\fR" +Include a header file derived from +.I file +instead of generating the XML Schema namespace mapping inline. The provided +file need not exist and is only used to derive the name of the included +header file. Use the +.B --generate-xml-schema +option to generate this header file. + +.IP "\fB\--skel-type-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B _pskel +to construct the names of generated parser skeletons. + +.IP "\fB\--skel-file-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B -pskel +to construct the names of generated parser skeleton files. + +.IP "\fB\--impl-type-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B _pimpl +to construct the names of parser implementations for the built-in XML +Schema types and sample parser implementations. + +.IP "\fB\--impl-file-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B -pimpl +to construct the names of generated sample parser implementation files. + +.\" +.\" C++/Serializer options +.\" +.SS cxx-serializer command options + +.IP "\fB\--type-map \fImapfile\fR" +Read XML Schema to C++ type mapping information from +.I mapfile +Repeat this option to specify several type maps. Type maps are +considered in order of appearance and the first match is used. +By default all user-defined types are mapped to +.BR void . +See the TYPE MAP section below for more information. + +.IP "\fB\--reuse-style-mixin\fR" +Generate code that supports the mixin base serializer implementation reuse +style. Note that this reuse style relies on virtual inheritance and may +result in a substantial object code size increase for large vocabularies. +By default support for the tiein style is generated. + +.IP "\fB\--reuse-style-none\fR" +Do not generate any support for base serializer implementation reuse. By +default support for the tiein style is generated. + +.IP "\fB\--suppress-validation\fR" +Suppress the generation of validation code. + +.IP "\fB\--generate-polymorphic\fR" +Generate polymorphism-aware code. Specify this option if you use substitution +groups or +.BR xsi:type . + +.IP "\fB\--runtime-polymorphic\fR" +Generate non-polymorphic code that uses the runtime library configured with +polymorphism support. + +.IP "\fB\--suppress-reset\fR" +Suppress the generation of serializer reset code. Reset support allows you to +reuse serializers after an error. + +.IP "\fB\--generate-empty-impl\fR" +Generate a sample serializer implementation with empty function bodies +which can then be filled with the application-specific code. For an input +file in the form +.B name.xsd +this option triggers the generation of the two additional C++ files in the form: +.B name-simpl.hxx +(serializer implementation header file) and +.B name-simpl.cxx +(serializer implementation source file). + +.IP "\fB\--generate-test-driver\fR" +Generate a test driver for the sample serializer implementation. For an input +file in the form +.B name.xsd +this option triggers the generation of an additional C++ file in the form +.BR name-sdriver.cxx . + +.IP "\fB\--force-overwrite\fR" +Force overwriting of the existing implementation and test driver files. +Use this option only if you do not mind loosing the changes you have made +in the sample implementation or test driver files. + +.IP "\fB\--root-element-first\fR" +Indicate that the first global element is the document root. This information +is used to generate the test driver for the sample implementation. + +.IP "\fB\--root-element-last\fR" +Indicate that the last global element is the document root. This information +is used to generate the test driver for the sample implementation. + +.IP "\fB\--root-element \fIelement\fR" +Indicate that +.I element +is the document root. This information is used to generate the test driver +for the sample implementation. + +.IP "\fB\--generate-xml-schema\fR" +Generate a C++ header file as if the schema being compiled defines the +XML Schema namespace. In particular, the resulting file will have +definitions for all serializer skeletons and implementations corresponding +to the XML Schema built-in types. The schema file provided to the compiler +need not exist and is only used to derive the name of the resulting header +file. Use the +.B --extern-xml-schema +option to include this file in the generated files for other schemas. + +.IP "\fB\--extern-xml-schema \fIfile\fR" +Include a header file derived from +.I file +instead of generating the XML Schema namespace mapping inline. The provided +file need not exist and is only used to derive the name of the included +header file. Use the +.B --generate-xml-schema +option to generate this header file. + +.IP "\fB\--skel-type-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B _sskel +to construct the names of generated serializer skeletons. + +.IP "\fB\--skel-file-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B -sskel +to construct the names of generated serializer skeleton files. + +.IP "\fB\--impl-type-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B _simpl +to construct the names of serializer implementations for the built-in XML +Schema types and sample serializer implementations. + +.IP "\fB\--impl-file-suffix \fIsuffix\fR" +Use the provided +.I suffix +instead of the default +.B -simpl +to construct the names of generated sample serializer implementation files. + +.\" +.\" Type map +.\" +.SH TYPE MAP + +Type map files are used to define a mapping between XML Schema and +C++ types. For C++/Parser, the compiler uses this information to +determine the return types of +.B post_* +functions in parser skeletons corresponding to XML Schema types as +well as argument types for callbacks corresponding to elements and +attributes of these types. For C++/Serializer, type maps are used +to determine the argument type of +.B pre +functions in serializer skeletons corresponding to XML Schema types +as well as return types for callbacks corresponding to elements and +attributes of these types. + +The compiler has a set of predefined mapping rules that map the +built-in XML Schema types to suitable C++ types (discussed in +the following sub-sections) and all other types to +.BR void . +By providing your own type maps you can override these predefined +rules. The format of the type map file is presented below: + + +.RS +.B namespace +.I schema-namespace +[ +.I cxx-namespace +] +.br +.B { +.br + ( +.B include +.IB file-name ; +)* +.br + ([ +.B type +] +.I schema-type cxx-ret-type +[ +.I cxx-arg-type +.RB ] ; +)* +.br +.B } +.br +.RE + +Both +.I schema-namespace +and +.I schema-type +are regex patterns while +.IR cxx-namespace , +.IR cxx-ret-type , +and +.I cxx-arg-type +are regex pattern substitutions. All names can be optionally enclosed +in \fR" "\fR, for example, to include white-spaces. + +.I schema-namespace +determines XML Schema namespace. Optional +.I cxx-namespace +is prefixed to every C++ type name in this namespace declaration. +.I cxx-ret-type +is a C++ type name that is used as a return type for the +.B post_* +function in C++/Parser or for element/attribute callbacks in C++/Serializer. +Optional +.I cxx-arg-type +is an argument type for element/attribute callbacks in C++/Parser or for the +.B pre +function in C++/Serializer. If +.I cxx-arg-type +is not specified, it defaults to +.I cxx-ret-type +if +.I cxx-ret-type +ends with +.B * +or +.B & +(that is, it is a pointer or a reference) and +.B const +\fIcxx-ret-type\fB&\fR otherwise. +.I file-name +is a file name either in the \fR" "\fR or < > format and is added with the +.B #include +directive to the generated code. + +The \fB#\fR character starts a comment that ends with a new line or end of +file. To specify a name that contains \fB#\fR enclose it in \fR" "\fR. For +example: + +.RS +namespace http://www.example.com/xmlns/my my +.br +{ +.br + include "my.hxx"; +.br + + # Pass apples by value. + # + apple apple; +.br + + # Pass oranges as pointers. + # + orange orange_t*; +.br +} +.br +.RE + +In the example above, for the +.B http://www.example.com/xmlns/my#orange +XML Schema type, the +.B my::orange_t* +C++ type will be used as both return and argument types. + +Several namespace declarations can be specified in a single file. +The namespace declaration can also be completely omitted to map +types in a schema without a namespace. For instance: + +.RS +include "my.hxx"; +.br +apple apple; +.br + +namespace http://www.example.com/xmlns/my +.br +{ +.br + orange "const orange_t*"; +.br +} +.br +.RE + +The compiler has a number of predefined mapping rules for the built-in +XML Schema types that vary depending on the mapping used. They are +described in the following subsections. The last predefined rule +for all mappings maps anything that wasn't mapped by previous rules to +.BR void : + +.RS +namespace .* +.br +{ +.br + .* void void; +.br +} +.br +.RE + +When you provide your own type maps with the +.B --type-map +option, they are evaluated first. This allows you to selectively override +predefined rules. + +.\" +.\" Predefined C++/Parser Type Maps +.\" +.SS Predefined C++/Parser Type Maps + +The C++/Parser mapping provides a number of predefined type map rules +for the built-in XML Schema types. They can be presented as the +following map files: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + boolean bool bool; +.br + + byte "signed char" "signed char"; +.br + unsignedByte "unsigned char" "unsigned char"; +.br + + short short short; +.br + unsignedShort "unsigned short" "unsigned short"; +.br + + int int int; +.br + unsignedInt "unsigned int" "unsigned int"; +.br + + long "long long" "long long"; +.br + unsignedLong "unsigned long long" "unsigned long long"; +.br + + integer long long; +.br + + negativeInteger long long; +.br + nonPositiveInteger long long; +.br + + positiveInteger "unsigned long" "unsigned long"; +.br + nonNegativeInteger "unsigned long" "unsigned long"; +.br + + float float float; +.br + double double double; +.br + decimal double double; +.br + + NMTOKENS xml_schema::string_sequence*; +.br + IDREFS xml_schema::string_sequence*; +.br + + base64Binary xml_schema::buffer*; +.br + hexBinary xml_schema::buffer*; +.br + + date xml_schema::date; +.br + dateTime xml_schema::date_time; +.br + duration xml_schema::duration; +.br + gDay xml_schema::gday; +.br + gMonth xml_schema::gmonth; +.br + gMonthDay xml_schema::gmonth_day; +.br + gYear xml_schema::gyear; +.br + gYearMonth xml_schema::gyear_month; +.br + time xml_schema::time; +.br +} +.br +.RE + +If the +.B --no-stl +option is not specified, the following mapping is used for the +string-based XML Schema built-in types: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + include ; +.br + + string std::string; +.br + normalizedString std::string; +.br + token std::string; +.br + Name std::string; +.br + NMTOKEN std::string; +.br + NCName std::string; +.br + ID std::string; +.br + IDREF std::string; +.br + language std::string; +.br + anyURI std::string; +.br + + QName xml_schema::qname; +.br +} +.br +.RE + +Otherwise, a C string-based mapping is used: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + string char*; +.br + normalizedString char*; +.br + token char*; +.br + Name char*; +.br + NMTOKEN char*; +.br + NCName char*; +.br + ID char*; +.br + IDREF char*; +.br + language char*; +.br + anyURI char*; +.br + + QName xml_schema::qname*; +.br +} +.br +.RE + +.\" +.\" Predefined C++/Serializer Type Maps +.\" +.SS Predefined C++/Serializer Type Maps + +The C++/Serializer mapping provides a number of predefined type map +rules for the built-in XML Schema types. They can be presented as the +following map files: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + boolean bool bool; +.br + + byte "signed char" "signed char"; +.br + unsignedByte "unsigned char" "unsigned char"; +.br + + short short short; +.br + unsignedShort "unsigned short" "unsigned short"; +.br + + int int int; +.br + unsignedInt "unsigned int" "unsigned int"; +.br + + long "long long" "long long"; +.br + unsignedLong "unsigned long long" "unsigned long long"; +.br + + integer long long; +.br + + negativeInteger long long; +.br + nonPositiveInteger long long; +.br + + positiveInteger "unsigned long" "unsigned long"; +.br + nonNegativeInteger "unsigned long" "unsigned long"; +.br + + float float float; +.br + double double double; +.br + decimal double double; +.br + + NMTOKENS "const xml_schema::string_sequence*"; +.br + IDREFS "const xml_schema::string_sequence*"; +.br + + base64Binary "const xml_schema::buffer*"; +.br + hexBinary "const xml_schema::buffer*"; +.br + + date xml_schema::date; +.br + dateTime xml_schema::date_time; +.br + duration xml_schema::duration; +.br + gDay xml_schema::gday; +.br + gMonth xml_schema::gmonth; +.br + gMonthDay xml_schema::gmonth_day; +.br + gYear xml_schema::gyear; +.br + gYearMonth xml_schema::gyear_month; +.br + time xml_schema::time; +.br +} +.br +.RE + +If the +.B --no-stl +option is not specified, the following mapping is used for the +string-based XML Schema built-in types: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + include ; +.br + + string std::string; +.br + normalizedString std::string; +.br + token std::string; +.br + Name std::string; +.br + NMTOKEN std::string; +.br + NCName std::string; +.br + ID std::string; +.br + IDREF std::string; +.br + language std::string; +.br + anyURI std::string; +.br + + QName xml_schema::qname; +.br +} +.br +.RE + +Otherwise, a C string-based mapping is used: + +.RS +namespace http://www.w3.org/2001/XMLSchema +.br +{ +.br + string "const char*"; +.br + normalizedString "const char*"; +.br + token "const char*"; +.br + Name "const char*"; +.br + NMTOKEN "const char*"; +.br + NCName "const char*"; +.br + ID "const char*"; +.br + IDREF "const char*"; +.br + language "const char*"; +.br + anyURI "const char*"; +.br + + QName "const xml_schema::qname*"; +.br +} +.br +.RE + +.\" +.\" REGEX AND SHELL QUOTING +.\" +.SH REGEX AND SHELL QUOTING +When entering a regular expression argument in the shell command line +it is often necessary to use quoting (enclosing the argument in " " +or ' ') in order to prevent the shell from interpreting certain +characters, for example, spaces as argument separators and $ as +variable expansions. + +Unfortunately it is hard to achieve this in a manner that is portable +across POSIX shells, such as those found on GNU/Linux and UNIX, and +Windows shell. For example, if you use " " for quoting you will get +a wrong result with POSIX shells if your expression contains $. The +standard way of dealing with this on POSIX systems is to use ' ' +instead. Unfortunately, Windows shell does not remove ' ' from +arguments when they are passed to applications. As a result you may +have to use ' ' for POSIX and " " for Windows ($ is not treated as +a special character on Windows). + +Alternatively, you can save regular expression options into a file, +one option per line, and use this file with the +.B --options-file +option. With this approach you don't need to worry about shell quoting. + +.\" +.\" DIAGNOSTICS +.\" +.SH DIAGNOSTICS +If the input file is not a valid W3C XML Schema definition, +.B xsde +will issue diagnostic messages to +.B STDERR +and exit with non-zero exit code. + +.SH BUGS +Send bug reports to the xsde-users@codesynthesis.com mailing list. + +.SH COPYRIGHT +Copyright (c) 2005-2009 Code Synthesis Tools CC. + +Permission is granted to copy, distribute and/or modify this +document under the terms of the GNU Free Documentation License, +version 1.2; with no Invariant Sections, no Front-Cover Texts and +no Back-Cover Texts. Copy of the license can be obtained from +http://codesynthesis.com/licenses/fdl-1.2.txt diff --git a/documentation/xsde.xhtml b/documentation/xsde.xhtml new file mode 100644 index 0000000..ac01b91 --- /dev/null +++ b/documentation/xsde.xhtml @@ -0,0 +1,1578 @@ + + + + + + XSD/e 3.0.0 Compiler Command Line Manual + + + + + + + + + + + +
+
+ +

NAME

+ +

xsde - W3C XML Schema to C++ Compiler for Embedded Systems

+ +

SYNOPSIS

+ +
+
xsde command [options] file [file ...]
+
xsde help [command]
+
xsde version
+
+ +

DESCRIPTION

+ +

xsde generates vocabulary-specific, statically-typed + C++ mapping from W3C XML Schema definitions. Particular mapping to + produce is selected by a command. Each mapping has + a number of mapping-specific options that should + appear, if any, after the command. Input files should + be W3C XML Schema definitions. The exact set of the generated files + depends on the selected mapping and options.

+ +

COMMANDS

+ +
+
cxx-hybrid
+
Generate the Embedded C++/Hybrid mapping. For each input file in the + form name.xsd the following C++ files are generated: + name.hxx (object model header file), + name.ixx (object model inline file, generated only + if the --generate-inline option is specified), + name.cxx (object model source file), and + name-fwd.hxx (object model forward declaration + file, generated only if the --generate-forward + option is specified). + +

If the --generate-parser option is specified, + the Embedded C++/Parser mapping is invoked and the + name-pskel.hxx, + name-pskel.ixx, and + name-pskel.cxx parser skeleton files are + generated, as described below. Additionally, the following parser + implementation files are generated: + name-pimpl.hxx (parser implementation header + file) and + name-pimpl.cxx (parser implementation source + file).

+ +

If the --generate-serializer option is + specified, the Embedded C++/Serializer mapping is invoked and the + name-sskel.hxx, + name-sskel.ixx, and + name-sskel.cxx serializer skeleton files are + generated, as described below. Additionally, the following serializer + implementation files are generated: + name-simpl.hxx (serializer implementation header + file) and + name-simpl.cxx (serializer implementation source + file).

+
+ +
cxx-parser
+
Generate the Embedded C++/Parser mapping. For each input file in the + form name.xsd the following C++ files are generated: + name-pskel.hxx (parser skeleton header file), + name-pskel.ixx (parser skeleton inline file, + generated only if the --generate-inline + option is specified), and + name-pskel.cxx (parser skeleton source file). + If the --generate-noop-impl or + --generate-print-impl option is specified, + the following additional sample implementation files are generated: + name-pimpl.hxx (parser implementation header + file) and + name-pimpl.cxx (parser implementation source + file). If the --generate-test-driver option + is specified, the additional name-pdriver.cxx + test driver file is generated.
+ +
cxx-serializer
+
Generate the Embedded C++/Serializer mapping. For each input file + in the form name.xsd the following C++ files + are generated: name-sskel.hxx (serializer + skeleton header file), name-sskel.ixx (serializer + skeleton inline file, generated only if the + --generate-inline option is specified), and + name-sskel.cxx (serializer skeleton source file). + If the --generate-empty-impl option is specified, + the following additional sample implementation files are generated: + name-simpl.hxx (serializer implementation header + file) and name-simpl.cxx (serializer + implementation source file). If the --generate-test-driver + option is specified, the additional name-sdriver.cxx + test driver file is generated. +
+ +
help
+
Print usage information and exit. Use +

xsde help command

+ for command-specific help. +
+ +
version
+
Print version and exit.
+
+ +

OPTIONS

+ +

Command-specific options, if any, should appear + after the corresponding command.

+ +

COMMON OPTIONS

+ +
+
--output-dir dir
+
Write generated files to dir instead of + the current directory.
+ +
--no-stl
+
Generate code that does not use the Standard Template Library + (STL).
+ +
--no-iostream
+
Generate code that does not use the standard input/output + stream library (iostream).
+ +
--no-exceptions
+
Generate code that does not use C++ exceptions.
+ +
--no-long-long
+
Generate code that does not use the long long + and unsigned long long types. The + 64 bit long and unsignedLong + built-in XML Schema types are then mapped to long + and unsigned long.
+ +
--generate-inline
+
Generate simple functions inline. This option triggers creation + of the inline file.
+ +
--namespace-map xns=cns
+
Map XML Schema namespace xns to C++ namespace cns. + Repeat this option to specify mapping for more than one XML Schema + namespace. For example, the following option: + +

--namespace-map http://example.com/foo/bar=foo::bar

+ +

will map the http://example.com/foo/bar + XML Schema namespace to the foo::bar C++ + namespace.

+
+ +
--namespace-regex regex
+
Add regex to the list of regular expressions + used to translate XML Schema namespace names to C++ namespace + names. regex is a perl-like regular expression in + the form /pattern/replacement/. + Any character can be used as a delimiter instead of /. + Escaping of the delimiter character in pattern or + replacement is not supported. + +

All regular expressions are pushed into a stack with the last + specified expression considered first. The first match that + succeeds is used. Regular expressions are applied to a string + in the form

+ +

filename namespace

+ +

For example,

+ +

XMLSchema.xsd http://www.w3.org/2001/XMLSchema

+ +

The filename for the current translation unit + is empty. For example, if you have file hello.xsd + with namespace http://example.com/hello and you run + xsde on this file, then the string in question + would be:

+ +

 http://example.com/hello

+ +

Note the leading space.

+ +

The following three steps are performed for each regular expression + until the match is found:

+ +
    +
  1. The expression is applied and if the result is empty the + next expression is considered.
  2. + +
  3. All / are replaced with + ::.
  4. + +
  5. The result is verified to be a valid C++ scope name (e.g., + foo::bar). If this test succeeds, the + result is used as a C++ namespace name.
  6. +
+ +

As an example, the following expression maps XML Schema + namespaces in the form + http://example.com/foo/bar to C++ + namespaces in the form foo::bar:

+ +

%.* http://example.com/(.+)%$1%

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--namespace-regex-trace
+
Trace the process of applying regular expressions specified with + the --namespace-regex option. Use this option + to find out why your regular expressions don't do what you expected + them to do. +
+ + + +
--reserved-name name[=rep]
+
Add name to the list of names that should not + be used as identifiers. The name can optionally be followed by + = and the replacement name that should be + used instead. All C++ keywords are already in this list. +
+ +
--include-with-brackets
+
Use angle brackets (<>) instead of quotes ("") in + generated #include directives. +
+ +
--include-prefix prefix
+
Add prefix to generated #include + directive paths. + +

For example, if you had the following import element in your + schema

+ +

<import namespace="..." schemaLocation="base.xsd"/>

+ +

and compiled this fragment with --include-prefix schemas/, + then the include directive in the generated code would be:

+ +

#include "schemas/base.hxx"

+
+ +
--include-regex regex
+
Add regex to the list of regular expressions + used to transform #include directive paths. + regex is a perl-like regular expression in + the form /pattern/replacement/. + Any character can be used as a delimiter instead of /. + Escaping of the delimiter character in pattern or + replacement is not supported. + +

All regular expressions are pushed into a stack with the last + specified expression considered first. The first match that + succeeds is used.

+ +

As an example, the following expression transforms paths + in the form schemas/foo/bar to paths + in the form generated/foo/bar:

+ +

%schemas/(.+)%generated/$1%

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--include-regex-trace
+
Trace the process of applying regular expressions specified with + the --include-regex option. Use this option + to find out why your regular expressions don't do what you expected + them to do. +
+ +
--guard-prefix prefix
+
Add prefix to generated header inclusion guards. + The prefix is transformed to upper case and all characters that are + illegal in a preprocessor macro name are replaced with underscores. + If this option is not specified then the directory part of the + input schema file is used as a prefix. +
+ +
--hxx-suffix suffix
+
Use the provided suffix instead of the default + .hxx to construct the name of the header file. + Note that this suffix is also used to construct names for + included/imported schemas. +
+ +
--ixx-suffix suffix
+
Use the provided suffix instead of the default + .ixx to construct the name of the inline file. +
+ +
--cxx-suffix suffix
+
Use the provided suffix instead of the default + .cxx to construct the name of the source file. +
+ +
--fwd-suffix suffix
+
Use the provided suffix instead of the default + -fwd.hxx to construct the name of the forward + declaration file (C++/Hybrid mapping only). +
+ +
--hxx-regex regex
+
Use the provided expression to construct the name of the header + file. regex is a perl-like regular expression + in the form + /pattern/replacement/. + This expression is also used to construct names for included/imported + schemas. + +

+ For the C++/Hybrid mapping, the regex argument + can be optionally prefixed with a file key in the form + key=regex. The valid values for + key are pskel (parser + skeleton files), pimpl (parser implementation + files), sskel (serializer skeleton files), + simpl (serializer implementation files), + and * (all files). If key + is empty or not present then the expression is used for the + object model files only. +

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--ixx-regex regex
+
Use the provided expression to construct the name of the inline + file. regex is a perl-like regular expression + in the form + /pattern/replacement/. + For the C++/Hybrid mapping, the regex argument + can be optionally prefixed with a file key. See the + --hxx-regex option for details. + See also the REGEX AND SHELL QUOTING section below. +
+ +
--cxx-regex regex
+
Use the provided expression to construct the name of the source + file. regex is a perl-like regular expression + in the form + /pattern/replacement/. + For the C++/Hybrid mapping, the regex argument + can be optionally prefixed with a file key. See the + --hxx-regex option for details. + See also the REGEX AND SHELL QUOTING section below. +
+ +
--fwd-regex regex
+
Use the provided expression to construct the name of the forward + declaration file (C++/Hybrid mapping only). regex + is a perl-like regular expression in the form + /pattern/replacement/. + See also the REGEX AND SHELL QUOTING section below. +
+ + + +
--hxx-prologue text
+
Insert text at the beginning of the header file. + +

+ For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key in the form + key=text. The valid values for + key are pskel (parser + skeleton files), pimpl (parser implementation + files), sskel (serializer skeleton files), + simpl (serializer implementation files), + and * (all files). If key + is empty or not present then the text is used for the + object model files only. +

+ +
+ +
--ixx-prologue text
+
Insert text at the beginning of the inline file. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ +
--cxx-prologue text
+
Insert text at the beginning of the source file. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ +
--fwd-prologue text
+
Insert text at the beginning of the forward + declaration file (C++/Hybrid mapping only). +
+ +
--prologue text
+
Insert text at the beginning of each generated + file for which there is no file-specific prologue. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ + + +
--hxx-epilogue text
+
Insert text at the end of the header file. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ +
--ixx-epilogue text
+
Insert text at the end of the inline file. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ +
--cxx-epilogue text
+
Insert text at the end of the source file. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ +
--fwd-epilogue text
+
Insert text at the end of the forward + declaration file (C++/Hybrid mapping only). +
+ +
--epilogue text
+
Insert text at the end of each generated + file for which there is no file-specific epilogue. + For the C++/Hybrid mapping, the text argument + can be optionally prefixed with a file key. See the + --hxx-prologue option for details. +
+ + + +
--hxx-prologue-file file
+
Insert the content of the file at the beginning + of the header file. + +

+ For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key in the form + key=file. The valid values for + key are pskel (parser + skeleton files), pimpl (parser implementation + files), sskel (serializer skeleton files), + simpl (serializer implementation files), + and * (all files). If key + is empty or not present then the file is used for the + object model files only. +

+
+ +
--ixx-prologue-file file
+
Insert the content of the file at the beginning + of the inline file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ +
--cxx-prologue-file file
+
Insert the content of the file at the beginning + of the source file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ +
--fwd-prologue-file file
+
Insert the content of the file at the beginning + of the forward declaration file (C++/Hybrid mapping only). +
+ +
--prologue-file file
+
Insert the content of the file at the beginning + of each generated file for which there is no file-specific prologue + file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ + + +
--hxx-epilogue-file file
+
Insert the content of the file at the end of the + header file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ +
--ixx-epilogue-file file
+
Insert the content of the file at the end of the + inline file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ +
--cxx-epilogue-file file
+
Insert the content of the file at the end of the + source file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ +
--fwd-epilogue-file file
+
Insert the content of the file at the end of the + forward declaration file (C++/Hybrid mapping only). +
+ +
--epilogue-file file
+
Insert the content of the file at the end of each + generated file for which there is no file-specific epilogue file. + For the C++/Hybrid mapping, the file argument + can be optionally prefixed with a file key. See the + --hxx-prologue-file option for details. +
+ + +
--disable-warning warn
+
Disable printing warning with id warn. If all + is specified for the warning id then all warnings are disabled. +
+ + + +
--show-sloc
+
Show the number of generated physical source lines of code (SLOC). +
+ +
--sloc-limit num
+
Check that the number of generated physical source lines of code + (SLOC) does not exceed num. +
+ +
--options-file file
+
Read additional options from file. Each option + should appear on a separate line optionally followed by space and + an argument. Empty lines and lines starting with # + are ignored. The semantics of providing options in a + file is equivalent to providing the same set of options in + the same order in the command line at the point where the + --options-file option is specified + except that shell escaping and quoting is not required. + Repeat this option to specify more than one options files. +
+ +
--proprietary-license
+
Indicate that the generated code is licensed under a proprietary + license instead of the GPL. +
+ + + +
--preserve-anonymous
+
Preserve anonymous types. By default anonymous types are + automatically named with names derived from the enclosing + elements/attributes. Because mappings implemented by this + compiler require all types to be named, this option is only + useful if you want to make sure your schemas don't have + anonymous types. +
+ +
--show-anonymous
+
Show elements and attributes that are of anonymous types. + This option only makes sense together with the + --preserve-anonymous option. +
+ +
--anonymous-regex regex
+
Add regex to the list of regular expressions + used to derive names for anonymous types from the enclosing + attributes/elements. regex is a perl-like regular + expression in the form + /pattern/replacement/. + Any character can be used as a delimiter instead of /. + Escaping of the delimiter character in pattern or + replacement is not supported. + +

All regular expressions are pushed into a stack with the last + specified expression considered first. The first match that + succeeds is used. Regular expressions are applied to a string + in the form

+ +

filename namespace xpath

+ +

For example,

+ +

hello.xsd http://example.com/hello element

+

hello.xsd http://example.com/hello type/element

+ +

The filename for the current translation unit + is empty. For example, if you have file hello.xsd + with namespace http://example.com/hello and you run + xsde on this file, then the string in question + would be:

+ +

 http://example.com/hello element

+ +

Note the leading space.

+ +

As an example, the following expression makes all the derived + names start with capital letters. This could be useful when + your naming convention requires type names to start with + capital letters:

+ +

%.* .* (.+/)*(.+)%\u$2%

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--anonymous-regex-trace
+
Trace the process of applying regular expressions specified with + the --anonymous-regex option. Use this option + to find out why your regular expressions don't do what you expected + them to do. +
+ + + +
--location-map ol=nl
+
Map the original schema location ol that is specified in + the XML Schema include or import elements to new schema + location nl. Repeat this option to map more than one + schema location. For example, the following option maps the + http://example.com/foo.xsd URL to the + foo.xsd local file. + +

--location-map http://example.com/foo.xsd=foo.xsd

+
+ +
--location-regex regex
+
Add regex to the list of regular expressions + used to map schema locations that are specified in the XML Schema + include or import elements. regex is a perl-like + regular expression in the form + /pattern/replacement/. + Any character can be used as a delimiter instead of /. + Escaping of the delimiter character in pattern or + replacement is not supported. All regular + expressions are pushed into a stack with the last specified + expression considered first. The first match that succeeds is used. + +

For example, the following expression maps URL locations in the form + http://example.com/foo/bar.xsd to local files + in the form bar.xsd:

+ +

%http://.+/(.+)%$1%

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--location-regex-trace
+
Trace the process of applying regular expressions specified with + the --location-regex option. Use this option + to find out why your regular expressions don't do what you expected + them to do. +
+ + + +
--file-per-type
+
Generate a separate set of C++ files for each type defined in XML + Schema. Note that in this mode you only need to compile the root + schema(s) and the code will be generated for all included and + imported schemas. This compilation mode is primarily useful when + some of your schemas cannot be compiled separately or have cyclic + dependencies which involve type inheritance. +
+ + +
--type-file-regex regex
+
Add regex to the list of regular expressions + used to translate type names to file names when the + --type-per-file option is specified. + regex is a perl-like regular expression in the form + /pattern/replacement/. + Any character can be used as a delimiter instead of /. + Escaping of the delimiter character in pattern or + replacement is not supported. All regular + expressions are pushed into a stack with the last specified + expression considered first. The first match that succeeds is used. + Regular expressions are applied to a string in the form + +

namespace type-name

+ +

For example, the following expression maps type foo + that is defined in the http://example.com/bar + namespace to file name bar-foo:

+ +

%http://example.com/(.+) (.+)%$1-$2%

+ +

See also the REGEX AND SHELL QUOTING section below.

+
+ +
--type-file-regex-trace
+
Trace the process of applying regular expressions specified with + the --type-file-regex option. Use this option + to find out why your regular expressions don't do what you expected + them to do. +
+ + + +
--file-list file
+
Write a list of generated C++ files to file. + This option is primarily useful in the file-per-type compilation + mode (--file-per-type) to create a list of + generated C++ files, for example, as a makefile fragment. +
+ +
--file-list-prologue text
+
Insert text at the beginning of the file list. + As a convenience, all occurrences of the \n character sequence in + text are replaced with new lines. This option + can, for example, be used to assign the generated file list to a + makefile variable. +
+ +
--file-list-epilogue text
+
Insert text at the end of the file list. + As a convenience, all occurrences of the \n character sequence in + text are replaced with new lines. +
+ +
--file-list-delim text
+
Delimit file names written to the file list with + text instead of new lines. As a convenience, + all occurrences of the \n character sequence in + text are replaced with new lines. +
+ +
+ +

CXX-HYBRID COMMAND OPTIONS

+ +
+
--generate-parser
+
Generate XML parsing code.
+ +
--generate-serializer
+
Generate XML serialization code.
+ +
--generate-aggregate
+
Generate parser/serializer aggregates for root elements and/or + types. See also the --root-element-* and + --root-type options.
+ +
--suppress-validation
+
Suppress the generation of validation code in parser and serializer.
+ +
--suppress-parser-val
+
Suppress the generation of validation code in parser.
+ +
--suppress-serializer-val
+
Suppress the generation of validation code in serializer.
+ +
--generate-forward
+
Generate forward declaration file.
+ +
--generate-xml-schema
+
Generate C++ header files as if the schema being compiled defines + the XML Schema namespace. In particular, the resulting files will + have definitions for all object model types, parser skeletons and + implementations, as well as serializer skeletons and implementations + corresponding to the XML Schema built-in types. The schema file + provided to the compiler need not exist and is only used to derive + the names of the resulting header files. Use the + --extern-xml-schema option to include these file + in the generated files for other schemas.
+ +
--extern-xml-schema file
+
Include header files derived from file instead of + generating the XML Schema namespace mapping inline. The provided + file need not exist and is only used to derive the names of the + included header files. Use the --generate-xml-schema + option to generate these header files.
+ +
--suppress-reset
+
Suppress the generation of parser and serializer reset code. + Reset support allows you to reuse parsers and serializers + after an error.
+ +
--reuse-style-mixin
+
Generate code that supports the mixin base parser/serializer + implementation reuse style. Note that this reuse style + relies on virtual inheritance and may result in a substantial + object code size increase for large vocabularies. By default + the tiein reuse style is used.
+ + +
--custom-data type
+
Add the ability to store custom data to the C++ class generated + for XML Schema type type. To add custom + data to a nested compositor class use the qualified name + starting from the XML Schema type containing the compositor, + for example, foo::sequence::choise1.
+ +
--custom-parser + type[=base[/include]]
+
Use a custom parser implementation instead of the generated version. + The type component is the XML Schema type name + being customized. Optional base is a C++ name + that should be given to the generated version. It is normally used + as a base for the custom implementation. Optional + include is the header file that defines the + custom implementation. It is #include'ed + into the generated code immediately after (if base + is specified) or instead of the generated version.
+ +
--custom-serializer + type[=base[/include]]
+
Use a custom serializer implementation instead of the generated version. + The type component is the XML Schema type name + being customized. Optional base is a C++ name + that should be given to the generated version. It is normally used + as a base for the custom implementation. Optional + include is the header file that defines the + custom implementation. It is #include'ed + into the generated code immediately after (if base + is specified) or instead of the generated version.
+ + + +
--root-element-first
+
Treat only the first global element as a document root. This + determines for which elements parser and serializer aggregates + are generated. By default all global elements are considered + document roots. See also the --generate-aggregate + option. +
+ +
--root-element-last
+
Treat only the last global element as a document root. This + determines for which elements parser and serializer aggregates + are generated. By default all global elements are considered + document roots. See also the --generate-aggregate + option. +
+ +
--root-element-all
+
Treat all global elements as document roots (the default + behavior). This determines for which elements parser and + serializer aggregates are generated. By explicitly specifying + this option you can suppress the warning that is issued if + more than one global element is defined. See also the + --generate-aggregate option. +
+ +
--root-element-none
+
Do not treat any global elements as document roots. This + determines for which elements parser and serializer aggregates + are generated. By default all global elements are considered + document roots. See also the --generate-aggregate + option. +
+ +
--root-element element
+
Treat only element as a document root. This + determines for which elements parser and serializer aggregates + are generated. Repeat this option to specify more than one root + element. See also the --generate-aggregate option. +
+ +
--root-type type
+
Generate parser/serializer aggregate for type. + Repeat this option to specify more than one type. See also the + --generate-aggregate option.
+ +
--pskel-type-suffix suffix
+
Use suffix instead of the default + _pskel to construct the names of generated parser + skeletons.
+ +
--sskel-type-suffix suffix
+
Use suffix instead of the default + _sskel to construct the names of generated + serializer skeletons.
+ +
--pskel-file-suffix suffix
+
Use suffix instead of the default + -pskel to construct the names of generated + parser skeleton files.
+ +
--sskel-file-suffix suffix
+
Use suffix instead of the default + -sskel to construct the names of generated + serializer skeleton files.
+ +
--pimpl-type-suffix suffix
+
Use suffix instead of the default + _pimpl to construct the names of generated + parser implementations.
+ +
--simpl-type-suffix suffix
+
Use suffix instead of the default + _simpl to construct the names of generated + serializer implementations.
+ +
--pimpl-file-suffix suffix
+
Use suffix instead of the default + -pimpl to construct the names of generated + parser implementation files.
+ +
--simpl-file-suffix suffix
+
Use suffix instead of the default + -simpl to construct the names of generated + serializer implementation files.
+ +
--paggr-type-suffix suffix
+
Use suffix instead of the default + _paggs to construct the names of generated + parser aggregates.
+ +
--saggr-type-suffix suffix
+
Use suffix instead of the default + _saggr to construct the names of generated + serializer aggregates.
+
+ +

CXX-PARSER COMMAND OPTIONS

+ +
+
--type-map mapfile
+
Read XML Schema to C++ type mapping information from + mapfile. Repeat this option to specify + several type maps. Type maps are considered in order of + appearance and the first match is used. By default all + user-defined types are mapped to void. + See the TYPE MAP section below for more information.
+ +
--reuse-style-mixin
+
Generate code that supports the mixin base parser + implementation reuse style. Note that this reuse style + relies on virtual inheritance and may result in a substantial + object code size increase for large vocabularies. By default + support for the tiein style is generated.
+ +
--reuse-style-none
+
Do not generate any support for base parser implementation + reuse. By default support for the tiein style is generated.
+ +
--suppress-validation
+
Suppress the generation of validation code.
+ +
--generate-polymorphic
+
Generate polymorphism-aware code. Specify this option if you use + substitution groups or xsi:type.
+ +
--runtime-polymorphic
+
Generate non-polymorphic code that uses the runtime library + configured with polymorphism support.
+ +
--suppress-reset
+
Suppress the generation of parser reset code. Reset + support allows you to reuse parsers after an error.
+ +
--generate-noop-impl
+
Generate a sample parser implementation that does nothing (no + operation). The sample implementation can then be filled with + the application-specific code. For an input file in the form + name.xsd this option triggers the generation + of the two additional C++ files in the form: + name-pimpl.hxx (parser implementation header + file) and name-pimpl.cxx (parser implementation + source file).
+ +
--generate-print-impl
+
Generate a sample parser implementation that prints the XML data + to STDOUT. For an input file in the form name.xsd + this option triggers the generation of the two additional C++ files + in the form: name-pimpl.hxx (parser implementation + header file) and name-pimpl.cxx (parser + implementation source file).
+ +
--generate-test-driver
+
Generate a test driver for the sample parser implementation. For an + input file in the form name.xsd this option + triggers the generation of an additional C++ file in the form + name-pdriver.cxx.
+ +
--force-overwrite
+
Force overwriting of the existing implementation and test driver + files. Use this option only if you do not mind loosing the changes + you have made in the sample implementation or test driver files.
+ +
--root-element-first
+
Indicate that the first global element is the document root. This + information is used to generate the test driver for the sample + implementation.
+ +
--root-element-last
+
Indicate that the last global element is the document root. This + information is used to generate the test driver for the sample + implementation.
+ +
--root-element element
+
Indicate that element is the document root. + This information is used to generate the test driver for the + sample implementation.
+ +
--generate-xml-schema
+
Generate a C++ header file as if the schema being compiled defines + the XML Schema namespace. In particular, the resulting file will + have definitions for all parser skeletons and implementations + corresponding to the XML Schema built-in types. The schema file + provided to the compiler need not exist and is only used to derive + the name of the resulting header file. Use the + --extern-xml-schema option to include this file + in the generated files for other schemas.
+ +
--extern-xml-schema file
+
Include a header file derived from file instead of + generating the XML Schema namespace mapping inline. The provided + file need not exist and is only used to derive the name of the + included header file. Use the --generate-xml-schema + option to generate this header file.
+ +
--skel-type-suffix suffix
+
Use the provided suffix instead of the + default _pskel to construct the names + of generated parser skeletons.
+ +
--skel-file-suffix suffix
+
Use the provided suffix instead of the + default -pskel to construct the names of + generated parser skeleton files.
+ +
--impl-type-suffix suffix
+
Use the provided suffix instead of the + default _pimpl to construct the names of + parser implementations for the built-in XML Schema types + and sample parser implementations.
+ +
--impl-file-suffix suffix
+
Use the provided suffix instead of the + default -pimpl to construct the names of + generated sample parser implementation files.
+
+ +

CXX-SERIALIZER COMMAND OPTIONS

+ +
+
--type-map mapfile
+
Read XML Schema to C++ type mapping information from + mapfile. Repeat this option to specify + several type maps. Type maps are considered in order of + appearance and the first match is used. By default all + user-defined types are mapped to void. + See the TYPE MAP section below for more information.
+ +
--reuse-style-mixin
+
Generate code that supports the mixin base serializer + implementation reuse style. Note that this reuse style + relies on virtual inheritance and may result in a substantial + object code size increase for large vocabularies. By default + support for the tiein style is generated.
+ +
--reuse-style-none
+
Do not generate any support for base serializer implementation + reuse. By default support for the tiein style is generated.
+ +
--suppress-validation
+
Suppress the generation of validation code.
+ +
--generate-polymorphic
+
Generate polymorphism-aware code. Specify this option if you use + substitution groups or xsi:type.
+ +
--runtime-polymorphic
+
Generate non-polymorphic code that uses the runtime library + configured with polymorphism support.
+ +
--suppress-reset
+
Suppress the generation of serializer reset code. Reset + support allows you to reuse serializers after an error.
+ +
--generate-empty-impl
+
Generate a sample serializer implementation with empty function + bodies which can then be filled with the application-specific code. + For an input file in the form name.xsd this + option triggers the generation of the two additional C++ files in the + form: name-simpl.hxx (serializer implementation + header file) and name-simpl.cxx (serializer + implementation source file).
+ +
--generate-test-driver
+
Generate a test driver for the sample serializer implementation. For + an input file in the form name.xsd this option + triggers the generation of an additional C++ file in the form + name-sdriver.cxx.
+ +
--force-overwrite
+
Force overwriting of the existing implementation and test driver + files. Use this option only if you do not mind loosing the changes + you have made in the sample implementation or test driver files.
+ +
--root-element-first
+
Indicate that the first global element is the document root. This + information is used to generate the test driver for the sample + implementation.
+ +
--root-element-last
+
Indicate that the last global element is the document root. This + information is used to generate the test driver for the sample + implementation.
+ +
--root-element element
+
Indicate that element is the document root. + This information is used to generate the test driver for the + sample implementation.
+ +
--generate-xml-schema
+
Generate a C++ header file as if the schema being compiled defines + the XML Schema namespace. In particular, the resulting file will + have definitions for all serializer skeletons and implementations + corresponding to the XML Schema built-in types. The schema file + provided to the compiler need not exist and is only used to derive + the name of the resulting header file. Use the + --extern-xml-schema option to include this file + in the generated files for other schemas.
+ +
--extern-xml-schema file
+
Include a header file derived from file instead of + generating the XML Schema namespace mapping inline. The provided + file need not exist and is only used to derive the name of the + included header file. Use the --generate-xml-schema + option to generate this header file.
+ +
--skel-type-suffix suffix
+
Use the provided suffix instead of the + default _sskel to construct the names + of generated serializer skeletons.
+ +
--skel-file-suffix suffix
+
Use the provided suffix instead of the + default -sskel to construct the names of + generated serializer skeleton files.
+ +
--impl-type-suffix suffix
+
Use the provided suffix instead of the + default _simpl to construct the names of + serializer implementations for the built-in XML Schema types + and sample serializer implementations.
+ +
--impl-file-suffix suffix
+
Use the provided suffix instead of the + default -simpl to construct the names of + generated sample serializer implementation files.
+
+ + +

TYPE MAP

+ +

Type map files are used to define a mapping between XML Schema + and C++ types. For C++/Parser, the compiler uses + this information to determine the return types of + post_* functions in parser skeletons + corresponding to XML Schema types as well as argument types + for callbacks corresponding to elements and attributes of these + types. For C++/Serializer, type maps are used to determine + the argument type of pre functions in + serializer skeletons corresponding to XML Schema types as + well as return types for callbacks corresponding to elements + and attributes of these types.

+ +

The compiler has a set of predefined mapping rules that map + the built-in XML Schema types to suitable C++ types (discussed + in the following sub-sections) and all other types to + void. By providing your own type maps you + can override these predefined rules. The format of the type map + file is presented below: +

+ +
+namespace <schema-namespace> [<cxx-namespace>]
+{
+  (include <file-name>;)*
+  ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)*
+}
+  
+ +

Both <schema-namespace> and + <schema-type> are regex patterns while + <cxx-namespace>, + <cxx-ret-type>, and + <cxx-arg-type> are regex pattern + substitutions. All names can be optionally enclosed in + " ", for example, to include white-spaces.

+ +

<schema-namespace> determines XML + Schema namespace. Optional <cxx-namespace> + is prefixed to every C++ type name in this namespace declaration. + <cxx-ret-type> is a C++ type name that is + used as a return type for the post_* function + in C++/Parser or for element/attribute callbacks in C++/Serializer. + Optional <cxx-arg-type> is an argument type + for element/attribute callbacks in C++/Parser or for the + pre function in C++/Serializer. If + <cxx-arg-type> is not specified, it defaults + to <cxx-ret-type> if <cxx-ret-type> + ends with * or & (that is, + it is a pointer or a reference) and + const <cxx-ret-type>& + otherwise. + <file-name> is a file name either in the + " " or < > format + and is added with the #include directive to + the generated code.

+ +

The # character starts a comment that ends + with a new line or end of file. To specify a name that contains + # enclose it in " ". + For example:

+ +
+namespace http://www.example.com/xmlns/my my
+{
+  include "my.hxx";
+
+  # Pass apples by value.
+  #
+  apple apple;
+
+  # Pass oranges as pointers.
+  #
+  orange orange_t*;
+}
+  
+ +

In the example above, for the + http://www.example.com/xmlns/my#orange + XML Schema type, the my::orange_t* C++ type will + be used as both return and argument types.

+ +

Several namespace declarations can be specified in a single + file. The namespace declaration can also be completely + omitted to map types in a schema without a namespace. For + instance:

+ +
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+  orange "const orange_t*";
+}
+  
+ +

The compiler has a number of predefined mapping rules + for the built-in XML Schema types that vary depending on + the mapping used. They are described in the following + subsections. The last predefined rule for all mappings + maps anything that wasn't mapped by previous rules to + void:

+ +
+namespace .*
+{
+  .* void void;
+}
+  
+ +

When you provide your own type maps with the + --type-map option, they are evaluated first. + This allows you to selectively override predefined rules.

+ + +

Predefined C++/Parser Type Maps

+ +

The C++/Parser mapping provides a number of predefined type + map rules for the built-in XML Schema types. They can be + presented as the following map files:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  boolean bool bool;
+
+  byte "signed char" "signed char";
+  unsignedByte "unsigned char" "unsigned char";
+
+  short short short;
+  unsignedShort "unsigned short" "unsigned short";
+
+  int int int;
+  unsignedInt "unsigned int" "unsigned int";
+
+  long "long long" "long long";
+  unsignedLong "unsigned long long" "unsigned long long";
+
+  integer long long;
+
+  negativeInteger long long;
+  nonPositiveInteger long long;
+
+  positiveInteger "unsigned long" "unsigned long";
+  nonNegativeInteger "unsigned long" "unsigned long";
+
+  float float float;
+  double double double;
+  decimal double double;
+
+  NMTOKENS xml_schema::string_sequence*;
+  IDREFS xml_schema::string_sequence*;
+
+  base64Binary xml_schema::buffer*;
+  hexBinary xml_schema::buffer*;
+
+  date xml_schema::date;
+  dateTime xml_schema::date_time;
+  duration xml_schema::duration;
+  gDay xml_schema::gday;
+  gMonth xml_schema::gmonth;
+  gMonthDay xml_schema::gmonth_day;
+  gYear xml_schema::gyear;
+  gYearMonth xml_schema::gyear_month;
+  time xml_schema::time;
+}
+  
+ +

If the --no-stl option is not specified, + the following mapping is used for the string-based XML Schema + built-in types:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  include <string>;
+
+  string std::string;
+  normalizedString std::string;
+  token std::string;
+  Name std::string;
+  NMTOKEN std::string;
+  NCName std::string;
+  ID std::string;
+  IDREF std::string;
+  language std::string;
+  anyURI std::string;
+
+  QName xml_schema::qname;
+}
+  
+ +

Otherwise, a C string-based mapping is used:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  string char*;
+  normalizedString char*;
+  token char*;
+  Name char*;
+  NMTOKEN char*;
+  NCName char*;
+  ID char*;
+  IDREF char*;
+  language char*;
+  anyURI char*;
+
+  QName xml_schema::qname*;
+}
+  
+ +

Predefined C++/Serializer Type Maps

+ +

The C++/Serializer mapping provides a number of predefined type + map rules for the built-in XML Schema types. They can be + presented as the following map files:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  boolean bool bool;
+
+  byte "signed char" "signed char";
+  unsignedByte "unsigned char" "unsigned char";
+
+  short short short;
+  unsignedShort "unsigned short" "unsigned short";
+
+  int int int;
+  unsignedInt "unsigned int" "unsigned int";
+
+  long "long long" "long long";
+  unsignedLong "unsigned long long" "unsigned long long";
+
+  integer long long;
+
+  negativeInteger long long;
+  nonPositiveInteger long long;
+
+  positiveInteger "unsigned long" "unsigned long";
+  nonNegativeInteger "unsigned long" "unsigned long";
+
+  float float float;
+  double double double;
+  decimal double double;
+
+  NMTOKENS "const xml_schema::string_sequence*";
+  IDREFS "const xml_schema::string_sequence*";
+
+  base64Binary "const xml_schema::buffer*";
+  hexBinary "const xml_schema::buffer*";
+
+  date xml_schema::date;
+  dateTime xml_schema::date_time;
+  duration xml_schema::duration;
+  gDay xml_schema::gday;
+  gMonth xml_schema::gmonth;
+  gMonthDay xml_schema::gmonth_day;
+  gYear xml_schema::gyear;
+  gYearMonth xml_schema::gyear_month;
+  time xml_schema::time;
+}
+  
+ +

If the --no-stl option is not specified, + the following mapping is used for the string-based XML Schema + built-in types:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  include <string>;
+
+  string std::string;
+  normalizedString std::string;
+  token std::string;
+  Name std::string;
+  NMTOKEN std::string;
+  NCName std::string;
+  ID std::string;
+  IDREF std::string;
+  language std::string;
+  anyURI std::string;
+
+  QName xml_schema::qname;
+}
+  
+ +

Otherwise, a C string-based mapping is used:

+ +
+namespace http://www.w3.org/2001/XMLSchema
+{
+  string "const char*";
+  normalizedString "const char*";
+  token "const char*";
+  Name "const char*";
+  NMTOKEN "const char*";
+  NCName "const char*";
+  ID "const char*";
+  IDREF "const char*";
+  language "const char*";
+  anyURI "const char*";
+
+  QName "const xml_schema::qname*";
+}
+  
+ +

REGEX AND SHELL QUOTING

+ +

When entering a regular expression argument in the shell + command line it is often necessary to use quoting (enclosing + the argument in " " or + ' ') in order to prevent the shell + from interpreting certain characters, for example, spaces as + argument separators and $ as variable + expansions.

+ +

Unfortunately it is hard to achieve this in a manner that is + portable across POSIX shells, such as those found on + GNU/Linux and UNIX, and Windows shell. For example, if you + use " " for quoting you will get a + wrong result with POSIX shells if your expression contains + $. The standard way of dealing with this + on POSIX systems is to use ' ' instead. + Unfortunately, Windows shell does not remove ' ' + from arguments when they are passed to applications. As a result you + may have to use ' ' for POSIX and + " " for Windows ($ is + not treated as a special character on Windows).

+ +

Alternatively, you can save regular expression options into + a file, one option per line, and use this file with the + --options-file option. With this approach + you don't need to worry about shell quoting.

+ +

DIAGNOSTICS

+ +

If the input file is not a valid W3C XML Schema definition, + xsde will issue diagnostic messages to STDERR + and exit with non-zero exit code.

+ +

BUGS

+ +

Send bug reports to the + xsde-users@codesynthesis.com mailing list.

+ +
+ +
+ + 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) diff --git a/examples/makefile b/examples/makefile new file mode 100644 index 0000000..81cba78 --- /dev/null +++ b/examples/makefile @@ -0,0 +1,20 @@ +# file : examples/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 := cxx + +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/libxsde/makefile b/libxsde/makefile new file mode 100644 index 0000000..dc644f3 --- /dev/null +++ b/libxsde/makefile @@ -0,0 +1,26 @@ +# file : libxsde/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 + +default := $(out_base)/ +install := $(out_base)/.install +clean := $(out_base)/.clean + +.PHONY: $(default) $(install) $(clean) + +$(default): $(out_base)/xsde/ +$(clean): $(out_base)/xsde/.clean + +$(install): + $(call install-dir,$(src_base)/xsde,$(install_inc_dir)/xsde) + $(call install-data,$(src_base)/GPLv2,$(install_doc_dir)/libxsde/GPLv2) + $(call install-data,$(src_base)/LICENSE,$(install_doc_dir)/libxsde/LICENSE) + $(call install-data,$(src_base)/README,$(install_doc_dir)/libxsde/README) + + +$(call include,$(bld_root)/install.make) + +$(call import,$(src_base)/xsde/makefile) diff --git a/libxsde/xsde/c/expat/COPYING b/libxsde/xsde/c/expat/COPYING new file mode 100644 index 0000000..dcb4506 --- /dev/null +++ b/libxsde/xsde/c/expat/COPYING @@ -0,0 +1,22 @@ +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + and Clark Cooper +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libxsde/xsde/c/expat/ascii.h b/libxsde/xsde/c/expat/ascii.h new file mode 100644 index 0000000..337e5bb --- /dev/null +++ b/libxsde/xsde/c/expat/ascii.h @@ -0,0 +1,85 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#define ASCII_A 0x41 +#define ASCII_B 0x42 +#define ASCII_C 0x43 +#define ASCII_D 0x44 +#define ASCII_E 0x45 +#define ASCII_F 0x46 +#define ASCII_G 0x47 +#define ASCII_H 0x48 +#define ASCII_I 0x49 +#define ASCII_J 0x4A +#define ASCII_K 0x4B +#define ASCII_L 0x4C +#define ASCII_M 0x4D +#define ASCII_N 0x4E +#define ASCII_O 0x4F +#define ASCII_P 0x50 +#define ASCII_Q 0x51 +#define ASCII_R 0x52 +#define ASCII_S 0x53 +#define ASCII_T 0x54 +#define ASCII_U 0x55 +#define ASCII_V 0x56 +#define ASCII_W 0x57 +#define ASCII_X 0x58 +#define ASCII_Y 0x59 +#define ASCII_Z 0x5A + +#define ASCII_a 0x61 +#define ASCII_b 0x62 +#define ASCII_c 0x63 +#define ASCII_d 0x64 +#define ASCII_e 0x65 +#define ASCII_f 0x66 +#define ASCII_g 0x67 +#define ASCII_h 0x68 +#define ASCII_i 0x69 +#define ASCII_j 0x6A +#define ASCII_k 0x6B +#define ASCII_l 0x6C +#define ASCII_m 0x6D +#define ASCII_n 0x6E +#define ASCII_o 0x6F +#define ASCII_p 0x70 +#define ASCII_q 0x71 +#define ASCII_r 0x72 +#define ASCII_s 0x73 +#define ASCII_t 0x74 +#define ASCII_u 0x75 +#define ASCII_v 0x76 +#define ASCII_w 0x77 +#define ASCII_x 0x78 +#define ASCII_y 0x79 +#define ASCII_z 0x7A + +#define ASCII_0 0x30 +#define ASCII_1 0x31 +#define ASCII_2 0x32 +#define ASCII_3 0x33 +#define ASCII_4 0x34 +#define ASCII_5 0x35 +#define ASCII_6 0x36 +#define ASCII_7 0x37 +#define ASCII_8 0x38 +#define ASCII_9 0x39 + +#define ASCII_TAB 0x09 +#define ASCII_SPACE 0x20 +#define ASCII_EXCL 0x21 +#define ASCII_QUOT 0x22 +#define ASCII_AMP 0x26 +#define ASCII_APOS 0x27 +#define ASCII_MINUS 0x2D +#define ASCII_PERIOD 0x2E +#define ASCII_COLON 0x3A +#define ASCII_SEMI 0x3B +#define ASCII_LT 0x3C +#define ASCII_EQUALS 0x3D +#define ASCII_GT 0x3E +#define ASCII_LSQB 0x5B +#define ASCII_RSQB 0x5D +#define ASCII_UNDERSCORE 0x5F diff --git a/libxsde/xsde/c/expat/asciitab.h b/libxsde/xsde/c/expat/asciitab.h new file mode 100644 index 0000000..79a15c2 --- /dev/null +++ b/libxsde/xsde/c/expat/asciitab.h @@ -0,0 +1,36 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/libxsde/xsde/c/expat/config.h b/libxsde/xsde/c/expat/config.h new file mode 100644 index 0000000..41c8fdf --- /dev/null +++ b/libxsde/xsde/c/expat/config.h @@ -0,0 +1,42 @@ +#ifndef XSDE_C_EXPAT_CONFIG_H +#define XSDE_C_EXPAT_CONFIG_H + +#include + + +#if XSDE_BYTEORDER == 1234 +# define BYTEORDER 1234 +#elif XSDE_BYTEORDER == 4321 +# define BYTEORDER 4321 +#else +# error XSDE_BYTEORDER is not defined or defined to an invalid value +#endif + + +#define XML_NS 1 +#define XML_DTD 1 +#define XML_CONTEXT_BYTES 1024 + +#define UNUSED(x) (void)x; + +/* Windows + * + */ +#if defined(XSDE_PLATFORM_WIN32) || defined (XSDE_PLATFORM_WINCE) + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#define HAVE_MEMMOVE 1 + +#endif /* XSDE_PLATFORM_WIN32 || XSDE_PLATFORM_WINCE */ + +/* POSIX + * + */ +#ifdef XSDE_PLATFORM_POSIX +#define HAVE_MEMMOVE 1 +#endif + +#endif /* XSDE_C_EXPAT_CONFIG_H */ diff --git a/libxsde/xsde/c/expat/expat.h b/libxsde/xsde/c/expat/expat.h new file mode 100644 index 0000000..2dd29ff --- /dev/null +++ b/libxsde/xsde/c/expat/expat.h @@ -0,0 +1,1013 @@ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef Expat_INCLUDED +#define Expat_INCLUDED 1 + +#ifdef __VMS +/* 0 1 2 3 0 1 2 3 + 1234567890123456789012345678901 1234567890123456789012345678901 */ +#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler +#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler +#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler +#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct XML_ParserStruct; +typedef struct XML_ParserStruct *XML_Parser; + +/* Should this be defined using stdbool.h when C99 is available? */ +typedef unsigned char XML_Bool; +#define XML_TRUE ((XML_Bool) 1) +#define XML_FALSE ((XML_Bool) 0) + +/* The XML_Status enum gives the possible return values for several + API functions. The preprocessor #defines are included so this + stanza can be added to code that still needs to support older + versions of Expat 1.95.x: + + #ifndef XML_STATUS_OK + #define XML_STATUS_OK 1 + #define XML_STATUS_ERROR 0 + #endif + + Otherwise, the #define hackery is quite ugly and would have been + dropped. +*/ +enum XML_Status { + XML_STATUS_ERROR = 0, +#define XML_STATUS_ERROR XML_STATUS_ERROR + XML_STATUS_OK = 1, +#define XML_STATUS_OK XML_STATUS_OK + XML_STATUS_SUSPENDED = 2 +#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED +}; + +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE, + XML_ERROR_UNEXPECTED_STATE, + XML_ERROR_ENTITY_DECLARED_IN_PE, + XML_ERROR_FEATURE_REQUIRES_XML_DTD, + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, + /* Added in 1.95.7. */ + XML_ERROR_UNBOUND_PREFIX, + /* Added in 1.95.8. */ + XML_ERROR_UNDECLARING_PREFIX, + XML_ERROR_INCOMPLETE_PE, + XML_ERROR_XML_DECL, + XML_ERROR_TEXT_DECL, + XML_ERROR_PUBLICID, + XML_ERROR_SUSPENDED, + XML_ERROR_NOT_SUSPENDED, + XML_ERROR_ABORTED, + XML_ERROR_FINISHED, + XML_ERROR_SUSPEND_PE, + /* Added in 2.0. */ + XML_ERROR_RESERVED_PREFIX_XML, + XML_ERROR_RESERVED_PREFIX_XMLNS, + XML_ERROR_RESERVED_NAMESPACE_URI +}; + +enum XML_Content_Type { + XML_CTYPE_EMPTY = 1, + XML_CTYPE_ANY, + XML_CTYPE_MIXED, + XML_CTYPE_NAME, + XML_CTYPE_CHOICE, + XML_CTYPE_SEQ +}; + +enum XML_Content_Quant { + XML_CQUANT_NONE, + XML_CQUANT_OPT, + XML_CQUANT_REP, + XML_CQUANT_PLUS +}; + +/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be + XML_CQUANT_NONE, and the other fields will be zero or NULL. + If type == XML_CTYPE_MIXED, then quant will be NONE or REP and + numchildren will contain number of elements that may be mixed in + and children point to an array of XML_Content cells that will be + all of XML_CTYPE_NAME type with no quantification. + + If type == XML_CTYPE_NAME, then the name points to the name, and + the numchildren field will be zero and children will be NULL. The + quant fields indicates any quantifiers placed on the name. + + CHOICE and SEQ will have name NULL, the number of children in + numchildren and children will point, recursively, to an array + of XML_Content cells. + + The EMPTY, ANY, and MIXED types will only occur at top level. +*/ + +typedef struct XML_cp XML_Content; + +struct XML_cp { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + XML_Char * name; + unsigned int numchildren; + XML_Content * children; +}; + + +/* This is called for an element declaration. See above for + description of the model argument. It's the caller's responsibility + to free model when finished with it. +*/ +typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, + const XML_Char *name, + XML_Content *model); + +XMLPARSEAPI(void) +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl); + +/* The Attlist declaration handler is called for *each* attribute. So + a single Attlist declaration with multiple attributes declared will + generate multiple calls to this handler. The "default" parameter + may be NULL in the case of the "#IMPLIED" or "#REQUIRED" + keyword. The "isrequired" parameter will be true and the default + value will be NULL in the case of "#REQUIRED". If "isrequired" is + true and default is non-NULL, then this is a "#FIXED" default. +*/ +typedef void (XMLCALL *XML_AttlistDeclHandler) ( + void *userData, + const XML_Char *elname, + const XML_Char *attname, + const XML_Char *att_type, + const XML_Char *dflt, + int isrequired); + +XMLPARSEAPI(void) +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl); + +/* The XML declaration handler is called for *both* XML declarations + and text declarations. The way to distinguish is that the version + parameter will be NULL for text declarations. The encoding + parameter may be NULL for XML declarations. The standalone + parameter will be -1, 0, or 1 indicating respectively that there + was no standalone parameter in the declaration, that it was given + as no, or that it was given as yes. +*/ +typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData, + const XML_Char *version, + const XML_Char *encoding, + int standalone); + +XMLPARSEAPI(void) +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler xmldecl); + + +typedef struct { + void *(*malloc_fcn)(size_t size); + void *(*realloc_fcn)(void *ptr, size_t size); + void (*free_fcn)(void *ptr); +} XML_Memory_Handling_Suite; + +/* Constructs a new parser; encoding is the encoding specified by the + external protocol or NULL if there is none specified. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate(const XML_Char *encoding); + +/* Constructs a new parser and namespace processor. Element type + names and attribute names that belong to a namespace will be + expanded; unprefixed attribute names are never expanded; unprefixed + element type names are expanded only if there is a default + namespace. The expanded name is the concatenation of the namespace + URI, the namespace separator character, and the local part of the + name. If the namespace separator is '\0' then the namespace URI + and the local part will be concatenated without any separator. + It is a programming error to use the separator '\0' with namespace + triplets (see XML_SetReturnNSTriplet). +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); + + +/* Constructs a new parser using the memory management suite referred to + by memsuite. If memsuite is NULL, then use the standard library memory + suite. If namespaceSeparator is non-NULL it creates a parser with + namespace processing as described above. The character pointed at + will serve as the namespace separator. + + All further memory operations used for the created parser will come from + the given suite. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate_MM(const XML_Char *encoding, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *namespaceSeparator); + +/* Prepare a parser object to be re-used. This is particularly + valuable when memory allocation overhead is disproportionatly high, + such as when a large number of small documnents need to be parsed. + All handlers are cleared from the parser, except for the + unknownEncodingHandler. The parser's external state is re-initialized + except for the values of ns and ns_triplets. + + Added in Expat 1.95.3. +*/ +XMLPARSEAPI(XML_Bool) +XML_ParserReset(XML_Parser parser, const XML_Char *encoding); + +/* atts is array of name/value pairs, terminated by 0; + names and values are 0 terminated. +*/ +typedef void (XMLCALL *XML_StartElementHandler) (void *userData, + const XML_Char *name, + const XML_Char **atts); + +typedef void (XMLCALL *XML_EndElementHandler) (void *userData, + const XML_Char *name); + + +/* s is not 0 terminated. */ +typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData, + const XML_Char *s, + int len); + +/* target and data are 0 terminated */ +typedef void (XMLCALL *XML_ProcessingInstructionHandler) ( + void *userData, + const XML_Char *target, + const XML_Char *data); + +/* data is 0 terminated */ +typedef void (XMLCALL *XML_CommentHandler) (void *userData, + const XML_Char *data); + +typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData); +typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); + +/* This is called for any characters in the XML document for which + there is no applicable handler. This includes both characters that + are part of markup which is of a kind that is not reported + (comments, markup declarations), or characters that are part of a + construct which could be reported but for which no handler has been + supplied. The characters are passed exactly as they were in the XML + document except that they will be encoded in UTF-8 or UTF-16. + Line boundaries are not normalized. Note that a byte order mark + character is not passed to the default handler. There are no + guarantees about how characters are divided between calls to the + default handler: for example, a comment might be split between + multiple calls. +*/ +typedef void (XMLCALL *XML_DefaultHandler) (void *userData, + const XML_Char *s, + int len); + +/* This is called for the start of the DOCTYPE declaration, before + any DTD or internal subset is parsed. +*/ +typedef void (XMLCALL *XML_StartDoctypeDeclHandler) ( + void *userData, + const XML_Char *doctypeName, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset); + +/* This is called for the start of the DOCTYPE declaration when the + closing > is encountered, but after processing any external + subset. +*/ +typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); + +/* This is called for entity declarations. The is_parameter_entity + argument will be non-zero if the entity is a parameter entity, zero + otherwise. + + For internal entities (), value will + be non-NULL and systemId, publicID, and notationName will be NULL. + The value string is NOT nul-terminated; the length is provided in + the value_length argument. Since it is legal to have zero-length + values, do not use this argument to test for internal entities. + + For external entities, value will be NULL and systemId will be + non-NULL. The publicId argument will be NULL unless a public + identifier was provided. The notationName argument will have a + non-NULL value only for unparsed entity declarations. + + Note that is_parameter_entity can't be changed to XML_Bool, since + that would break binary compatibility. +*/ +typedef void (XMLCALL *XML_EntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +XMLPARSEAPI(void) +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler); + +/* OBSOLETE -- OBSOLETE -- OBSOLETE + This handler has been superceded by the EntityDeclHandler above. + It is provided here for backward compatibility. + + This is called for a declaration of an unparsed (NDATA) entity. + The base argument is whatever was set by XML_SetBase. The + entityName, systemId and notationName arguments will never be + NULL. The other arguments may be. +*/ +typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +/* This is called for a declaration of notation. The base argument is + whatever was set by XML_SetBase. The notationName will never be + NULL. The other arguments can be. +*/ +typedef void (XMLCALL *XML_NotationDeclHandler) ( + void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* When namespace processing is enabled, these are called once for + each namespace declaration. The call to the start and end element + handlers occur between the calls to the start and end namespace + declaration handlers. For an xmlns attribute, prefix will be + NULL. For an xmlns="" attribute, uri will be NULL. +*/ +typedef void (XMLCALL *XML_StartNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix, + const XML_Char *uri); + +typedef void (XMLCALL *XML_EndNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix); + +/* This is called if the document is not standalone, that is, it has an + external subset or a reference to a parameter entity, but does not + have standalone="yes". If this handler returns XML_STATUS_ERROR, + then processing will not continue, and the parser will return a + XML_ERROR_NOT_STANDALONE error. + If parameter entity parsing is enabled, then in addition to the + conditions above this handler will only be called if the referenced + entity was actually read. +*/ +typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData); + +/* This is called for a reference to an external parsed general + entity. The referenced entity is not automatically parsed. The + application can parse it immediately or later using + XML_ExternalEntityParserCreate. + + The parser argument is the parser parsing the entity containing the + reference; it can be passed as the parser argument to + XML_ExternalEntityParserCreate. The systemId argument is the + system identifier as specified in the entity declaration; it will + not be NULL. + + The base argument is the system identifier that should be used as + the base for resolving systemId if systemId was relative; this is + set by XML_SetBase; it may be NULL. + + The publicId argument is the public identifier as specified in the + entity declaration, or NULL if none was specified; the whitespace + in the public identifier will have been normalized as required by + the XML spec. + + The context argument specifies the parsing context in the format + expected by the context argument to XML_ExternalEntityParserCreate; + context is valid only until the handler returns, so if the + referenced entity is to be parsed later, it must be copied. + context is NULL only when the entity is a parameter entity. + + The handler should return XML_STATUS_ERROR if processing should not + continue because of a fatal error in the handling of the external + entity. In this case the calling parser will return an + XML_ERROR_EXTERNAL_ENTITY_HANDLING error. + + Note that unlike other handlers the first argument is the parser, + not userData. +*/ +typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( + XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* This is called in two situations: + 1) An entity reference is encountered for which no declaration + has been read *and* this is not an error. + 2) An internal entity reference is read, but not expanded, because + XML_SetDefaultHandler has been called. + Note: skipped parameter entities in declarations and skipped general + entities in attribute values cannot be reported, because + the event would be out of sync with the reporting of the + declarations or attribute values +*/ +typedef void (XMLCALL *XML_SkippedEntityHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity); + +/* This structure is filled in by the XML_UnknownEncodingHandler to + provide information to the parser about encodings that are unknown + to the parser. + + The map[b] member gives information about byte sequences whose + first byte is b. + + If map[b] is c where c is >= 0, then b by itself encodes the + Unicode scalar value c. + + If map[b] is -1, then the byte sequence is malformed. + + If map[b] is -n, where n >= 2, then b is the first byte of an + n-byte sequence that encodes a single Unicode scalar value. + + The data member will be passed as the first argument to the convert + function. + + The convert function is used to convert multibyte sequences; s will + point to a n-byte sequence where map[(unsigned char)*s] == -n. The + convert function must return the Unicode scalar value represented + by this byte sequence or -1 if the byte sequence is malformed. + + The convert function may be NULL if the encoding is a single-byte + encoding, that is if map[b] >= -1 for all bytes b. + + When the parser is finished with the encoding, then if release is + not NULL, it will call release passing it the data member; once + release has been called, the convert function will not be called + again. + + Expat places certain restrictions on the encodings that are supported + using this mechanism. + + 1. Every ASCII character that can appear in a well-formed XML document, + other than the characters + + $@\^`{}~ + + must be represented by a single byte, and that byte must be the + same byte that represents that character in ASCII. + + 2. No character may require more than 4 bytes to encode. + + 3. All characters encoded must have Unicode scalar values <= + 0xFFFF, (i.e., characters that would be encoded by surrogates in + UTF-16 are not allowed). Note that this restriction doesn't + apply to the built-in support for UTF-8 and UTF-16. + + 4. No Unicode character may be encoded by more than one distinct + sequence of bytes. +*/ +typedef struct { + int map[256]; + void *data; + int (XMLCALL *convert)(void *data, const char *s); + void (XMLCALL *release)(void *data); +} XML_Encoding; + +/* This is called for an encoding that is unknown to the parser. + + The encodingHandlerData argument is that which was passed as the + second argument to XML_SetUnknownEncodingHandler. + + The name argument gives the name of the encoding as specified in + the encoding declaration. + + If the callback can provide information about the encoding, it must + fill in the XML_Encoding structure, and return XML_STATUS_OK. + Otherwise it must return XML_STATUS_ERROR. + + If info does not describe a suitable encoding, then the parser will + return an XML_UNKNOWN_ENCODING error. +*/ +typedef int (XMLCALL *XML_UnknownEncodingHandler) ( + void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + +XMLPARSEAPI(void) +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end); + +XMLPARSEAPI(void) +XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler handler); + +XMLPARSEAPI(void) +XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler handler); + +XMLPARSEAPI(void) +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler); + +XMLPARSEAPI(void) +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler); +XMLPARSEAPI(void) +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler); + +XMLPARSEAPI(void) +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end); + +XMLPARSEAPI(void) +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start); + +XMLPARSEAPI(void) +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end); + +/* This sets the default handler and also inhibits expansion of + internal entities. These entity references will be passed to the + default handler, or to the skipped entity handler, if one is set. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler); + +/* This sets the default handler but does not inhibit expansion of + internal entities. The entity reference will not be passed to the + default handler. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler); + +XMLPARSEAPI(void) +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler); + +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler); + +/* If a non-NULL value for arg is specified here, then it will be + passed as the first argument to the external entity ref handler + instead of the parser object. +*/ +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandlerArg(XML_Parser parser, + void *arg); + +XMLPARSEAPI(void) +XML_SetSkippedEntityHandler(XML_Parser parser, + XML_SkippedEntityHandler handler); + +XMLPARSEAPI(void) +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + +/* This can be called within a handler for a start element, end + element, processing instruction or character data. It causes the + corresponding markup to be passed to the default handler. +*/ +XMLPARSEAPI(void) +XML_DefaultCurrent(XML_Parser parser); + +/* If do_nst is non-zero, and namespace processing is in effect, and + a name has a prefix (i.e. an explicit namespace qualifier) then + that name is returned as a triplet in a single string separated by + the separator character specified when the parser was created: URI + + sep + local_name + sep + prefix. + + If do_nst is zero, then namespace information is returned in the + default manner (URI + sep + local_name) whether or not the name + has a prefix. + + Note: Calling XML_SetReturnNSTriplet after XML_Parse or + XML_ParseBuffer has no effect. +*/ + +XMLPARSEAPI(void) +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); + +/* This value is passed as the userData argument to callbacks. */ +XMLPARSEAPI(void) +XML_SetUserData(XML_Parser parser, void *userData); + +/* Returns the last value set by XML_SetUserData or NULL. */ +#define XML_GetUserData(parser) (*(void **)(parser)) + +/* This is equivalent to supplying an encoding argument to + XML_ParserCreate. On success XML_SetEncoding returns non-zero, + zero otherwise. + Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer + has no effect and returns XML_STATUS_ERROR. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); + +/* If this function is called, then the parser will be passed as the + first argument to callbacks instead of userData. The userData will + still be accessible using XML_GetUserData. +*/ +XMLPARSEAPI(void) +XML_UseParserAsHandlerArg(XML_Parser parser); + +/* If useDTD == XML_TRUE is passed to this function, then the parser + will assume that there is an external subset, even if none is + specified in the document. In such a case the parser will call the + externalEntityRefHandler with a value of NULL for the systemId + argument (the publicId and context arguments will be NULL as well). + Note: For the purpose of checking WFC: Entity Declared, passing + useDTD == XML_TRUE will make the parser behave as if the document + had a DTD with an external subset. + Note: If this function is called, then this must be done before + the first call to XML_Parse or XML_ParseBuffer, since it will + have no effect after that. Returns + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. + Note: If the document does not have a DOCTYPE declaration at all, + then startDoctypeDeclHandler and endDoctypeDeclHandler will not + be called, despite an external subset being parsed. + Note: If XML_DTD is not defined when Expat is compiled, returns + XML_ERROR_FEATURE_REQUIRES_XML_DTD. +*/ +XMLPARSEAPI(enum XML_Error) +XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); + + +/* Sets the base to be used for resolving relative URIs in system + identifiers in declarations. Resolving relative identifiers is + left to the application: this value will be passed through as the + base argument to the XML_ExternalEntityRefHandler, + XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base + argument will be copied. Returns XML_STATUS_ERROR if out of memory, + XML_STATUS_OK otherwise. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetBase(XML_Parser parser, const XML_Char *base); + +XMLPARSEAPI(const XML_Char *) +XML_GetBase(XML_Parser parser); + +/* Returns the number of the attribute/value pairs passed in last call + to the XML_StartElementHandler that were specified in the start-tag + rather than defaulted. Each attribute/value pair counts as 2; thus + this correspondds to an index into the atts array passed to the + XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetSpecifiedAttributeCount(XML_Parser parser); + +/* Returns the index of the ID attribute passed in the last call to + XML_StartElementHandler, or -1 if there is no ID attribute. Each + attribute/value pair counts as 2; thus this correspondds to an + index into the atts array passed to the XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetIdAttributeIndex(XML_Parser parser); + +/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is + detected. The last call to XML_Parse must have isFinal true; len + may be zero for this call (or any other). + + Though the return values for these functions has always been + described as a Boolean value, the implementation, at least for the + 1.95.x series, has always returned exactly one of the XML_Status + values. +*/ +XMLPARSEAPI(enum XML_Status) +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); + +XMLPARSEAPI(void *) +XML_GetBuffer(XML_Parser parser, int len); + +XMLPARSEAPI(enum XML_Status) +XML_ParseBuffer(XML_Parser parser, int len, int isFinal); + +/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return. + Must be called from within a call-back handler, except when aborting + (resumable = 0) an already suspended parser. Some call-backs may + still follow because they would otherwise get lost. Examples: + - endElementHandler() for empty elements when stopped in + startElementHandler(), + - endNameSpaceDeclHandler() when stopped in endElementHandler(), + and possibly others. + + Can be called from most handlers, including DTD related call-backs, + except when parsing an external parameter entity and resumable != 0. + Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. + Possible error codes: + - XML_ERROR_SUSPENDED: when suspending an already suspended parser. + - XML_ERROR_FINISHED: when the parser has already finished. + - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. + + When resumable != 0 (true) then parsing is suspended, that is, + XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. + Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() + return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. + + *Note*: + This will be applied to the current parser instance only, that is, if + there is a parent parser then it will continue parsing when the + externalEntityRefHandler() returns. It is up to the implementation of + the externalEntityRefHandler() to call XML_StopParser() on the parent + parser (recursively), if one wants to stop parsing altogether. + + When suspended, parsing can be resumed by calling XML_ResumeParser(). +*/ +XMLPARSEAPI(enum XML_Status) +XML_StopParser(XML_Parser parser, XML_Bool resumable); + +/* Resumes parsing after it has been suspended with XML_StopParser(). + Must not be called from within a handler call-back. Returns same + status codes as XML_Parse() or XML_ParseBuffer(). + Additional error code XML_ERROR_NOT_SUSPENDED possible. + + *Note*: + This must be called on the most deeply nested child parser instance + first, and on its parent parser only after the child parser has finished, + to be applied recursively until the document entity's parser is restarted. + That is, the parent parser will not resume by itself and it is up to the + application to call XML_ResumeParser() on it at the appropriate moment. +*/ +XMLPARSEAPI(enum XML_Status) +XML_ResumeParser(XML_Parser parser); + +enum XML_Parsing { + XML_INITIALIZED, + XML_PARSING, + XML_FINISHED, + XML_SUSPENDED +}; + +typedef struct { + enum XML_Parsing parsing; + XML_Bool finalBuffer; +} XML_ParsingStatus; + +/* Returns status of parser with respect to being initialized, parsing, + finished, or suspended and processing the final buffer. + XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus, + XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED +*/ +XMLPARSEAPI(void) +XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status); + +/* Creates an XML_Parser object that can parse an external general + entity; context is a '\0'-terminated string specifying the parse + context; encoding is a '\0'-terminated string giving the name of + the externally specified encoding, or NULL if there is no + externally specified encoding. The context string consists of a + sequence of tokens separated by formfeeds (\f); a token consisting + of a name specifies that the general entity of the name is open; a + token of the form prefix=uri specifies the namespace for a + particular prefix; a token of the form =uri specifies the default + namespace. This can be called at any point after the first call to + an ExternalEntityRefHandler so longer as the parser has not yet + been freed. The new parser is completely independent and may + safely be used in a separate thread. The handlers and userData are + initialized from the parser argument. Returns NULL if out of memory. + Otherwise returns a new XML_Parser object. +*/ +XMLPARSEAPI(XML_Parser) +XML_ExternalEntityParserCreate(XML_Parser parser, + const XML_Char *context, + const XML_Char *encoding); + +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS +}; + +/* Controls parsing of parameter entities (including the external DTD + subset). If parsing of parameter entities is enabled, then + references to external parameter entities (including the external + DTD subset) will be passed to the handler set with + XML_SetExternalEntityRefHandler. The context passed will be 0. + + Unlike external general entities, external parameter entities can + only be parsed synchronously. If the external parameter entity is + to be parsed, it must be parsed during the call to the external + entity ref handler: the complete sequence of + XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and + XML_ParserFree calls must be made during this call. After + XML_ExternalEntityParserCreate has been called to create the parser + for the external parameter entity (context must be 0 for this + call), it is illegal to make any calls on the old parser until + XML_ParserFree has been called on the newly created parser. + If the library has been compiled without support for parameter + entity parsing (ie without XML_DTD being defined), then + XML_SetParamEntityParsing will return 0 if parsing of parameter + entities is requested; otherwise it will return non-zero. + Note: If XML_SetParamEntityParsing is called after XML_Parse or + XML_ParseBuffer, then it has no effect and will always return 0. +*/ +XMLPARSEAPI(int) +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing); + +/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then + XML_GetErrorCode returns information about the error. +*/ +XMLPARSEAPI(enum XML_Error) +XML_GetErrorCode(XML_Parser parser); + +/* These functions return information about the current parse + location. They may be called from any callback called to report + some parse event; in this case the location is the location of the + first of the sequence of characters that generated the event. When + called from callbacks generated by declarations in the document + prologue, the location identified isn't as neatly defined, but will + be within the relevant markup. When called outside of the callback + functions, the position indicated will be just past the last parse + event (regardless of whether there was an associated callback). + + They may also be called after returning from a call to XML_Parse + or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then + the location is the location of the character at which the error + was detected; otherwise the location is the location of the last + parse event, as described above. +*/ +XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser); +XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser); +XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser); + +/* Return the number of bytes in the current event. + Returns 0 if the event is in an internal entity. +*/ +XMLPARSEAPI(int) +XML_GetCurrentByteCount(XML_Parser parser); + +/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets + the integer pointed to by offset to the offset within this buffer + of the current parse position, and sets the integer pointed to by size + to the size of this buffer (the number of input bytes). Otherwise + returns a NULL pointer. Also returns a NULL pointer if a parse isn't + active. + + NOTE: The character pointer returned should not be used outside + the handler that makes the call. +*/ +XMLPARSEAPI(const char *) +XML_GetInputContext(XML_Parser parser, + int *offset, + int *size); + +/* For backwards compatibility with previous versions. */ +#define XML_GetErrorLineNumber XML_GetCurrentLineNumber +#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +#define XML_GetErrorByteIndex XML_GetCurrentByteIndex + +/* Frees the content model passed to the element declaration handler */ +XMLPARSEAPI(void) +XML_FreeContentModel(XML_Parser parser, XML_Content *model); + +/* Exposing the memory handling functions used in Expat */ +XMLPARSEAPI(void *) +XML_MemMalloc(XML_Parser parser, size_t size); + +XMLPARSEAPI(void *) +XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); + +XMLPARSEAPI(void) +XML_MemFree(XML_Parser parser, void *ptr); + +/* Frees memory used by the parser. */ +XMLPARSEAPI(void) +XML_ParserFree(XML_Parser parser); + +/* Returns a string describing the error. */ +XMLPARSEAPI(const XML_LChar *) +XML_ErrorString(enum XML_Error code); + +/* Return a string containing the version number of this expat */ +XMLPARSEAPI(const XML_LChar *) +XML_ExpatVersion(void); + +typedef struct { + int major; + int minor; + int micro; +} XML_Expat_Version; + +/* Return an XML_Expat_Version structure containing numeric version + number information for this version of expat. +*/ +XMLPARSEAPI(XML_Expat_Version) +XML_ExpatVersionInfo(void); + +/* Added in Expat 1.95.5. */ +enum XML_FeatureEnum { + XML_FEATURE_END = 0, + XML_FEATURE_UNICODE, + XML_FEATURE_UNICODE_WCHAR_T, + XML_FEATURE_DTD, + XML_FEATURE_CONTEXT_BYTES, + XML_FEATURE_MIN_SIZE, + XML_FEATURE_SIZEOF_XML_CHAR, + XML_FEATURE_SIZEOF_XML_LCHAR, + XML_FEATURE_NS + /* Additional features must be added to the end of this enum. */ +}; + +typedef struct { + enum XML_FeatureEnum feature; + const XML_LChar *name; + long int value; +} XML_Feature; + +XMLPARSEAPI(const XML_Feature *) +XML_GetFeatureList(void); + + +/* Expat follows the GNU/Linux convention of odd number minor version for + beta/development releases and even number minor version for stable + releases. Micro is bumped with each release, and set to 0 with each + change to major or minor version. +*/ +#define XML_MAJOR_VERSION 2 +#define XML_MINOR_VERSION 0 +#define XML_MICRO_VERSION 0 + +#ifdef __cplusplus +} +#endif + +#endif /* not Expat_INCLUDED */ diff --git a/libxsde/xsde/c/expat/expat_external.h b/libxsde/xsde/c/expat/expat_external.h new file mode 100644 index 0000000..ea2279e --- /dev/null +++ b/libxsde/xsde/c/expat/expat_external.h @@ -0,0 +1,119 @@ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef Expat_External_INCLUDED +#define Expat_External_INCLUDED 1 + +/* Link to Expat API statically */ + +#define XML_STATIC 1 + +/* External API definitions */ + +#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) +#define XML_USE_MSC_EXTENSIONS 1 +#endif + +/* Expat tries very hard to make the API boundary very specifically + defined. There are two macros defined to control this boundary; + each of these can be defined before including this header to + achieve some different behavior, but doing so it not recommended or + tested frequently. + + XMLCALL - The calling convention to use for all calls across the + "library boundary." This will default to cdecl, and + try really hard to tell the compiler that's what we + want. + + XMLIMPORT - Whatever magic is needed to note that a function is + to be imported from a dynamically loaded library + (.dll, .so, or .sl, depending on your platform). + + The XMLCALL macro was added in Expat 1.95.7. The only one which is + expected to be directly useful in client code is XMLCALL. + + Note that on at least some Unix versions, the Expat library must be + compiled with the cdecl calling convention as the default since + system headers may assume the cdecl convention. +*/ +#ifndef XMLCALL +#if defined(XML_USE_MSC_EXTENSIONS) +#define XMLCALL __cdecl +#elif defined(__GNUC__) && defined(__i386) +#define XMLCALL __attribute__((cdecl)) +#else +/* For any platform which uses this definition and supports more than + one calling convention, we need to extend this definition to + declare the convention used on that platform, if it's possible to + do so. + + If this is the case for your platform, please file a bug report + with information on how to identify your platform via the C + pre-processor and how to specify the same calling convention as the + platform's malloc() implementation. +*/ +#define XMLCALL +#endif +#endif /* not defined XMLCALL */ + + +#if !defined(XML_STATIC) && !defined(XMLIMPORT) +#ifndef XML_BUILDING_EXPAT +/* using Expat from an application */ + +#ifdef XML_USE_MSC_EXTENSIONS +#define XMLIMPORT __declspec(dllimport) +#endif + +#endif +#endif /* not defined XML_STATIC */ + + +/* If we didn't define it above, define it away: */ +#ifndef XMLIMPORT +#define XMLIMPORT +#endif + + +#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef XML_UNICODE_WCHAR_T +#define XML_UNICODE +#endif + +#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ +#ifdef XML_UNICODE_WCHAR_T +typedef wchar_t XML_Char; +typedef wchar_t XML_LChar; +#else +typedef unsigned short XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE_WCHAR_T */ +#else /* Information is UTF-8 encoded. */ +typedef char XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE */ + +#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ +#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 +typedef __int64 XML_Index; +typedef unsigned __int64 XML_Size; +#else +typedef long long XML_Index; +typedef unsigned long long XML_Size; +#endif +#else +typedef long XML_Index; +typedef unsigned long XML_Size; +#endif /* XML_LARGE_SIZE */ + +#ifdef __cplusplus +} +#endif + +#endif /* not Expat_External_INCLUDED */ diff --git a/libxsde/xsde/c/expat/iasciitab.h b/libxsde/xsde/c/expat/iasciitab.h new file mode 100644 index 0000000..24a1d5c --- /dev/null +++ b/libxsde/xsde/c/expat/iasciitab.h @@ -0,0 +1,37 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/libxsde/xsde/c/expat/internal.h b/libxsde/xsde/c/expat/internal.h new file mode 100644 index 0000000..ff056c6 --- /dev/null +++ b/libxsde/xsde/c/expat/internal.h @@ -0,0 +1,73 @@ +/* internal.h + + Internal definitions used by Expat. This is not needed to compile + client code. + + The following calling convention macros are defined for frequently + called functions: + + FASTCALL - Used for those internal functions that have a simple + body and a low number of arguments and local variables. + + PTRCALL - Used for functions called though function pointers. + + PTRFASTCALL - Like PTRCALL, but for low number of arguments. + + inline - Used for selected internal functions for which inlining + may improve performance on some platforms. + + Note: Use of these macros is based on judgement, not hard rules, + and therefore subject to change. +*/ + +#if defined(__GNUC__) && defined(__i386__) +/* We'll use this version by default only where we know it helps. + + regparm() generates warnings on Solaris boxes. See SF bug #692878. + + Instability reported with egcs on a RedHat Linux 7.3. + Let's comment out: + #define FASTCALL __attribute__((stdcall, regparm(3))) + and let's try this: +*/ +#define FASTCALL __attribute__((regparm(3))) +#define PTRFASTCALL __attribute__((regparm(3))) +#endif + +/* Using __fastcall seems to have an unexpected negative effect under + MS VC++, especially for function pointers, so we won't use it for + now on that platform. It may be reconsidered for a future release + if it can be made more effective. + Likely reason: __fastcall on Windows is like stdcall, therefore + the compiler cannot perform stack optimizations for call clusters. +*/ + +/* Make sure all of these are defined if they aren't already. */ + +#ifndef FASTCALL +#define FASTCALL +#endif + +#ifndef PTRCALL +#define PTRCALL +#endif + +#ifndef PTRFASTCALL +#define PTRFASTCALL +#endif + +#ifndef XML_MIN_SIZE +#if !defined(__cplusplus) && !defined(inline) +#ifdef __GNUC__ +#define inline __inline +#endif /* __GNUC__ */ +#endif +#endif /* XML_MIN_SIZE */ + +#ifdef __cplusplus +#define inline inline +#else +#ifndef inline +#define inline +#endif +#endif diff --git a/libxsde/xsde/c/expat/latin1tab.h b/libxsde/xsde/c/expat/latin1tab.h new file mode 100644 index 0000000..53c25d7 --- /dev/null +++ b/libxsde/xsde/c/expat/latin1tab.h @@ -0,0 +1,36 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, +/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, diff --git a/libxsde/xsde/c/expat/nametab.h b/libxsde/xsde/c/expat/nametab.h new file mode 100644 index 0000000..b05e62c --- /dev/null +++ b/libxsde/xsde/c/expat/nametab.h @@ -0,0 +1,150 @@ +static const unsigned namingBitmap[] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, +0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, +0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, +0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, +0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, +0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, +0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, +0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, +0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, +0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, +0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, +0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, +0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, +0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, +0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, +0x40000000, 0xF580C900, 0x00000007, 0x02010800, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, +0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, +0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, +0x00000000, 0x00004C40, 0x00000000, 0x00000000, +0x00000007, 0x00000000, 0x00000000, 0x00000000, +0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, +0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, +0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, +0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, +0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, +0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, +0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, +0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, +0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, +0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, +0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, +0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, +0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, +0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, +0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, +0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, +0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, +0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, +}; +static const unsigned char nmstrtPages[] = { +0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, +0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const unsigned char namePages[] = { +0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, +0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/libxsde/xsde/c/expat/utf8tab.h b/libxsde/xsde/c/expat/utf8tab.h new file mode 100644 index 0000000..7bb3e77 --- /dev/null +++ b/libxsde/xsde/c/expat/utf8tab.h @@ -0,0 +1,37 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + + +/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, +/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, diff --git a/libxsde/xsde/c/expat/xmlparse.c b/libxsde/xsde/c/expat/xmlparse.c new file mode 100644 index 0000000..6eac810 --- /dev/null +++ b/libxsde/xsde/c/expat/xmlparse.c @@ -0,0 +1,6260 @@ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#include +#include /* memset(), memcpy() */ +#include + +#define XML_BUILDING_EXPAT 1 + +#include "config.h" + +#include "expat.h" + +#ifdef XML_UNICODE +#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX +#define XmlConvert XmlUtf16Convert +#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS +#define XmlEncode XmlUtf16Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) +typedef unsigned short ICHAR; +#else +#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX +#define XmlConvert XmlUtf8Convert +#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS +#define XmlEncode XmlUtf8Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) +typedef char ICHAR; +#endif + + +#ifndef XML_NS + +#define XmlInitEncodingNS XmlInitEncoding +#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding +#undef XmlGetInternalEncodingNS +#define XmlGetInternalEncodingNS XmlGetInternalEncoding +#define XmlParseXmlDeclNS XmlParseXmlDecl + +#endif + +#ifdef XML_UNICODE + +#ifdef XML_UNICODE_WCHAR_T +#define XML_T(x) (const wchar_t)x +#define XML_L(x) L ## x +#else +#define XML_T(x) (const unsigned short)x +#define XML_L(x) x +#endif + +#else + +#define XML_T(x) x +#define XML_L(x) x + +#endif + +/* Round up n to be a multiple of sz, where sz is a power of 2. */ +#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) + +/* Handle the case where memmove() doesn't exist. */ +#ifndef HAVE_MEMMOVE +#ifdef HAVE_BCOPY +#define memmove(d,s,l) bcopy((s),(d),(l)) +#else +#error memmove does not exist on this platform, nor is a substitute available +#endif /* HAVE_BCOPY */ +#endif /* HAVE_MEMMOVE */ + +#include "internal.h" +#include "xmltok.h" +#include "xmlrole.h" + +typedef const XML_Char *KEY; + +typedef struct { + KEY name; +} NAMED; + +typedef struct { + NAMED **v; + unsigned char power; + size_t size; + size_t used; + const XML_Memory_Handling_Suite *mem; +} HASH_TABLE; + +/* Basic character hash algorithm, taken from Python's string hash: + h = h * 1000003 ^ character, the constant being a prime number. + +*/ +#ifdef XML_UNICODE +#define CHAR_HASH(h, c) \ + (((h) * 0xF4243) ^ (unsigned short)(c)) +#else +#define CHAR_HASH(h, c) \ + (((h) * 0xF4243) ^ (unsigned char)(c)) +#endif + +/* For probing (after a collision) we need a step size relative prime + to the hash table size, which is a power of 2. We use double-hashing, + since we can calculate a second hash value cheaply by taking those bits + of the first hash value that were discarded (masked out) when the table + index was calculated: index = hash & mask, where mask = table->size - 1. + We limit the maximum step size to table->size / 4 (mask >> 2) and make + it odd, since odd numbers are always relative prime to a power of 2. +*/ +#define SECOND_HASH(hash, mask, power) \ + ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2)) +#define PROBE_STEP(hash, mask, power) \ + ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) + +typedef struct { + NAMED **p; + NAMED **end; +} HASH_TABLE_ITER; + +#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ +#define INIT_DATA_BUF_SIZE 1024 +#define INIT_ATTS_SIZE 16 +#define INIT_ATTS_VERSION 0xFFFFFFFF +#define INIT_BLOCK_SIZE 1024 +#define INIT_BUFFER_SIZE 1024 + +#define EXPAND_SPARE 24 + +typedef struct binding { + struct prefix *prefix; + struct binding *nextTagBinding; + struct binding *prevPrefixBinding; + const struct attribute_id *attId; + XML_Char *uri; + int uriLen; + int uriAlloc; +} BINDING; + +typedef struct prefix { + const XML_Char *name; + BINDING *binding; +} PREFIX; + +typedef struct { + const XML_Char *str; + const XML_Char *localPart; + const XML_Char *prefix; + int strLen; + int uriLen; + int prefixLen; +} TAG_NAME; + +/* TAG represents an open element. + The name of the element is stored in both the document and API + encodings. The memory buffer 'buf' is a separately-allocated + memory area which stores the name. During the XML_Parse()/ + XMLParseBuffer() when the element is open, the memory for the 'raw' + version of the name (in the document encoding) is shared with the + document buffer. If the element is open across calls to + XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to + contain the 'raw' name as well. + + A parser re-uses these structures, maintaining a list of allocated + TAG objects in a free list. +*/ +typedef struct tag { + struct tag *parent; /* parent of this element */ + const char *rawName; /* tagName in the original encoding */ + int rawNameLength; + TAG_NAME name; /* tagName in the API encoding */ + char *buf; /* buffer for name components */ + char *bufEnd; /* end of the buffer */ + BINDING *bindings; +} TAG; + +typedef struct { + const XML_Char *name; + const XML_Char *textPtr; + int textLen; /* length in XML_Chars */ + int processed; /* # of processed bytes - when suspended */ + const XML_Char *systemId; + const XML_Char *base; + const XML_Char *publicId; + const XML_Char *notation; + XML_Bool open; + XML_Bool is_param; + XML_Bool is_internal; /* true if declared in internal subset outside PE */ +} ENTITY; + +typedef struct { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + const XML_Char * name; + int firstchild; + int lastchild; + int childcnt; + int nextsib; +} CONTENT_SCAFFOLD; + +#define INIT_SCAFFOLD_ELEMENTS 32 + +typedef struct block { + struct block *next; + int size; + XML_Char s[1]; +} BLOCK; + +typedef struct { + BLOCK *blocks; + BLOCK *freeBlocks; + const XML_Char *end; + XML_Char *ptr; + XML_Char *start; + const XML_Memory_Handling_Suite *mem; +} STRING_POOL; + +/* The XML_Char before the name is used to determine whether + an attribute has been specified. */ +typedef struct attribute_id { + XML_Char *name; + PREFIX *prefix; + XML_Bool maybeTokenized; + XML_Bool xmlns; +} ATTRIBUTE_ID; + +typedef struct { + const ATTRIBUTE_ID *id; + XML_Bool isCdata; + const XML_Char *value; +} DEFAULT_ATTRIBUTE; + +typedef struct { + unsigned long version; + unsigned long hash; + const XML_Char *uriName; +} NS_ATT; + +typedef struct { + const XML_Char *name; + PREFIX *prefix; + const ATTRIBUTE_ID *idAtt; + int nDefaultAtts; + int allocDefaultAtts; + DEFAULT_ATTRIBUTE *defaultAtts; +} ELEMENT_TYPE; + +typedef struct { + HASH_TABLE generalEntities; + HASH_TABLE elementTypes; + HASH_TABLE attributeIds; + HASH_TABLE prefixes; + STRING_POOL pool; + STRING_POOL entityValuePool; + /* false once a parameter entity reference has been skipped */ + XML_Bool keepProcessing; + /* true once an internal or external PE reference has been encountered; + this includes the reference to an external subset */ + XML_Bool hasParamEntityRefs; + XML_Bool standalone; +#ifdef XML_DTD + /* indicates if external PE has been read */ + XML_Bool paramEntityRead; + HASH_TABLE paramEntities; +#endif /* XML_DTD */ + PREFIX defaultPrefix; + /* === scaffolding for building content model === */ + XML_Bool in_eldecl; + CONTENT_SCAFFOLD *scaffold; + unsigned contentStringLen; + unsigned scaffSize; + unsigned scaffCount; + int scaffLevel; + int *scaffIndex; +} DTD; + +typedef struct open_internal_entity { + const char *internalEventPtr; + const char *internalEventEndPtr; + struct open_internal_entity *next; + ENTITY *entity; + int startTagLevel; + XML_Bool betweenDecl; /* WFC: PE Between Declarations */ +} OPEN_INTERNAL_ENTITY; + +typedef enum XML_Error PTRCALL Processor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr); + +static Processor prologProcessor; +static Processor prologInitProcessor; +static Processor contentProcessor; +static Processor cdataSectionProcessor; +#ifdef XML_DTD +static Processor ignoreSectionProcessor; +static Processor externalParEntProcessor; +static Processor externalParEntInitProcessor; +static Processor entityValueProcessor; +static Processor entityValueInitProcessor; +#endif /* XML_DTD */ +static Processor epilogProcessor; +static Processor errorProcessor; +static Processor externalEntityInitProcessor; +static Processor externalEntityInitProcessor2; +static Processor externalEntityInitProcessor3; +static Processor externalEntityContentProcessor; +static Processor internalEntityProcessor; + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, + const char *s, const char *next); +static enum XML_Error +initializeEncoding(XML_Parser parser); +static enum XML_Error +doProlog(XML_Parser parser, const ENCODING *enc, const char *s, + const char *end, int tok, const char *next, const char **nextPtr, + XML_Bool haveMore); +static enum XML_Error +processInternalEntity(XML_Parser parser, ENTITY *entity, + XML_Bool betweenDecl); +static enum XML_Error +doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, + const char *start, const char *end, const char **endPtr, + XML_Bool haveMore); +static enum XML_Error +doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, + const char *end, const char **nextPtr, XML_Bool haveMore); +#ifdef XML_DTD +static enum XML_Error +doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, + const char *end, const char **nextPtr, XML_Bool haveMore); +#endif /* XML_DTD */ + +static enum XML_Error +storeAtts(XML_Parser parser, const ENCODING *, const char *s, + TAG_NAME *tagNamePtr, BINDING **bindingsPtr); +static enum XML_Error +addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + const XML_Char *uri, BINDING **bindingsPtr); +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, + XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser); +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, + const char *, const char *, STRING_POOL *); +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata, + const char *, const char *, STRING_POOL *); +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static int +setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); +static enum XML_Error +storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end); +static int +reportComment(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); +static void +reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, + const char *end); + +static const XML_Char * getContext(XML_Parser parser); +static XML_Bool +setContext(XML_Parser parser, const XML_Char *context); + +static void FASTCALL normalizePublicId(XML_Char *s); + +static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms); +/* do not call if parentParser != NULL */ +static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); +static void +dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); +static int +dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); +static int +copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); + +static NAMED * +lookup(HASH_TABLE *table, KEY name, size_t createSize); +static void FASTCALL +hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); +static void FASTCALL hashTableClear(HASH_TABLE *); +static void FASTCALL hashTableDestroy(HASH_TABLE *); +static void FASTCALL +hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); +static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *); + +static void FASTCALL +poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms); +static void FASTCALL poolClear(STRING_POOL *); +static void FASTCALL poolDestroy(STRING_POOL *); +static XML_Char * +poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); +static XML_Char * +poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); +static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); +static const XML_Char * FASTCALL +poolCopyString(STRING_POOL *pool, const XML_Char *s); +static const XML_Char * +poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); +static const XML_Char * FASTCALL +poolAppendString(STRING_POOL *pool, const XML_Char *s); + +static int FASTCALL nextScaffoldPart(XML_Parser parser); +static XML_Content * build_model(XML_Parser parser); +static ELEMENT_TYPE * +getElementType(XML_Parser parser, const ENCODING *enc, + const char *ptr, const char *end); + +static XML_Parser +parserCreate(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep, + DTD *dtd); +static void +parserInit(XML_Parser parser, const XML_Char *encodingName); + +#define poolStart(pool) ((pool)->start) +#define poolEnd(pool) ((pool)->ptr) +#define poolLength(pool) ((pool)->ptr - (pool)->start) +#define poolChop(pool) ((void)--(pool->ptr)) +#define poolLastChar(pool) (((pool)->ptr)[-1]) +#define poolDiscard(pool) ((pool)->ptr = (pool)->start) +#define poolFinish(pool) ((pool)->start = (pool)->ptr) +#define poolAppendChar(pool, c) \ + (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ + ? 0 \ + : ((*((pool)->ptr)++ = c), 1)) + +struct XML_ParserStruct { + /* The first member must be userData so that the XML_GetUserData + macro works. */ + void *m_userData; + void *m_handlerArg; + char *m_buffer; + const XML_Memory_Handling_Suite m_mem; + /* first character to be parsed */ + const char *m_bufferPtr; + /* past last character to be parsed */ + char *m_bufferEnd; + /* allocated end of buffer */ + const char *m_bufferLim; + XML_Index m_parseEndByteIndex; + const char *m_parseEndPtr; + XML_Char *m_dataBuf; + XML_Char *m_dataBufEnd; + XML_StartElementHandler m_startElementHandler; + XML_EndElementHandler m_endElementHandler; + XML_CharacterDataHandler m_characterDataHandler; + XML_ProcessingInstructionHandler m_processingInstructionHandler; + XML_CommentHandler m_commentHandler; + XML_StartCdataSectionHandler m_startCdataSectionHandler; + XML_EndCdataSectionHandler m_endCdataSectionHandler; + XML_DefaultHandler m_defaultHandler; + XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; + XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; + XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; + XML_NotationDeclHandler m_notationDeclHandler; + XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; + XML_NotStandaloneHandler m_notStandaloneHandler; + XML_ExternalEntityRefHandler m_externalEntityRefHandler; + XML_Parser m_externalEntityRefHandlerArg; + XML_SkippedEntityHandler m_skippedEntityHandler; + XML_UnknownEncodingHandler m_unknownEncodingHandler; + XML_ElementDeclHandler m_elementDeclHandler; + XML_AttlistDeclHandler m_attlistDeclHandler; + XML_EntityDeclHandler m_entityDeclHandler; + XML_XmlDeclHandler m_xmlDeclHandler; + const ENCODING *m_encoding; + INIT_ENCODING m_initEncoding; + const ENCODING *m_internalEncoding; + const XML_Char *m_protocolEncodingName; + XML_Bool m_ns; + XML_Bool m_ns_triplets; + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; + void (XMLCALL *m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; + enum XML_Error m_errorCode; + const char *m_eventPtr; + const char *m_eventEndPtr; + const char *m_positionPtr; + OPEN_INTERNAL_ENTITY *m_openInternalEntities; + OPEN_INTERNAL_ENTITY *m_freeInternalEntities; + XML_Bool m_defaultExpandInternalEntities; + int m_tagLevel; + ENTITY *m_declEntity; + const XML_Char *m_doctypeName; + const XML_Char *m_doctypeSysid; + const XML_Char *m_doctypePubid; + const XML_Char *m_declAttributeType; + const XML_Char *m_declNotationName; + const XML_Char *m_declNotationPublicId; + ELEMENT_TYPE *m_declElementType; + ATTRIBUTE_ID *m_declAttributeId; + XML_Bool m_declAttributeIsCdata; + XML_Bool m_declAttributeIsId; + DTD *m_dtd; + const XML_Char *m_curBase; + TAG *m_tagStack; + TAG *m_freeTagList; + BINDING *m_inheritedBindings; + BINDING *m_freeBindingList; + int m_attsSize; + int m_nSpecifiedAtts; + int m_idAttIndex; + ATTRIBUTE *m_atts; + NS_ATT *m_nsAtts; + unsigned long m_nsAttsVersion; + unsigned char m_nsAttsPower; + POSITION m_position; + STRING_POOL m_tempPool; + STRING_POOL m_temp2Pool; + char *m_groupConnector; + unsigned int m_groupSize; + XML_Char m_namespaceSeparator; + XML_Parser m_parentParser; + XML_ParsingStatus m_parsingStatus; +#ifdef XML_DTD + XML_Bool m_isParamEntity; + XML_Bool m_useForeignDTD; + enum XML_ParamEntityParsing m_paramEntityParsing; +#endif +}; + +#define MALLOC(s) (parser->m_mem.malloc_fcn((s))) +#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s))) +#define FREE(p) (parser->m_mem.free_fcn((p))) + +#define userData (parser->m_userData) +#define handlerArg (parser->m_handlerArg) +#define startElementHandler (parser->m_startElementHandler) +#define endElementHandler (parser->m_endElementHandler) +#define characterDataHandler (parser->m_characterDataHandler) +#define processingInstructionHandler \ + (parser->m_processingInstructionHandler) +#define commentHandler (parser->m_commentHandler) +#define startCdataSectionHandler \ + (parser->m_startCdataSectionHandler) +#define endCdataSectionHandler (parser->m_endCdataSectionHandler) +#define defaultHandler (parser->m_defaultHandler) +#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler) +#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler) +#define unparsedEntityDeclHandler \ + (parser->m_unparsedEntityDeclHandler) +#define notationDeclHandler (parser->m_notationDeclHandler) +#define startNamespaceDeclHandler \ + (parser->m_startNamespaceDeclHandler) +#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler) +#define notStandaloneHandler (parser->m_notStandaloneHandler) +#define externalEntityRefHandler \ + (parser->m_externalEntityRefHandler) +#define externalEntityRefHandlerArg \ + (parser->m_externalEntityRefHandlerArg) +#define internalEntityRefHandler \ + (parser->m_internalEntityRefHandler) +#define skippedEntityHandler (parser->m_skippedEntityHandler) +#define unknownEncodingHandler (parser->m_unknownEncodingHandler) +#define elementDeclHandler (parser->m_elementDeclHandler) +#define attlistDeclHandler (parser->m_attlistDeclHandler) +#define entityDeclHandler (parser->m_entityDeclHandler) +#define xmlDeclHandler (parser->m_xmlDeclHandler) +#define encoding (parser->m_encoding) +#define initEncoding (parser->m_initEncoding) +#define internalEncoding (parser->m_internalEncoding) +#define unknownEncodingMem (parser->m_unknownEncodingMem) +#define unknownEncodingData (parser->m_unknownEncodingData) +#define unknownEncodingHandlerData \ + (parser->m_unknownEncodingHandlerData) +#define unknownEncodingRelease (parser->m_unknownEncodingRelease) +#define protocolEncodingName (parser->m_protocolEncodingName) +#define ns (parser->m_ns) +#define ns_triplets (parser->m_ns_triplets) +#define prologState (parser->m_prologState) +#define processor (parser->m_processor) +#define errorCode (parser->m_errorCode) +#define eventPtr (parser->m_eventPtr) +#define eventEndPtr (parser->m_eventEndPtr) +#define positionPtr (parser->m_positionPtr) +#define position (parser->m_position) +#define openInternalEntities (parser->m_openInternalEntities) +#define freeInternalEntities (parser->m_freeInternalEntities) +#define defaultExpandInternalEntities \ + (parser->m_defaultExpandInternalEntities) +#define tagLevel (parser->m_tagLevel) +#define buffer (parser->m_buffer) +#define bufferPtr (parser->m_bufferPtr) +#define bufferEnd (parser->m_bufferEnd) +#define parseEndByteIndex (parser->m_parseEndByteIndex) +#define parseEndPtr (parser->m_parseEndPtr) +#define bufferLim (parser->m_bufferLim) +#define dataBuf (parser->m_dataBuf) +#define dataBufEnd (parser->m_dataBufEnd) +#define _dtd (parser->m_dtd) +#define curBase (parser->m_curBase) +#define declEntity (parser->m_declEntity) +#define doctypeName (parser->m_doctypeName) +#define doctypeSysid (parser->m_doctypeSysid) +#define doctypePubid (parser->m_doctypePubid) +#define declAttributeType (parser->m_declAttributeType) +#define declNotationName (parser->m_declNotationName) +#define declNotationPublicId (parser->m_declNotationPublicId) +#define declElementType (parser->m_declElementType) +#define declAttributeId (parser->m_declAttributeId) +#define declAttributeIsCdata (parser->m_declAttributeIsCdata) +#define declAttributeIsId (parser->m_declAttributeIsId) +#define freeTagList (parser->m_freeTagList) +#define freeBindingList (parser->m_freeBindingList) +#define inheritedBindings (parser->m_inheritedBindings) +#define tagStack (parser->m_tagStack) +#define atts (parser->m_atts) +#define attsSize (parser->m_attsSize) +#define nSpecifiedAtts (parser->m_nSpecifiedAtts) +#define idAttIndex (parser->m_idAttIndex) +#define nsAtts (parser->m_nsAtts) +#define nsAttsVersion (parser->m_nsAttsVersion) +#define nsAttsPower (parser->m_nsAttsPower) +#define tempPool (parser->m_tempPool) +#define temp2Pool (parser->m_temp2Pool) +#define groupConnector (parser->m_groupConnector) +#define groupSize (parser->m_groupSize) +#define namespaceSeparator (parser->m_namespaceSeparator) +#define parentParser (parser->m_parentParser) +#define ps_parsing (parser->m_parsingStatus.parsing) +#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer) +#ifdef XML_DTD +#define isParamEntity (parser->m_isParamEntity) +#define useForeignDTD (parser->m_useForeignDTD) +#define paramEntityParsing (parser->m_paramEntityParsing) +#endif /* XML_DTD */ + +XML_Parser XMLCALL +XML_ParserCreate(const XML_Char *encodingName) +{ + return XML_ParserCreate_MM(encodingName, NULL, NULL); +} + +XML_Parser XMLCALL +XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) +{ + XML_Char tmp[2]; + *tmp = nsSep; + return XML_ParserCreate_MM(encodingName, NULL, tmp); +} + +static const XML_Char implicitContext[] = { + 'x', 'm', 'l', '=', 'h', 't', 't', 'p', ':', '/', '/', + 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', + 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', + 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' +}; + +XML_Parser XMLCALL +XML_ParserCreate_MM(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep) +{ + XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL); + if (parser != NULL && ns) { + /* implicit context only set for root parser, since child + parsers (i.e. external entity parsers) will inherit it + */ + if (!setContext(parser, implicitContext)) { + XML_ParserFree(parser); + return NULL; + } + } + return parser; +} + +static XML_Parser +parserCreate(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep, + DTD *dtd) +{ + XML_Parser parser; + + if (memsuite) { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser) + memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = memsuite->malloc_fcn; + mtemp->realloc_fcn = memsuite->realloc_fcn; + mtemp->free_fcn = memsuite->free_fcn; + } + } + else { + XML_Memory_Handling_Suite *mtemp; + parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); + if (parser != NULL) { + mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); + mtemp->malloc_fcn = malloc; + mtemp->realloc_fcn = realloc; + mtemp->free_fcn = free; + } + } + + if (!parser) + return parser; + + buffer = NULL; + bufferLim = NULL; + + attsSize = INIT_ATTS_SIZE; + atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE)); + if (atts == NULL) { + FREE(parser); + return NULL; + } + dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + if (dataBuf == NULL) { + FREE(atts); + FREE(parser); + return NULL; + } + dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; + + if (dtd) + _dtd = dtd; + else { + _dtd = dtdCreate(&parser->m_mem); + if (_dtd == NULL) { + FREE(dataBuf); + FREE(atts); + FREE(parser); + return NULL; + } + } + + freeBindingList = NULL; + freeTagList = NULL; + freeInternalEntities = NULL; + + groupSize = 0; + groupConnector = NULL; + + unknownEncodingHandler = NULL; + unknownEncodingHandlerData = NULL; + + namespaceSeparator = '!'; + ns = XML_FALSE; + ns_triplets = XML_FALSE; + + nsAtts = NULL; + nsAttsVersion = 0; + nsAttsPower = 0; + + poolInit(&tempPool, &(parser->m_mem)); + poolInit(&temp2Pool, &(parser->m_mem)); + parserInit(parser, encodingName); + + if (encodingName && !protocolEncodingName) { + XML_ParserFree(parser); + return NULL; + } + + if (nameSep) { + ns = XML_TRUE; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = *nameSep; + } + else { + internalEncoding = XmlGetInternalEncoding(); + } + + return parser; +} + +static void +parserInit(XML_Parser parser, const XML_Char *encodingName) +{ + processor = prologInitProcessor; + XmlPrologStateInit(&prologState); + protocolEncodingName = (encodingName != NULL + ? poolCopyString(&tempPool, encodingName) + : NULL); + curBase = NULL; + XmlInitEncoding(&initEncoding, &encoding, 0); + userData = NULL; + handlerArg = NULL; + startElementHandler = NULL; + endElementHandler = NULL; + characterDataHandler = NULL; + processingInstructionHandler = NULL; + commentHandler = NULL; + startCdataSectionHandler = NULL; + endCdataSectionHandler = NULL; + defaultHandler = NULL; + startDoctypeDeclHandler = NULL; + endDoctypeDeclHandler = NULL; + unparsedEntityDeclHandler = NULL; + notationDeclHandler = NULL; + startNamespaceDeclHandler = NULL; + endNamespaceDeclHandler = NULL; + notStandaloneHandler = NULL; + externalEntityRefHandler = NULL; + externalEntityRefHandlerArg = parser; + skippedEntityHandler = NULL; + elementDeclHandler = NULL; + attlistDeclHandler = NULL; + entityDeclHandler = NULL; + xmlDeclHandler = NULL; + bufferPtr = buffer; + bufferEnd = buffer; + parseEndByteIndex = 0; + parseEndPtr = NULL; + declElementType = NULL; + declAttributeId = NULL; + declEntity = NULL; + doctypeName = NULL; + doctypeSysid = NULL; + doctypePubid = NULL; + declAttributeType = NULL; + declNotationName = NULL; + declNotationPublicId = NULL; + declAttributeIsCdata = XML_FALSE; + declAttributeIsId = XML_FALSE; + memset(&position, 0, sizeof(POSITION)); + errorCode = XML_ERROR_NONE; + eventPtr = NULL; + eventEndPtr = NULL; + positionPtr = NULL; + openInternalEntities = NULL; + defaultExpandInternalEntities = XML_TRUE; + tagLevel = 0; + tagStack = NULL; + inheritedBindings = NULL; + nSpecifiedAtts = 0; + unknownEncodingMem = NULL; + unknownEncodingRelease = NULL; + unknownEncodingData = NULL; + parentParser = NULL; + ps_parsing = XML_INITIALIZED; +#ifdef XML_DTD + isParamEntity = XML_FALSE; + useForeignDTD = XML_FALSE; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif +} + +/* moves list of bindings to freeBindingList */ +static void FASTCALL +moveToFreeBindingList(XML_Parser parser, BINDING *bindings) +{ + while (bindings) { + BINDING *b = bindings; + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + } +} + +XML_Bool XMLCALL +XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) +{ + TAG *tStk; + OPEN_INTERNAL_ENTITY *openEntityList; + if (parentParser) + return XML_FALSE; + /* move tagStack to freeTagList */ + tStk = tagStack; + while (tStk) { + TAG *tag = tStk; + tStk = tStk->parent; + tag->parent = freeTagList; + moveToFreeBindingList(parser, tag->bindings); + tag->bindings = NULL; + freeTagList = tag; + } + /* move openInternalEntities to freeInternalEntities */ + openEntityList = openInternalEntities; + while (openEntityList) { + OPEN_INTERNAL_ENTITY *openEntity = openEntityList; + openEntityList = openEntity->next; + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + moveToFreeBindingList(parser, inheritedBindings); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + poolClear(&tempPool); + poolClear(&temp2Pool); + parserInit(parser, encodingName); + dtdReset(_dtd, &parser->m_mem); + return setContext(parser, implicitContext); +} + +enum XML_Status XMLCALL +XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + /* Block after XML_Parse()/XML_ParseBuffer() has been called. + XXX There's no way for the caller to determine which of the + XXX possible error cases caused the XML_STATUS_ERROR return. + */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return XML_STATUS_ERROR; + if (encodingName == NULL) + protocolEncodingName = NULL; + else { + protocolEncodingName = poolCopyString(&tempPool, encodingName); + if (!protocolEncodingName) + return XML_STATUS_ERROR; + } + return XML_STATUS_OK; +} + +XML_Parser XMLCALL +XML_ExternalEntityParserCreate(XML_Parser oldParser, + const XML_Char *context, + const XML_Char *encodingName) +{ + XML_Parser parser = oldParser; + DTD *newDtd = NULL; + DTD *oldDtd = _dtd; + XML_StartElementHandler oldStartElementHandler = startElementHandler; + XML_EndElementHandler oldEndElementHandler = endElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler + = processingInstructionHandler; + XML_CommentHandler oldCommentHandler = commentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler + = startCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler + = endCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler = defaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler + = unparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler + = startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler + = endNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler + = externalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler + = unknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType = declElementType; + + void *oldUserData = userData; + void *oldHandlerArg = handlerArg; + XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; + int oldInEntityValue = prologState.inEntityValue; +#endif + XML_Bool oldns_triplets = ns_triplets; + +#ifdef XML_DTD + if (!context) + newDtd = oldDtd; +#endif /* XML_DTD */ + + /* Note that the magical uses of the pre-processor to make field + access look more like C++ require that `parser' be overwritten + here. This makes this function more painful to follow than it + would be otherwise. + */ + if (ns) { + XML_Char tmp[2]; + *tmp = namespaceSeparator; + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + } + else { + parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); + } + + if (!parser) + return NULL; + + startElementHandler = oldStartElementHandler; + endElementHandler = oldEndElementHandler; + characterDataHandler = oldCharacterDataHandler; + processingInstructionHandler = oldProcessingInstructionHandler; + commentHandler = oldCommentHandler; + startCdataSectionHandler = oldStartCdataSectionHandler; + endCdataSectionHandler = oldEndCdataSectionHandler; + defaultHandler = oldDefaultHandler; + unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; + notationDeclHandler = oldNotationDeclHandler; + startNamespaceDeclHandler = oldStartNamespaceDeclHandler; + endNamespaceDeclHandler = oldEndNamespaceDeclHandler; + notStandaloneHandler = oldNotStandaloneHandler; + externalEntityRefHandler = oldExternalEntityRefHandler; + skippedEntityHandler = oldSkippedEntityHandler; + unknownEncodingHandler = oldUnknownEncodingHandler; + elementDeclHandler = oldElementDeclHandler; + attlistDeclHandler = oldAttlistDeclHandler; + entityDeclHandler = oldEntityDeclHandler; + xmlDeclHandler = oldXmlDeclHandler; + declElementType = oldDeclElementType; + userData = oldUserData; + if (oldUserData == oldHandlerArg) + handlerArg = userData; + else + handlerArg = parser; + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; + ns_triplets = oldns_triplets; + parentParser = oldParser; +#ifdef XML_DTD + paramEntityParsing = oldParamEntityParsing; + prologState.inEntityValue = oldInEntityValue; + if (context) { +#endif /* XML_DTD */ + if (!dtdCopy(_dtd, oldDtd, &parser->m_mem) + || !setContext(parser, context)) { + XML_ParserFree(parser); + return NULL; + } + processor = externalEntityInitProcessor; +#ifdef XML_DTD + } + else { + /* The DTD instance referenced by _dtd is shared between the document's + root parser and external PE parsers, therefore one does not need to + call setContext. In addition, one also *must* not call setContext, + because this would overwrite existing prefix->binding pointers in + _dtd with ones that get destroyed with the external PE parser. + This would leave those prefixes with dangling pointers. + */ + isParamEntity = XML_TRUE; + XmlPrologStateInitExternalEntity(&prologState); + processor = externalParEntInitProcessor; + } +#endif /* XML_DTD */ + return parser; +} + +static void FASTCALL +destroyBindings(BINDING *bindings, XML_Parser parser) +{ + for (;;) { + BINDING *b = bindings; + if (!b) + break; + bindings = b->nextTagBinding; + FREE(b->uri); + FREE(b); + } +} + +void XMLCALL +XML_ParserFree(XML_Parser parser) +{ + TAG *tagList; + OPEN_INTERNAL_ENTITY *entityList; + if (parser == NULL) + return; + /* free tagStack and freeTagList */ + tagList = tagStack; + for (;;) { + TAG *p; + if (tagList == NULL) { + if (freeTagList == NULL) + break; + tagList = freeTagList; + freeTagList = NULL; + } + p = tagList; + tagList = tagList->parent; + FREE(p->buf); + destroyBindings(p->bindings, parser); + FREE(p); + } + /* free openInternalEntities and freeInternalEntities */ + entityList = openInternalEntities; + for (;;) { + OPEN_INTERNAL_ENTITY *openEntity; + if (entityList == NULL) { + if (freeInternalEntities == NULL) + break; + entityList = freeInternalEntities; + freeInternalEntities = NULL; + } + openEntity = entityList; + entityList = entityList->next; + FREE(openEntity); + } + + destroyBindings(freeBindingList, parser); + destroyBindings(inheritedBindings, parser); + poolDestroy(&tempPool); + poolDestroy(&temp2Pool); +#ifdef XML_DTD + /* external parameter entity parsers share the DTD structure + parser->m_dtd with the root parser, so we must not destroy it + */ + if (!isParamEntity && _dtd) +#else + if (_dtd) +#endif /* XML_DTD */ + dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem); + FREE((void *)atts); + FREE(groupConnector); + FREE(buffer); + FREE(dataBuf); + FREE(nsAtts); + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + FREE(parser); +} + +void XMLCALL +XML_UseParserAsHandlerArg(XML_Parser parser) +{ + handlerArg = parser; +} + +enum XML_Error XMLCALL +XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) +{ +#ifdef XML_DTD + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; + useForeignDTD = useDTD; + return XML_ERROR_NONE; +#else + return XML_ERROR_FEATURE_REQUIRES_XML_DTD; +#endif +} + +void XMLCALL +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) +{ + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return; + ns_triplets = do_nst ? XML_TRUE : XML_FALSE; +} + +void XMLCALL +XML_SetUserData(XML_Parser parser, void *p) +{ + if (handlerArg == userData) + handlerArg = userData = p; + else + userData = p; +} + +enum XML_Status XMLCALL +XML_SetBase(XML_Parser parser, const XML_Char *p) +{ + if (p) { + p = poolCopyString(&_dtd->pool, p); + if (!p) + return XML_STATUS_ERROR; + curBase = p; + } + else + curBase = NULL; + return XML_STATUS_OK; +} + +const XML_Char * XMLCALL +XML_GetBase(XML_Parser parser) +{ + return curBase; +} + +int XMLCALL +XML_GetSpecifiedAttributeCount(XML_Parser parser) +{ + return nSpecifiedAtts; +} + +int XMLCALL +XML_GetIdAttributeIndex(XML_Parser parser) +{ + return idAttIndex; +} + +void XMLCALL +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end) +{ + startElementHandler = start; + endElementHandler = end; +} + +void XMLCALL +XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler start) { + startElementHandler = start; +} + +void XMLCALL +XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler end) { + endElementHandler = end; +} + +void XMLCALL +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler) +{ + characterDataHandler = handler; +} + +void XMLCALL +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler) +{ + processingInstructionHandler = handler; +} + +void XMLCALL +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler) +{ + commentHandler = handler; +} + +void XMLCALL +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end) +{ + startCdataSectionHandler = start; + endCdataSectionHandler = end; +} + +void XMLCALL +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start) { + startCdataSectionHandler = start; +} + +void XMLCALL +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end) { + endCdataSectionHandler = end; +} + +void XMLCALL +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = XML_FALSE; +} + +void XMLCALL +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = XML_TRUE; +} + +void XMLCALL +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end) +{ + startDoctypeDeclHandler = start; + endDoctypeDeclHandler = end; +} + +void XMLCALL +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start) { + startDoctypeDeclHandler = start; +} + +void XMLCALL +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end) { + endDoctypeDeclHandler = end; +} + +void XMLCALL +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler) +{ + unparsedEntityDeclHandler = handler; +} + +void XMLCALL +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler) +{ + notationDeclHandler = handler; +} + +void XMLCALL +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end) +{ + startNamespaceDeclHandler = start; + endNamespaceDeclHandler = end; +} + +void XMLCALL +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start) { + startNamespaceDeclHandler = start; +} + +void XMLCALL +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end) { + endNamespaceDeclHandler = end; +} + +void XMLCALL +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler) +{ + notStandaloneHandler = handler; +} + +void XMLCALL +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler) +{ + externalEntityRefHandler = handler; +} + +void XMLCALL +XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) +{ + if (arg) + externalEntityRefHandlerArg = (XML_Parser)arg; + else + externalEntityRefHandlerArg = parser; +} + +void XMLCALL +XML_SetSkippedEntityHandler(XML_Parser parser, + XML_SkippedEntityHandler handler) +{ + skippedEntityHandler = handler; +} + +void XMLCALL +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *data) +{ + unknownEncodingHandler = handler; + unknownEncodingHandlerData = data; +} + +void XMLCALL +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl) +{ + elementDeclHandler = eldecl; +} + +void XMLCALL +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl) +{ + attlistDeclHandler = attdecl; +} + +void XMLCALL +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler) +{ + entityDeclHandler = handler; +} + +void XMLCALL +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler handler) { + xmlDeclHandler = handler; +} + +int XMLCALL +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing peParsing) +{ + /* block after XML_Parse()/XML_ParseBuffer() has been called */ + if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) + return 0; +#ifdef XML_DTD + paramEntityParsing = peParsing; + return 1; +#else + return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; +#endif +} + +enum XML_Status XMLCALL +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + ps_parsing = XML_PARSING; + } + + if (len == 0) { + ps_finalBuffer = (XML_Bool)isFinal; + if (!isFinal) + return XML_STATUS_OK; + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; + + /* If data are left over from last buffer, and we now know that these + data are the final chunk of input, then we have to check them again + to detect errors based on that fact. + */ + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode == XML_ERROR_NONE) { + switch (ps_parsing) { + case XML_SUSPENDED: + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return XML_STATUS_SUSPENDED; + case XML_INITIALIZED: + case XML_PARSING: + ps_parsing = XML_FINISHED; + /* fall through */ + default: + return XML_STATUS_OK; + } + } + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } +#ifndef XML_CONTEXT_BYTES + else if (bufferPtr == bufferEnd) { + const char *end; + int nLeftOver; + enum XML_Error result; + parseEndByteIndex += len; + positionPtr = s; + ps_finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, s, parseEndPtr = s + len, &end); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + result = XML_STATUS_OK; + if (isFinal) { + ps_parsing = XML_FINISHED; + return result; + } + } + } + + XmlUpdatePosition(encoding, positionPtr, end, &position); + nLeftOver = s + len - end; + if (nLeftOver) { + if (buffer == NULL || nLeftOver > bufferLim - buffer) { + /* FIXME avoid integer overflow */ + char *temp; + temp = (buffer == NULL + ? (char *)MALLOC(len * 2) + : (char *)REALLOC(buffer, len * 2)); + if (temp == NULL) { + errorCode = XML_ERROR_NO_MEMORY; + return XML_STATUS_ERROR; + } + buffer = temp; + if (!buffer) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + bufferLim = buffer + len * 2; + } + memcpy(buffer, end, nLeftOver); + } + bufferPtr = buffer; + bufferEnd = buffer + nLeftOver; + positionPtr = bufferPtr; + parseEndPtr = bufferEnd; + eventPtr = bufferPtr; + eventEndPtr = bufferPtr; + return result; + } +#endif /* not defined XML_CONTEXT_BYTES */ + else { + void *buff = XML_GetBuffer(parser, len); + if (buff == NULL) + return XML_STATUS_ERROR; + else { + memcpy(buff, s, len); + return XML_ParseBuffer(parser, len, isFinal); + } + } +} + +enum XML_Status XMLCALL +XML_ParseBuffer(XML_Parser parser, int len, int isFinal) +{ + const char *start; + enum XML_Status result = XML_STATUS_OK; + + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + ps_parsing = XML_PARSING; + } + + start = bufferPtr; + positionPtr = start; + bufferEnd += len; + parseEndPtr = bufferEnd; + parseEndByteIndex += len; + ps_finalBuffer = (XML_Bool)isFinal; + + errorCode = processor(parser, start, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (isFinal) { + ps_parsing = XML_FINISHED; + return result; + } + default: ; /* should not happen */ + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; +} + +void * XMLCALL +XML_GetBuffer(XML_Parser parser, int len) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + errorCode = XML_ERROR_SUSPENDED; + return NULL; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return NULL; + default: ; + } + + if (len > bufferLim - bufferEnd) { + /* FIXME avoid integer overflow */ + int neededSize = len + (int)(bufferEnd - bufferPtr); +#ifdef XML_CONTEXT_BYTES + int keep = (int)(bufferPtr - buffer); + + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + neededSize += keep; +#endif /* defined XML_CONTEXT_BYTES */ + if (neededSize <= bufferLim - buffer) { +#ifdef XML_CONTEXT_BYTES + if (keep < bufferPtr - buffer) { + int offset = (int)(bufferPtr - buffer) - keep; + memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); + bufferEnd -= offset; + bufferPtr -= offset; + } +#else + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; +#endif /* not defined XML_CONTEXT_BYTES */ + } + else { + char *newBuf; + int bufferSize = (int)(bufferLim - bufferPtr); + if (bufferSize == 0) + bufferSize = INIT_BUFFER_SIZE; + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = (char *)MALLOC(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } + bufferLim = newBuf + bufferSize; +#ifdef XML_CONTEXT_BYTES + if (bufferPtr) { + int keep = (int)(bufferPtr - buffer); + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); + FREE(buffer); + buffer = newBuf; + bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; + bufferPtr = buffer + keep; + } + else { + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } +#else + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + FREE(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; +#endif /* not defined XML_CONTEXT_BYTES */ + } + } + return bufferEnd; +} + +enum XML_Status XMLCALL +XML_StopParser(XML_Parser parser, XML_Bool resumable) +{ + switch (ps_parsing) { + case XML_SUSPENDED: + if (resumable) { + errorCode = XML_ERROR_SUSPENDED; + return XML_STATUS_ERROR; + } + ps_parsing = XML_FINISHED; + break; + case XML_FINISHED: + errorCode = XML_ERROR_FINISHED; + return XML_STATUS_ERROR; + default: + if (resumable) { +#ifdef XML_DTD + if (isParamEntity) { + errorCode = XML_ERROR_SUSPEND_PE; + return XML_STATUS_ERROR; + } +#endif + ps_parsing = XML_SUSPENDED; + } + else + ps_parsing = XML_FINISHED; + } + return XML_STATUS_OK; +} + +enum XML_Status XMLCALL +XML_ResumeParser(XML_Parser parser) +{ + enum XML_Status result = XML_STATUS_OK; + + if (ps_parsing != XML_SUSPENDED) { + errorCode = XML_ERROR_NOT_SUSPENDED; + return XML_STATUS_ERROR; + } + ps_parsing = XML_PARSING; + + errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr); + + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return XML_STATUS_ERROR; + } + else { + switch (ps_parsing) { + case XML_SUSPENDED: + result = XML_STATUS_SUSPENDED; + break; + case XML_INITIALIZED: + case XML_PARSING: + if (ps_finalBuffer) { + ps_parsing = XML_FINISHED; + return result; + } + default: ; + } + } + + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + positionPtr = bufferPtr; + return result; +} + +void XMLCALL +XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) +{ + assert(status != NULL); + *status = parser->m_parsingStatus; +} + +enum XML_Error XMLCALL +XML_GetErrorCode(XML_Parser parser) +{ + return errorCode; +} + +XML_Index XMLCALL +XML_GetCurrentByteIndex(XML_Parser parser) +{ + if (eventPtr) + return parseEndByteIndex - (parseEndPtr - eventPtr); + return -1; +} + +int XMLCALL +XML_GetCurrentByteCount(XML_Parser parser) +{ + if (eventEndPtr && eventPtr) + return (int)(eventEndPtr - eventPtr); + return 0; +} + +const char * XMLCALL +XML_GetInputContext(XML_Parser parser, int *offset, int *size) +{ +#ifdef XML_CONTEXT_BYTES + if (eventPtr && buffer) { + *offset = (int)(eventPtr - buffer); + *size = (int)(bufferEnd - buffer); + return buffer; + } +#endif /* defined XML_CONTEXT_BYTES */ + return (char *) 0; +} + +XML_Size XMLCALL +XML_GetCurrentLineNumber(XML_Parser parser) +{ + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.lineNumber + 1; +} + +XML_Size XMLCALL +XML_GetCurrentColumnNumber(XML_Parser parser) +{ + if (eventPtr && eventPtr >= positionPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.columnNumber; +} + +void XMLCALL +XML_FreeContentModel(XML_Parser parser, XML_Content *model) +{ + FREE(model); +} + +void * XMLCALL +XML_MemMalloc(XML_Parser parser, size_t size) +{ + return MALLOC(size); +} + +void * XMLCALL +XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) +{ + return REALLOC(ptr, size); +} + +void XMLCALL +XML_MemFree(XML_Parser parser, void *ptr) +{ + FREE(ptr); +} + +void XMLCALL +XML_DefaultCurrent(XML_Parser parser) +{ + if (defaultHandler) { + if (openInternalEntities) + reportDefault(parser, + internalEncoding, + openInternalEntities->internalEventPtr, + openInternalEntities->internalEventEndPtr); + else + reportDefault(parser, encoding, eventPtr, eventEndPtr); + } +} + +const XML_LChar * XMLCALL +XML_ErrorString(enum XML_Error code) +{ + static const XML_LChar* const message[] = { + 0, + XML_L("out of memory"), + XML_L("syntax error"), + XML_L("no element found"), + XML_L("not well-formed (invalid token)"), + XML_L("unclosed token"), + XML_L("partial character"), + XML_L("mismatched tag"), + XML_L("duplicate attribute"), + XML_L("junk after document element"), + XML_L("illegal parameter entity reference"), + XML_L("undefined entity"), + XML_L("recursive entity reference"), + XML_L("asynchronous entity"), + XML_L("reference to invalid character number"), + XML_L("reference to binary entity"), + XML_L("reference to external entity in attribute"), + XML_L("XML or text declaration not at start of entity"), + XML_L("unknown encoding"), + XML_L("encoding specified in XML declaration is incorrect"), + XML_L("unclosed CDATA section"), + XML_L("error in processing external entity reference"), + XML_L("document is not standalone"), + XML_L("unexpected parser state - please send a bug report"), + XML_L("entity declared in parameter entity"), + XML_L("requested feature requires XML_DTD support in Expat"), + XML_L("cannot change setting once parsing has begun"), + XML_L("unbound prefix"), + XML_L("must not undeclare prefix"), + XML_L("incomplete markup in parameter entity"), + XML_L("XML declaration not well-formed"), + XML_L("text declaration not well-formed"), + XML_L("illegal character(s) in public id"), + XML_L("parser suspended"), + XML_L("parser not suspended"), + XML_L("parsing aborted"), + XML_L("parsing finished"), + XML_L("cannot suspend in external parameter entity"), + XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"), + XML_L("reserved prefix (xmlns) must not be declared or undeclared"), + XML_L("prefix must not be bound to one of the reserved namespace names") + }; + if (code > 0 && code < sizeof(message)/sizeof(message[0])) + return message[code]; + return NULL; +} + +const XML_LChar * XMLCALL +XML_ExpatVersion(void) { + + /* V1 is used to string-ize the version number. However, it would + string-ize the actual version macro *names* unless we get them + substituted before being passed to V1. CPP is defined to expand + a macro, then rescan for more expansions. Thus, we use V2 to expand + the version macros, then CPP will expand the resulting V1() macro + with the correct numerals. */ + /* ### I'm assuming cpp is portable in this respect... */ + +#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c) +#define V2(a,b,c) XML_L("expat_")V1(a,b,c) + + return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); + +#undef V1 +#undef V2 +} + +XML_Expat_Version XMLCALL +XML_ExpatVersionInfo(void) +{ + XML_Expat_Version version; + + version.major = XML_MAJOR_VERSION; + version.minor = XML_MINOR_VERSION; + version.micro = XML_MICRO_VERSION; + + return version; +} + +const XML_Feature * XMLCALL +XML_GetFeatureList(void) +{ + static const XML_Feature features[] = { + {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), + sizeof(XML_Char)}, + {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), + sizeof(XML_LChar)}, +#ifdef XML_UNICODE + {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, +#endif +#ifdef XML_UNICODE_WCHAR_T + {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, +#endif +#ifdef XML_DTD + {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, +#endif +#ifdef XML_CONTEXT_BYTES + {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), + XML_CONTEXT_BYTES}, +#endif +#ifdef XML_MIN_SIZE + {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, +#endif +#ifdef XML_NS + {XML_FEATURE_NS, XML_L("XML_NS"), 0}, +#endif + {XML_FEATURE_END, NULL, 0} + }; + + return features; +} + +/* Initially tag->rawName always points into the parse buffer; + for those TAG instances opened while the current parse buffer was + processed, and not yet closed, we need to store tag->rawName in a more + permanent location, since the parse buffer is about to be discarded. +*/ +static XML_Bool +storeRawNames(XML_Parser parser) +{ + TAG *tag = tagStack; + while (tag) { + int bufSize; + int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); + char *rawNameBuf = tag->buf + nameLen; + /* Stop if already stored. Since tagStack is a stack, we can stop + at the first entry that has already been copied; everything + below it in the stack is already been accounted for in a + previous call to this function. + */ + if (tag->rawName == rawNameBuf) + break; + /* For re-use purposes we need to ensure that the + size of tag->buf is a multiple of sizeof(XML_Char). + */ + bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); + if (bufSize > tag->bufEnd - tag->buf) { + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_FALSE; + /* if tag->name.str points to tag->buf (only when namespace + processing is off) then we have to update it + */ + if (tag->name.str == (XML_Char *)tag->buf) + tag->name.str = (XML_Char *)temp; + /* if tag->name.localPart is set (when namespace processing is on) + then update it as well, since it will always point into tag->buf + */ + if (tag->name.localPart) + tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - + (XML_Char *)tag->buf); + tag->buf = temp; + tag->bufEnd = temp + bufSize; + rawNameBuf = temp + nameLen; + } + memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); + tag->rawName = rawNameBuf; + tag = tag->parent; + } + return XML_TRUE; +} + +static enum XML_Error PTRCALL +contentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doContent(parser, 0, encoding, start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = externalEntityInitProcessor2; + return externalEntityInitProcessor2(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor2(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(encoding, start, end, &next); + switch (tok) { + case XML_TOK_BOM: + /* If we are at the end of the buffer, this would cause the next stage, + i.e. externalEntityInitProcessor3, to pass control directly to + doContent (by detecting XML_TOK_NONE) without processing any xml text + declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. + */ + if (next == end && !ps_finalBuffer) { + *endPtr = next; + return XML_ERROR_NONE; + } + start = next; + break; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityInitProcessor3; + return externalEntityInitProcessor3(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityInitProcessor3(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + int tok; + const char *next = start; /* XmlContentTok doesn't always set the last arg */ + eventPtr = start; + tok = XmlContentTok(encoding, start, end, &next); + eventEndPtr = next; + + switch (tok) { + case XML_TOK_XML_DECL: + { + enum XML_Error result; + result = processXmlDecl(parser, 1, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (ps_parsing) { + case XML_SUSPENDED: + *endPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + start = next; + } + } + break; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *endPtr = start; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityContentProcessor; + tagLevel = 1; + return externalEntityContentProcessor(parser, start, end, endPtr); +} + +static enum XML_Error PTRCALL +externalEntityContentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doContent(parser, 1, encoding, start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result == XML_ERROR_NONE) { + if (!storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; +} + +static enum XML_Error +doContent(XML_Parser parser, + int startTagLevel, + const ENCODING *enc, + const char *s, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + + for (;;) { + const char *next = s; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_TRAILING_CR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + *eventEndPP = end; + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) + return XML_ERROR_NO_ELEMENTS; + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (startTagLevel > 0) { + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_NO_ELEMENTS; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (characterDataHandler) + characterDataHandler(handlerArg, &ch, 1); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); + poolDiscard(&dtd->pool); + /* First, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity or default handler. + */ + if (!dtd->hasParamEntityRefs || dtd->standalone) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->notation) + return XML_ERROR_BINARY_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + if (!defaultExpandInternalEntities) { + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, entity->name, 0); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + result = processInternalEntity(parser, entity, XML_FALSE); + if (result != XML_ERROR_NONE) + return result; + } + else if (externalEntityRefHandler) { + const XML_Char *context; + entity->open = XML_TRUE; + context = getContext(parser); + entity->open = XML_FALSE; + if (!context) + return XML_ERROR_NO_MEMORY; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + context, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + poolDiscard(&tempPool); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + case XML_TOK_START_TAG_NO_ATTS: + /* fall through */ + case XML_TOK_START_TAG_WITH_ATTS: + { + TAG *tag; + enum XML_Error result; + XML_Char *toPtr; + if (freeTagList) { + tag = freeTagList; + freeTagList = freeTagList->parent; + } + else { + tag = (TAG *)MALLOC(sizeof(TAG)); + if (!tag) + return XML_ERROR_NO_MEMORY; + tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE); + if (!tag->buf) { + FREE(tag); + return XML_ERROR_NO_MEMORY; + } + tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + } + tag->bindings = NULL; + tag->parent = tagStack; + tagStack = tag; + tag->name.localPart = NULL; + tag->name.prefix = NULL; + tag->rawName = s + enc->minBytesPerChar; + tag->rawNameLength = XmlNameLength(enc, tag->rawName); + ++tagLevel; + { + const char *rawNameEnd = tag->rawName + tag->rawNameLength; + const char *fromPtr = tag->rawName; + toPtr = (XML_Char *)tag->buf; + for (;;) { + int bufSize; + int convLen; + XmlConvert(enc, + &fromPtr, rawNameEnd, + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); + convLen = (int)(toPtr - (XML_Char *)tag->buf); + if (fromPtr == rawNameEnd) { + tag->name.strLen = convLen; + break; + } + bufSize = (int)(tag->bufEnd - tag->buf) << 1; + { + char *temp = (char *)REALLOC(tag->buf, bufSize); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + tag->buf = temp; + tag->bufEnd = temp + bufSize; + toPtr = (XML_Char *)temp + convLen; + } + } + } + tag->name.str = (XML_Char *)tag->buf; + *toPtr = XML_T('\0'); + result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + if (result) + return result; + if (startElementHandler) + startElementHandler(handlerArg, tag->name.str, + (const XML_Char **)atts); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); + break; + } + case XML_TOK_EMPTY_ELEMENT_NO_ATTS: + /* fall through */ + case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: + { + const char *rawName = s + enc->minBytesPerChar; + enum XML_Error result; + BINDING *bindings = NULL; + XML_Bool noElmHandlers = XML_TRUE; + TAG_NAME name; + name.str = poolStoreString(&tempPool, enc, rawName, + rawName + XmlNameLength(enc, rawName)); + if (!name.str) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + result = storeAtts(parser, enc, s, &name, &bindings); + if (result) + return result; + poolFinish(&tempPool); + if (startElementHandler) { + startElementHandler(handlerArg, name.str, (const XML_Char **)atts); + noElmHandlers = XML_FALSE; + } + if (endElementHandler) { + if (startElementHandler) + *eventPP = *eventEndPP; + endElementHandler(handlerArg, name.str); + noElmHandlers = XML_FALSE; + } + if (noElmHandlers && defaultHandler) + reportDefault(parser, enc, s, next); + poolClear(&tempPool); + while (bindings) { + BINDING *b = bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + break; + case XML_TOK_END_TAG: + if (tagLevel == startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + else { + int len; + const char *rawName; + TAG *tag = tagStack; + tagStack = tag->parent; + tag->parent = freeTagList; + freeTagList = tag; + rawName = s + enc->minBytesPerChar*2; + len = XmlNameLength(enc, rawName); + if (len != tag->rawNameLength + || memcmp(tag->rawName, rawName, len) != 0) { + *eventPP = rawName; + return XML_ERROR_TAG_MISMATCH; + } + --tagLevel; + if (endElementHandler) { + const XML_Char *localPart; + const XML_Char *prefix; + XML_Char *uri; + localPart = tag->name.localPart; + if (ns && localPart) { + /* localPart and prefix may have been overwritten in + tag->name.str, since this points to the binding->uri + buffer which gets re-used; so we have to add them again + */ + uri = (XML_Char *)tag->name.str + tag->name.uriLen; + /* don't need to check for space - already done in storeAtts() */ + while (*localPart) *uri++ = *localPart++; + prefix = (XML_Char *)tag->name.prefix; + if (ns_triplets && prefix) { + *uri++ = namespaceSeparator; + while (*prefix) *uri++ = *prefix++; + } + *uri = XML_T('\0'); + } + endElementHandler(handlerArg, tag->name.str); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + while (tag->bindings) { + BINDING *b = tag->bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + tag->bindings = tag->bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + } + break; + case XML_TOK_CHAR_REF: + { + int n = XmlCharRefNumber(enc, s); + if (n < 0) + return XML_ERROR_BAD_CHAR_REF; + if (characterDataHandler) { + XML_Char buf[XML_ENCODE_MAX]; + characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_CDATA_SECT_OPEN: + { + enum XML_Error result; + if (startCdataSectionHandler) + startCdataSectionHandler(handlerArg); +#if 0 + /* Suppose you doing a transformation on a document that involves + changing only the character data. You set up a defaultHandler + and a characterDataHandler. The defaultHandler simply copies + characters through. The characterDataHandler does the + transformation and writes the characters out escaping them as + necessary. This case will fail to work if we leave out the + following two lines (because & and < inside CDATA sections will + be incorrectly escaped). + + However, now we have a start/endCdataSectionHandler, so it seems + easier to let the user deal with this. + */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = cdataSectionProcessor; + return result; + } + } + break; + case XML_TOK_TRAILING_RSQB: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + characterDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)end - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + /* We are at the end of the final buffer, should we check for + XML_SUSPENDED, XML_FINISHED? + */ + if (startTagLevel == 0) { + *eventPP = end; + return XML_ERROR_NO_ELEMENTS; + } + if (tagLevel != startTagLevel) { + *eventPP = end; + return XML_ERROR_ASYNC_ENTITY; + } + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + characterDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)next - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + default: + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + *eventPP = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } + /* not reached */ +} + +/* Precondition: all arguments must be non-NULL; + Purpose: + - normalize attributes + - check attributes for well-formedness + - generate namespace aware attribute names (URI, prefix) + - build list of attributes for startElementHandler + - default attributes + - process namespace declarations (check and report them) + - generate namespace aware element name (URI, prefix) +*/ +static enum XML_Error +storeAtts(XML_Parser parser, const ENCODING *enc, + const char *attStr, TAG_NAME *tagNamePtr, + BINDING **bindingsPtr) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + ELEMENT_TYPE *elementType; + int nDefaultAtts; + const XML_Char **appAtts; /* the attribute list for the application */ + int attIndex = 0; + int prefixLen; + int i; + int n; + XML_Char *uri; + int nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + + /* lookup the element type name */ + elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0); + if (!elementType) { + const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); + if (!name) + return XML_ERROR_NO_MEMORY; + elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name, + sizeof(ELEMENT_TYPE)); + if (!elementType) + return XML_ERROR_NO_MEMORY; + if (ns && !setElementTypePrefix(parser, elementType)) + return XML_ERROR_NO_MEMORY; + } + nDefaultAtts = elementType->nDefaultAtts; + + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, attsSize, atts); + if (n + nDefaultAtts > attsSize) { + int oldAttsSize = attsSize; + ATTRIBUTE *temp; + attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; + temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + atts = temp; + if (n > oldAttsSize) + XmlGetAttributes(enc, attStr, n, atts); + } + + appAtts = (const XML_Char **)atts; + for (i = 0; i < n; i++) { + /* add the name and value to the attribute list */ + ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, + atts[i].name + + XmlNameLength(enc, atts[i].name)); + if (!attId) + return XML_ERROR_NO_MEMORY; + /* Detect duplicate attributes by their QNames. This does not work when + namespace processing is turned on and different prefixes for the same + namespace are used. For this case we have a check further down. + */ + if ((attId->name)[-1]) { + if (enc == encoding) + eventPtr = atts[i].name; + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + (attId->name)[-1] = 1; + appAtts[attIndex++] = attId->name; + if (!atts[i].normalized) { + enum XML_Error result; + XML_Bool isCdata = XML_TRUE; + + /* figure out whether declared as other than CDATA */ + if (attId->maybeTokenized) { + int j; + for (j = 0; j < nDefaultAtts; j++) { + if (attId == elementType->defaultAtts[j].id) { + isCdata = elementType->defaultAtts[j].isCdata; + break; + } + } + } + + /* normalize the attribute value */ + result = storeAttributeValue(parser, enc, isCdata, + atts[i].valuePtr, atts[i].valueEnd, + &tempPool); + if (result) + return result; + appAtts[attIndex] = poolStart(&tempPool); + poolFinish(&tempPool); + } + else { + /* the value did not need normalizing */ + appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, + atts[i].valueEnd); + if (appAtts[attIndex] == 0) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + /* handle prefixed attribute names */ + if (attId->prefix) { + if (attId->xmlns) { + /* deal with namespace declarations here */ + enum XML_Error result = addBinding(parser, attId->prefix, attId, + appAtts[attIndex], bindingsPtr); + if (result) + return result; + --attIndex; + } + else { + /* deal with other prefixed names later */ + attIndex++; + nPrefixes++; + (attId->name)[-1] = 2; + } + } + else + attIndex++; + } + + /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ + nSpecifiedAtts = attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { + for (i = 0; i < attIndex; i += 2) + if (appAtts[i] == elementType->idAtt->name) { + idAttIndex = i; + break; + } + } + else + idAttIndex = -1; + + /* do attribute defaulting */ + for (i = 0; i < nDefaultAtts; i++) { + const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; + if (!(da->id->name)[-1] && da->value) { + if (da->id->prefix) { + if (da->id->xmlns) { + enum XML_Error result = addBinding(parser, da->id->prefix, da->id, + da->value, bindingsPtr); + if (result) + return result; + } + else { + (da->id->name)[-1] = 2; + nPrefixes++; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + else { + (da->id->name)[-1] = 1; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + } + appAtts[attIndex] = 0; + + /* expand prefixed attribute names, check for duplicates, + and clear flags that say whether attributes were specified */ + i = 0; + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = nsAttsVersion; + int nsAttsSize = (int)1 << nsAttsPower; + /* size of hash table must be at least 2 * (# of prefixed attributes) */ + if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */ + NS_ATT *temp; + /* hash table size must also be a power of 2 and >= 8 */ + while (nPrefixes >> nsAttsPower++); + if (nsAttsPower < 3) + nsAttsPower = 3; + nsAttsSize = (int)1 << nsAttsPower; + temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT)); + if (!temp) + return XML_ERROR_NO_MEMORY; + nsAtts = temp; + version = 0; /* force re-initialization of nsAtts hash table */ + } + /* using a version flag saves us from initializing nsAtts every time */ + if (!version) { /* initialize version flags when version wraps around */ + version = INIT_ATTS_VERSION; + for (j = nsAttsSize; j != 0; ) + nsAtts[--j].version = version; + } + nsAttsVersion = --version; + + /* expand prefixed names and check for duplicates */ + for (; i < attIndex; i += 2) { + const XML_Char *s = appAtts[i]; + if (s[-1] == 2) { /* prefixed */ + ATTRIBUTE_ID *id; + const BINDING *b; + unsigned long uriHash = 0; + ((XML_Char *)s)[-1] = 0; /* clear flag */ + id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0); + b = id->prefix->binding; + if (!b) + return XML_ERROR_UNBOUND_PREFIX; + + /* as we expand the name we also calculate its hash value */ + for (j = 0; j < b->uriLen; j++) { + const XML_Char c = b->uri[j]; + if (!poolAppendChar(&tempPool, c)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); + } + while (*s++ != XML_T(':')) + ; + do { /* copies null terminator */ + const XML_Char c = *s; + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + uriHash = CHAR_HASH(uriHash, c); + } while (*s++); + + { /* Check hash table for duplicate of expanded name (uriName). + Derived from code in lookup(HASH_TABLE *table, ...). + */ + unsigned char step = 0; + unsigned long mask = nsAttsSize - 1; + j = uriHash & mask; /* index into hash table */ + while (nsAtts[j].version == version) { + /* for speed we compare stored hash values first */ + if (uriHash == nsAtts[j].hash) { + const XML_Char *s1 = poolStart(&tempPool); + const XML_Char *s2 = nsAtts[j].uriName; + /* s1 is null terminated, but not s2 */ + for (; *s1 == *s2 && *s1 != 0; s1++, s2++); + if (*s1 == 0) + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + if (!step) + step = PROBE_STEP(uriHash, mask, nsAttsPower); + j < step ? (j += nsAttsSize - step) : (j -= step); + } + } + + if (ns_triplets) { /* append namespace separator and prefix */ + tempPool.ptr[-1] = namespaceSeparator; + s = b->prefix->name; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + } + + /* store expanded name in attribute list */ + s = poolStart(&tempPool); + poolFinish(&tempPool); + appAtts[i] = s; + + /* fill empty slot with new version, uriName and hash value */ + nsAtts[j].version = version; + nsAtts[j].hash = uriHash; + nsAtts[j].uriName = s; + + if (!--nPrefixes) { + i += 2; + break; + } + } + else /* not prefixed */ + ((XML_Char *)s)[-1] = 0; /* clear flag */ + } + } + /* clear flags for the remaining attributes */ + for (; i < attIndex; i += 2) + ((XML_Char *)(appAtts[i]))[-1] = 0; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + + if (!ns) + return XML_ERROR_NONE; + + /* expand the element type name */ + if (elementType->prefix) { + binding = elementType->prefix->binding; + if (!binding) + return XML_ERROR_UNBOUND_PREFIX; + localPart = tagNamePtr->str; + while (*localPart++ != XML_T(':')) + ; + } + else if (dtd->defaultPrefix.binding) { + binding = dtd->defaultPrefix.binding; + localPart = tagNamePtr->str; + } + else + return XML_ERROR_NONE; + prefixLen = 0; + if (ns_triplets && binding->prefix->name) { + for (; binding->prefix->name[prefixLen++];) + ; /* prefixLen includes null terminator */ + } + tagNamePtr->localPart = localPart; + tagNamePtr->uriLen = binding->uriLen; + tagNamePtr->prefix = binding->prefix->name; + tagNamePtr->prefixLen = prefixLen; + for (i = 0; localPart[i++];) + ; /* i includes null terminator */ + n = i + binding->uriLen + prefixLen; + if (n > binding->uriAlloc) { + TAG *p; + uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); + if (!uri) + return XML_ERROR_NO_MEMORY; + binding->uriAlloc = n + EXPAND_SPARE; + memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); + for (p = tagStack; p; p = p->parent) + if (p->name.str == binding->uri) + p->name.str = uri; + FREE(binding->uri); + binding->uri = uri; + } + /* if namespaceSeparator != '\0' then uri includes it already */ + uri = binding->uri + binding->uriLen; + memcpy(uri, localPart, i * sizeof(XML_Char)); + /* we always have a namespace separator between localPart and prefix */ + if (prefixLen) { + uri += i - 1; + *uri = namespaceSeparator; /* replace null terminator */ + memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); + } + tagNamePtr->str = binding->uri; + return XML_ERROR_NONE; +} + +/* addBinding() overwrites the value of prefix->binding without checking. + Therefore one must keep track of the old value outside of addBinding(). +*/ +static enum XML_Error +addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + const XML_Char *uri, BINDING **bindingsPtr) +{ + static const XML_Char xmlNamespace[] = { + 'h', 't', 't', 'p', ':', '/', '/', + 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', + 'X', 'M', 'L', '/', '1', '9', '9', '8', '/', + 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' + }; + static const int xmlLen = + (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1; + static const XML_Char xmlnsNamespace[] = { + 'h', 't', 't', 'p', ':', '/', '/', + 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r', 'g', '/', + '2', '0', '0', '0', '/', 'x', 'm', 'l', 'n', 's', '/', '\0' + }; + static const int xmlnsLen = + (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1; + + XML_Bool mustBeXML = XML_FALSE; + XML_Bool isXML = XML_TRUE; + XML_Bool isXMLNS = XML_TRUE; + + BINDING *b; + int len; + + /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ + if (*uri == XML_T('\0') && prefix->name) + return XML_ERROR_UNDECLARING_PREFIX; + + if (prefix->name + && prefix->name[0] == XML_T('x') + && prefix->name[1] == XML_T('m') + && prefix->name[2] == XML_T('l')) { + + /* Not allowed to bind xmlns */ + if (prefix->name[3] == XML_T('n') + && prefix->name[4] == XML_T('s') + && prefix->name[5] == XML_T('\0')) + return XML_ERROR_RESERVED_PREFIX_XMLNS; + + if (prefix->name[3] == XML_T('\0')) + mustBeXML = XML_TRUE; + } + + for (len = 0; uri[len]; len++) { + if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len])) + isXML = XML_FALSE; + + if (!mustBeXML && isXMLNS + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; + } + isXML = isXML && len == xmlLen; + isXMLNS = isXMLNS && len == xmlnsLen; + + if (mustBeXML != isXML) + return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML + : XML_ERROR_RESERVED_NAMESPACE_URI; + + if (isXMLNS) + return XML_ERROR_RESERVED_NAMESPACE_URI; + + if (namespaceSeparator) + len++; + if (freeBindingList) { + b = freeBindingList; + if (len > b->uriAlloc) { + XML_Char *temp = (XML_Char *)REALLOC(b->uri, + sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + b->uri = temp; + b->uriAlloc = len + EXPAND_SPARE; + } + freeBindingList = b->nextTagBinding; + } + else { + b = (BINDING *)MALLOC(sizeof(BINDING)); + if (!b) + return XML_ERROR_NO_MEMORY; + b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) { + FREE(b); + return XML_ERROR_NO_MEMORY; + } + b->uriAlloc = len + EXPAND_SPARE; + } + b->uriLen = len; + memcpy(b->uri, uri, len * sizeof(XML_Char)); + if (namespaceSeparator) + b->uri[len - 1] = namespaceSeparator; + b->prefix = prefix; + b->attId = attId; + b->prevPrefixBinding = prefix->binding; + /* NULL binding when default namespace undeclared */ + if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix) + prefix->binding = NULL; + else + prefix->binding = b; + b->nextTagBinding = *bindingsPtr; + *bindingsPtr = b; + /* if attId == NULL then we are not starting a namespace scope */ + if (attId && startNamespaceDeclHandler) + startNamespaceDeclHandler(handlerArg, prefix->name, + prefix->binding ? uri : 0); + return XML_ERROR_NONE; +} + +/* The idea here is to avoid using stack for each CDATA section when + the whole file is parsed with one call. +*/ +static enum XML_Error PTRCALL +cdataSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doCdataSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result != XML_ERROR_NONE) + return result; + if (start) { + if (parentParser) { /* we are parsing an external entity */ + processor = externalEntityContentProcessor; + return externalEntityContentProcessor(parser, start, end, endPtr); + } + else { + processor = contentProcessor; + return contentProcessor(parser, start, end, endPtr); + } + } + return result; +} + +/* startPtr gets set to non-null if the section is closed, and to null if + the section is not yet closed. +*/ +static enum XML_Error +doCdataSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + + for (;;) { + const char *next; + int tok = XmlCdataSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_CDATA_SECT_CLOSE: + if (endCdataSectionHandler) + endCdataSectionHandler(handlerArg); +#if 0 + /* see comment under XML_TOK_CDATA_SECT_OPEN */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = next; + characterDataHandler(handlerArg, dataBuf, + (int)(dataPtr - (ICHAR *)dataBuf)); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (int)((XML_Char *)next - (XML_Char *)s)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_CDATA_SECTION; + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + + *eventPP = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } + /* not reached */ +} + +#ifdef XML_DTD + +/* The idea here is to avoid using stack for each IGNORE section when + the whole file is parsed with one call. +*/ +static enum XML_Error PTRCALL +ignoreSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, + endPtr, (XML_Bool)!ps_finalBuffer); + if (result != XML_ERROR_NONE) + return result; + if (start) { + processor = prologProcessor; + return prologProcessor(parser, start, end, endPtr); + } + return result; +} + +/* startPtr gets set to non-null is the section is closed, and to null + if the section is not yet closed. +*/ +static enum XML_Error +doIgnoreSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr, + XML_Bool haveMore) +{ + const char *next; + int tok; + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = NULL; + tok = XmlIgnoreSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_IGNORE_SECT: + if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + *nextPtr = next; + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + else + return XML_ERROR_NONE; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (haveMore) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + /* not reached */ +} + +#endif /* XML_DTD */ + +static enum XML_Error +initializeEncoding(XML_Parser parser) +{ + const char *s; +#ifdef XML_UNICODE + char encodingBuf[128]; + if (!protocolEncodingName) + s = NULL; + else { + int i; + for (i = 0; protocolEncodingName[i]; i++) { + if (i == sizeof(encodingBuf) - 1 + || (protocolEncodingName[i] & ~0x7f) != 0) { + encodingBuf[0] = '\0'; + break; + } + encodingBuf[i] = (char)protocolEncodingName[i]; + } + encodingBuf[i] = '\0'; + s = encodingBuf; + } +#else + s = protocolEncodingName; +#endif + if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) + return XML_ERROR_NONE; + return handleUnknownEncoding(parser, protocolEncodingName); +} + +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, + const char *s, const char *next) +{ + const char *encodingName = NULL; + const XML_Char *storedEncName = NULL; + const ENCODING *newEncoding = NULL; + const char *version = NULL; + const char *versionend; + const XML_Char *storedversion = NULL; + int standalone = -1; + if (!(ns + ? XmlParseXmlDeclNS + : XmlParseXmlDecl)(isGeneralTextEntity, + encoding, + s, + next, + &eventPtr, + &version, + &versionend, + &encodingName, + &newEncoding, + &standalone)) { + if (isGeneralTextEntity) + return XML_ERROR_TEXT_DECL; + else + return XML_ERROR_XML_DECL; + } + if (!isGeneralTextEntity && standalone == 1) { + _dtd->standalone = XML_TRUE; +#ifdef XML_DTD + if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif /* XML_DTD */ + } + if (xmlDeclHandler) { + if (encodingName != NULL) { + storedEncName = poolStoreString(&temp2Pool, + encoding, + encodingName, + encodingName + + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + poolFinish(&temp2Pool); + } + if (version) { + storedversion = poolStoreString(&temp2Pool, + encoding, + version, + versionend - encoding->minBytesPerChar); + if (!storedversion) + return XML_ERROR_NO_MEMORY; + } + xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); + } + else if (defaultHandler) + reportDefault(parser, encoding, s, next); + if (protocolEncodingName == NULL) { + if (newEncoding) { + if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { + eventPtr = encodingName; + return XML_ERROR_INCORRECT_ENCODING; + } + encoding = newEncoding; + } + else if (encodingName) { + enum XML_Error result; + if (!storedEncName) { + storedEncName = poolStoreString( + &temp2Pool, encoding, encodingName, + encodingName + XmlNameLength(encoding, encodingName)); + if (!storedEncName) + return XML_ERROR_NO_MEMORY; + } + result = handleUnknownEncoding(parser, storedEncName); + poolClear(&temp2Pool); + if (result == XML_ERROR_UNKNOWN_ENCODING) + eventPtr = encodingName; + return result; + } + } + + if (storedEncName || storedversion) + poolClear(&temp2Pool); + + return XML_ERROR_NONE; +} + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (unknownEncodingHandler) { + XML_Encoding info; + int i; + for (i = 0; i < 256; i++) + info.map[i] = -1; + info.convert = NULL; + info.data = NULL; + info.release = NULL; + if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, + &info)) { + ENCODING *enc; + unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); + if (!unknownEncodingMem) { + if (info.release) + info.release(info.data); + return XML_ERROR_NO_MEMORY; + } + enc = (ns + ? XmlInitUnknownEncodingNS + : XmlInitUnknownEncoding)(unknownEncodingMem, + info.map, + info.convert, + info.data); + if (enc) { + unknownEncodingData = info.data; + unknownEncodingRelease = info.release; + encoding = enc; + return XML_ERROR_NONE; + } + } + if (info.release != NULL) + info.release(info.data); + } + return XML_ERROR_UNKNOWN_ENCODING; +} + +static enum XML_Error PTRCALL +prologInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = prologProcessor; + return prologProcessor(parser, s, end, nextPtr); +} + +#ifdef XML_DTD + +static enum XML_Error PTRCALL +externalParEntInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + + /* we know now that XML_Parse(Buffer) has been called, + so we consider the external parameter entity read */ + _dtd->paramEntityRead = XML_TRUE; + + if (prologState.inEntityValue) { + processor = entityValueInitProcessor; + return entityValueInitProcessor(parser, s, end, nextPtr); + } + else { + processor = externalParEntProcessor; + return externalParEntProcessor(parser, s, end, nextPtr); + } +} + +static enum XML_Error PTRCALL +entityValueInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + int tok; + const char *start = s; + const char *next = start; + eventPtr = start; + + for (;;) { + tok = XmlPrologTok(encoding, start, end, &next); + eventEndPtr = next; + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, encoding, s, end); + } + else if (tok == XML_TOK_XML_DECL) { + enum XML_Error result; + result = processXmlDecl(parser, 0, start, next); + if (result != XML_ERROR_NONE) + return result; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + *nextPtr = next; + } + /* stop scanning for text declaration - we found one */ + processor = entityValueProcessor; + return entityValueProcessor(parser, next, end, nextPtr); + } + /* If we are at the end of the buffer, this would cause XmlPrologTok to + return XML_TOK_NONE on the next call, which would then cause the + function to exit with *nextPtr set to s - that is what we want for other + tokens, but not for the BOM - we would rather like to skip it; + then, when this routine is entered the next time, XmlPrologTok will + return XML_TOK_INVALID, since the BOM is still in the buffer + */ + else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) { + *nextPtr = next; + return XML_ERROR_NONE; + } + start = next; + eventPtr = start; + } +} + +static enum XML_Error PTRCALL +externalParEntProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *next = s; + int tok; + + tok = XmlPrologTok(encoding, s, end, &next); + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + } + /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. + However, when parsing an external subset, doProlog will not accept a BOM + as valid, and report a syntax error, so we have to skip the BOM + */ + else if (tok == XML_TOK_BOM) { + s = next; + tok = XmlPrologTok(encoding, s, end, &next); + } + + processor = prologProcessor; + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!ps_finalBuffer); +} + +static enum XML_Error PTRCALL +entityValueProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *start = s; + const char *next = s; + const ENCODING *enc = encoding; + int tok; + + for (;;) { + tok = XmlPrologTok(enc, start, end, &next); + if (tok <= 0) { + if (!ps_finalBuffer && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: /* start == end */ + default: + break; + } + /* found end of entity value - can store it now */ + return storeEntityValue(parser, enc, s, end); + } + start = next; + } +} + +#endif /* XML_DTD */ + +static enum XML_Error PTRCALL +prologProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *next = s; + int tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, + nextPtr, (XML_Bool)!ps_finalBuffer); +} + +static enum XML_Error +doProlog(XML_Parser parser, + const ENCODING *enc, + const char *s, + const char *end, + int tok, + const char *next, + const char **nextPtr, + XML_Bool haveMore) +{ +#ifdef XML_DTD + static const XML_Char externalSubsetName[] = { '#' , '\0' }; +#endif /* XML_DTD */ + static const XML_Char atypeCDATA[] = { 'C', 'D', 'A', 'T', 'A', '\0' }; + static const XML_Char atypeID[] = { 'I', 'D', '\0' }; + static const XML_Char atypeIDREF[] = { 'I', 'D', 'R', 'E', 'F', '\0' }; + static const XML_Char atypeIDREFS[] = { 'I', 'D', 'R', 'E', 'F', 'S', '\0' }; + static const XML_Char atypeENTITY[] = { 'E', 'N', 'T', 'I', 'T', 'Y', '\0' }; + static const XML_Char atypeENTITIES[] = + { 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S', '\0' }; + static const XML_Char atypeNMTOKEN[] = { + 'N', 'M', 'T', 'O', 'K', 'E', 'N', '\0' }; + static const XML_Char atypeNMTOKENS[] = { + 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S', '\0' }; + static const XML_Char notationPrefix[] = { + 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N', '(', '\0' }; + static const XML_Char enumValueSep[] = { '|', '\0' }; + static const XML_Char enumValueStart[] = { '(', '\0' }; + + /* save one level of indirection */ + DTD * const dtd = _dtd; + + const char **eventPP; + const char **eventEndPP; + enum XML_Content_Quant quant; + + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + + for (;;) { + int role; + XML_Bool handleDefault = XML_TRUE; + *eventPP = s; + *eventEndPP = next; + if (tok <= 0) { + if (haveMore && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: +#ifdef XML_DTD + /* for internal PE NOT referenced between declarations */ + if (enc != encoding && !openInternalEntities->betweenDecl) { + *nextPtr = s; + return XML_ERROR_NONE; + } + /* WFC: PE Between Declarations - must check that PE contains + complete markup, not only for external PEs, but also for + internal PEs if the reference occurs between declarations. + */ + if (isParamEntity || enc != encoding) { + if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) + == XML_ROLE_ERROR) + return XML_ERROR_INCOMPLETE_PE; + *nextPtr = s; + return XML_ERROR_NONE; + } +#endif /* XML_DTD */ + return XML_ERROR_NO_ELEMENTS; + default: + tok = -tok; + next = end; + break; + } + } + role = XmlTokenRole(&prologState, tok, s, next, enc); + switch (role) { + case XML_ROLE_XML_DECL: + { + enum XML_Error result = processXmlDecl(parser, 0, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_NAME: + if (startDoctypeDeclHandler) { + doctypeName = poolStoreString(&tempPool, enc, s, next); + if (!doctypeName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + doctypePubid = NULL; + handleDefault = XML_FALSE; + } + doctypeSysid = NULL; /* always initialize to NULL */ + break; + case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: + if (startDoctypeDeclHandler) { + startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, + doctypePubid, 1); + doctypeName = NULL; + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + break; +#ifdef XML_DTD + case XML_ROLE_TEXT_DECL: + { + enum XML_Error result = processXmlDecl(parser, 1, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + handleDefault = XML_FALSE; + } + break; +#endif /* XML_DTD */ + case XML_ROLE_DOCTYPE_PUBLIC_ID: +#ifdef XML_DTD + useForeignDTD = XML_FALSE; + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; +#endif /* XML_DTD */ + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + doctypePubid = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!doctypePubid) + return XML_ERROR_NO_MEMORY; + normalizePublicId((XML_Char *)doctypePubid); + poolFinish(&tempPool); + handleDefault = XML_FALSE; + goto alreadyChecked; + } + /* fall through */ + case XML_ROLE_ENTITY_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + alreadyChecked: + if (dtd->keepProcessing && declEntity) { + XML_Char *tem = poolStoreString(&dtd->pool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declEntity->publicId = tem; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_DOCTYPE_CLOSE: + if (doctypeName) { + startDoctypeDeclHandler(handlerArg, doctypeName, + doctypeSysid, doctypePubid, 0); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + /* doctypeSysid will be non-NULL in the case of a previous + XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler + was not set, indicating an external subset + */ +#ifdef XML_DTD + if (doctypeSysid || useForeignDTD) { + XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; + dtd->hasParamEntityRefs = XML_TRUE; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + if (useForeignDTD) + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead) { + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + } + /* if we didn't read the foreign DTD then this means that there + is no external subset and we must reset dtd->hasParamEntityRefs + */ + else if (!doctypeSysid) + dtd->hasParamEntityRefs = hadParamEntityRefs; + /* end of DTD - no need to update dtd->keepProcessing */ + } + useForeignDTD = XML_FALSE; + } +#endif /* XML_DTD */ + if (endDoctypeDeclHandler) { + endDoctypeDeclHandler(handlerArg); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_INSTANCE_START: +#ifdef XML_DTD + /* if there is no DOCTYPE declaration then now is the + last chance to read the foreign DTD + */ + if (useForeignDTD) { + XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; + dtd->hasParamEntityRefs = XML_TRUE; + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!entity) + return XML_ERROR_NO_MEMORY; + entity->base = curBase; + dtd->paramEntityRead = XML_FALSE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + if (dtd->paramEntityRead) { + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + } + /* if we didn't read the foreign DTD then this means that there + is no external subset and we must reset dtd->hasParamEntityRefs + */ + else + dtd->hasParamEntityRefs = hadParamEntityRefs; + /* end of DTD - no need to update dtd->keepProcessing */ + } + } +#endif /* XML_DTD */ + processor = contentProcessor; + return contentProcessor(parser, s, end, nextPtr); + case XML_ROLE_ATTLIST_ELEMENT_NAME: + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_NAME: + declAttributeId = getAttributeId(parser, enc, s, next); + if (!declAttributeId) + return XML_ERROR_NO_MEMORY; + declAttributeIsCdata = XML_FALSE; + declAttributeType = NULL; + declAttributeIsId = XML_FALSE; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_CDATA: + declAttributeIsCdata = XML_TRUE; + declAttributeType = atypeCDATA; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ID: + declAttributeIsId = XML_TRUE; + declAttributeType = atypeID; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREF: + declAttributeType = atypeIDREF; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: + declAttributeType = atypeIDREFS; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: + declAttributeType = atypeENTITY; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: + declAttributeType = atypeENTITIES; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: + declAttributeType = atypeNMTOKEN; + goto checkAttListDeclHandler; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: + declAttributeType = atypeNMTOKENS; + checkAttListDeclHandler: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTRIBUTE_ENUM_VALUE: + case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: + if (dtd->keepProcessing && attlistDeclHandler) { + const XML_Char *prefix; + if (declAttributeType) { + prefix = enumValueSep; + } + else { + prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE + ? notationPrefix + : enumValueStart); + } + if (!poolAppendString(&tempPool, prefix)) + return XML_ERROR_NO_MEMORY; + if (!poolAppend(&tempPool, enc, s, next)) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: + case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, declAttributeIsId, + 0, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T('(') + || (*declAttributeType == XML_T('N') + && declAttributeType[1] == XML_T('O'))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(')')) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: + case XML_ROLE_FIXED_ATTRIBUTE_VALUE: + if (dtd->keepProcessing) { + const XML_Char *attVal; + enum XML_Error result = + storeAttributeValue(parser, enc, declAttributeIsCdata, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar, + &dtd->pool); + if (result) + return result; + attVal = poolStart(&dtd->pool); + poolFinish(&dtd->pool); + /* ID attributes aren't allowed to have a default */ + if (!defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, XML_FALSE, attVal, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == XML_T('(') + || (*declAttributeType == XML_T('N') + && declAttributeType[1] == XML_T('O'))) { + /* Enumerated or Notation type */ + if (!poolAppendChar(&tempPool, XML_T(')')) + || !poolAppendChar(&tempPool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + attVal, + role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_ENTITY_VALUE: + if (dtd->keepProcessing) { + enum XML_Error result = storeEntityValue(parser, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (declEntity) { + declEntity->textPtr = poolStart(&dtd->entityValuePool); + declEntity->textLen = (int)(poolLength(&dtd->entityValuePool)); + poolFinish(&dtd->entityValuePool); + if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + declEntity->textPtr, + declEntity->textLen, + curBase, 0, 0, 0); + handleDefault = XML_FALSE; + } + } + else + poolDiscard(&dtd->entityValuePool); + if (result != XML_ERROR_NONE) + return result; + } + break; + case XML_ROLE_DOCTYPE_SYSTEM_ID: +#ifdef XML_DTD + useForeignDTD = XML_FALSE; +#endif /* XML_DTD */ + dtd->hasParamEntityRefs = XML_TRUE; + if (startDoctypeDeclHandler) { + doctypeSysid = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (doctypeSysid == NULL) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } +#ifdef XML_DTD + else + /* use externalSubsetName to make doctypeSysid non-NULL + for the case where no startDoctypeDeclHandler is set */ + doctypeSysid = externalSubsetName; +#endif /* XML_DTD */ + if (!dtd->standalone +#ifdef XML_DTD + && !paramEntityParsing +#endif /* XML_DTD */ + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; +#ifndef XML_DTD + break; +#else /* XML_DTD */ + if (!declEntity) { + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + declEntity->publicId = NULL; + } + /* fall through */ +#endif /* XML_DTD */ + case XML_ROLE_ENTITY_SYSTEM_ID: + if (dtd->keepProcessing && declEntity) { + declEntity->systemId = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!declEntity->systemId) + return XML_ERROR_NO_MEMORY; + declEntity->base = curBase; + poolFinish(&dtd->pool); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_COMPLETE: + if (dtd->keepProcessing && declEntity && entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + 0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + 0); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_ENTITY_NOTATION_NAME: + if (dtd->keepProcessing && declEntity) { + declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); + if (!declEntity->notation) + return XML_ERROR_NO_MEMORY; + poolFinish(&dtd->pool); + if (unparsedEntityDeclHandler) { + *eventEndPP = s; + unparsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; + } + else if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + 0,0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + handleDefault = XML_FALSE; + } + } + break; + case XML_ROLE_GENERAL_ENTITY_NAME: + { + if (XmlPredefinedEntityName(enc, s, next)) { + declEntity = NULL; + break; + } + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(&dtd->generalEntities, name, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_FALSE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + } + break; + case XML_ROLE_PARAM_ENTITY_NAME: +#ifdef XML_DTD + if (dtd->keepProcessing) { + const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(&dtd->paramEntities, + name, sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd->pool); + declEntity = NULL; + } + else { + poolFinish(&dtd->pool); + declEntity->publicId = NULL; + declEntity->is_param = XML_TRUE; + /* if we have a parent parser or are reading an internal parameter + entity, then the entity declaration is not considered "internal" + */ + declEntity->is_internal = !(parentParser || openInternalEntities); + if (entityDeclHandler) + handleDefault = XML_FALSE; + } + } + else { + poolDiscard(&dtd->pool); + declEntity = NULL; + } +#else /* not XML_DTD */ + declEntity = NULL; +#endif /* XML_DTD */ + break; + case XML_ROLE_NOTATION_NAME: + declNotationPublicId = NULL; + declNotationName = NULL; + if (notationDeclHandler) { + declNotationName = poolStoreString(&tempPool, enc, s, next); + if (!declNotationName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_PUBLICID; + if (declNotationName) { /* means notationDeclHandler != NULL */ + XML_Char *tem = poolStoreString(&tempPool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declNotationPublicId = tem; + poolFinish(&tempPool); + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_NOTATION_SYSTEM_ID: + if (declNotationName && notationDeclHandler) { + const XML_Char *systemId + = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!systemId) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + systemId, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_NOTATION_NO_SYSTEM_ID: + if (declNotationPublicId && notationDeclHandler) { + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + 0, + declNotationPublicId); + handleDefault = XML_FALSE; + } + poolClear(&tempPool); + break; + case XML_ROLE_ERROR: + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + /* PE references in internal subset are + not allowed within declarations. */ + return XML_ERROR_PARAM_ENTITY_REF; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + default: + return XML_ERROR_SYNTAX; + } +#ifdef XML_DTD + case XML_ROLE_IGNORE_SECT: + { + enum XML_Error result; + if (defaultHandler) + reportDefault(parser, enc, s, next); + handleDefault = XML_FALSE; + result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); + if (result != XML_ERROR_NONE) + return result; + else if (!next) { + processor = ignoreSectionProcessor; + return result; + } + } + break; +#endif /* XML_DTD */ + case XML_ROLE_GROUP_OPEN: + if (prologState.level >= groupSize) { + if (groupSize) { + char *temp = (char *)REALLOC(groupConnector, groupSize *= 2); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + groupConnector = temp; + if (dtd->scaffIndex) { + int *temp = (int *)REALLOC(dtd->scaffIndex, + groupSize * sizeof(int)); + if (temp == NULL) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex = temp; + } + } + else { + groupConnector = (char *)MALLOC(groupSize = 32); + if (!groupConnector) + return XML_ERROR_NO_MEMORY; + } + } + groupConnector[prologState.level] = 0; + if (dtd->in_eldecl) { + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffIndex[dtd->scaffLevel] = myindex; + dtd->scaffLevel++; + dtd->scaffold[myindex].type = XML_CTYPE_SEQ; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + case XML_ROLE_GROUP_SEQUENCE: + if (groupConnector[prologState.level] == '|') + return XML_ERROR_SYNTAX; + groupConnector[prologState.level] = ','; + if (dtd->in_eldecl && elementDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_GROUP_CHOICE: + if (groupConnector[prologState.level] == ',') + return XML_ERROR_SYNTAX; + if (dtd->in_eldecl + && !groupConnector[prologState.level] + && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + != XML_CTYPE_MIXED) + ) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_CHOICE; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + groupConnector[prologState.level] = '|'; + break; + case XML_ROLE_PARAM_ENTITY_REF: +#ifdef XML_DTD + case XML_ROLE_INNER_PARAM_ENTITY_REF: + dtd->hasParamEntityRefs = XML_TRUE; + if (!paramEntityParsing) + dtd->keepProcessing = dtd->standalone; + else { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&dtd->pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); + poolDiscard(&dtd->pool); + /* first, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal, + otherwise call the skipped entity handler + */ + if (prologState.documentEntity && + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs)) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + dtd->keepProcessing = dtd->standalone; + /* cannot report skipped entities in declarations */ + if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) { + skippedEntityHandler(handlerArg, name, 1); + handleDefault = XML_FALSE; + } + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + XML_Bool betweenDecl = + (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); + result = processInternalEntity(parser, entity, betweenDecl); + if (result != XML_ERROR_NONE) + return result; + handleDefault = XML_FALSE; + break; + } + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + entity->open = XML_FALSE; + handleDefault = XML_FALSE; + if (!dtd->paramEntityRead) { + dtd->keepProcessing = dtd->standalone; + break; + } + } + else { + dtd->keepProcessing = dtd->standalone; + break; + } + } +#endif /* XML_DTD */ + if (!dtd->standalone && + notStandaloneHandler && + !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + break; + + /* Element declaration stuff */ + + case XML_ROLE_ELEMENT_NAME: + if (elementDeclHandler) { + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + dtd->scaffLevel = 0; + dtd->scaffCount = 0; + dtd->in_eldecl = XML_TRUE; + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ANY: + case XML_ROLE_CONTENT_EMPTY: + if (dtd->in_eldecl) { + if (elementDeclHandler) { + XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); + if (!content) + return XML_ERROR_NO_MEMORY; + content->quant = XML_CQUANT_NONE; + content->name = NULL; + content->numchildren = 0; + content->children = NULL; + content->type = ((role == XML_ROLE_CONTENT_ANY) ? + XML_CTYPE_ANY : + XML_CTYPE_EMPTY); + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, content); + handleDefault = XML_FALSE; + } + dtd->in_eldecl = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_PCDATA: + if (dtd->in_eldecl) { + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type + = XML_CTYPE_MIXED; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_CONTENT_ELEMENT: + quant = XML_CQUANT_NONE; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_OPT: + quant = XML_CQUANT_OPT; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_REP: + quant = XML_CQUANT_REP; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_PLUS: + quant = XML_CQUANT_PLUS; + elementContent: + if (dtd->in_eldecl) { + ELEMENT_TYPE *el; + const XML_Char *name; + int nameLen; + const char *nxt = (quant == XML_CQUANT_NONE + ? next + : next - enc->minBytesPerChar); + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd->scaffold[myindex].type = XML_CTYPE_NAME; + dtd->scaffold[myindex].quant = quant; + el = getElementType(parser, enc, s, nxt); + if (!el) + return XML_ERROR_NO_MEMORY; + name = el->name; + dtd->scaffold[myindex].name = name; + nameLen = 0; + for (; name[nameLen++]; ); + dtd->contentStringLen += nameLen; + if (elementDeclHandler) + handleDefault = XML_FALSE; + } + break; + + case XML_ROLE_GROUP_CLOSE: + quant = XML_CQUANT_NONE; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_OPT: + quant = XML_CQUANT_OPT; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_REP: + quant = XML_CQUANT_REP; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_PLUS: + quant = XML_CQUANT_PLUS; + closeGroup: + if (dtd->in_eldecl) { + if (elementDeclHandler) + handleDefault = XML_FALSE; + dtd->scaffLevel--; + dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; + if (dtd->scaffLevel == 0) { + if (!handleDefault) { + XML_Content *model = build_model(parser); + if (!model) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, model); + } + dtd->in_eldecl = XML_FALSE; + dtd->contentStringLen = 0; + } + } + break; + /* End element declaration stuff */ + + case XML_ROLE_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + handleDefault = XML_FALSE; + break; + case XML_ROLE_NONE: + switch (tok) { + case XML_TOK_BOM: + handleDefault = XML_FALSE; + break; + } + break; + case XML_ROLE_DOCTYPE_NONE: + if (startDoctypeDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ENTITY_NONE: + if (dtd->keepProcessing && entityDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_NOTATION_NONE: + if (notationDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ATTLIST_NONE: + if (dtd->keepProcessing && attlistDeclHandler) + handleDefault = XML_FALSE; + break; + case XML_ROLE_ELEMENT_NONE: + if (elementDeclHandler) + handleDefault = XML_FALSE; + break; + } /* end of big switch */ + + if (handleDefault && defaultHandler) + reportDefault(parser, enc, s, next); + + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: + s = next; + tok = XmlPrologTok(enc, s, end, &next); + } + } + /* not reached */ +} + +static enum XML_Error PTRCALL +epilogProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + processor = epilogProcessor; + eventPtr = s; + for (;;) { + const char *next = NULL; + int tok = XmlPrologTok(encoding, s, end, &next); + eventEndPtr = next; + switch (tok) { + /* report partial linebreak - it might be the last token */ + case -XML_TOK_PROLOG_S: + if (defaultHandler) { + reportDefault(parser, encoding, s, next); + if (ps_parsing == XML_FINISHED) + return XML_ERROR_ABORTED; + } + *nextPtr = next; + return XML_ERROR_NONE; + case XML_TOK_NONE: + *nextPtr = s; + return XML_ERROR_NONE; + case XML_TOK_PROLOG_S: + if (defaultHandler) + reportDefault(parser, encoding, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_INVALID: + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (!ps_finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (!ps_finalBuffer) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + default: + return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; + } + eventPtr = s = next; + switch (ps_parsing) { + case XML_SUSPENDED: + *nextPtr = next; + return XML_ERROR_NONE; + case XML_FINISHED: + return XML_ERROR_ABORTED; + default: ; + } + } +} + +static enum XML_Error +processInternalEntity(XML_Parser parser, ENTITY *entity, + XML_Bool betweenDecl) +{ + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity; + + if (freeInternalEntities) { + openEntity = freeInternalEntities; + freeInternalEntities = openEntity->next; + } + else { + openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY)); + if (!openEntity) + return XML_ERROR_NO_MEMORY; + } + entity->open = XML_TRUE; + entity->processed = 0; + openEntity->next = openInternalEntities; + openInternalEntities = openEntity; + openEntity->entity = entity; + openEntity->startTagLevel = tagLevel; + openEntity->betweenDecl = betweenDecl; + openEntity->internalEventPtr = NULL; + openEntity->internalEventEndPtr = NULL; + textStart = (char *)entity->textPtr; + textEnd = (char *)(entity->textPtr + entity->textLen); + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, tagLevel, internalEncoding, textStart, + textEnd, &next, XML_FALSE); + + if (result == XML_ERROR_NONE) { + if (textEnd != next && ps_parsing == XML_SUSPENDED) { + entity->processed = (int)(next - textStart); + processor = internalEntityProcessor; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + } + return result; +} + +static enum XML_Error PTRCALL +internalEntityProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + ENTITY *entity; + const char *textStart, *textEnd; + const char *next; + enum XML_Error result; + OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities; + if (!openEntity) + return XML_ERROR_UNEXPECTED_STATE; + + entity = openEntity->entity; + textStart = ((char *)entity->textPtr) + entity->processed; + textEnd = (char *)(entity->textPtr + entity->textLen); + +#ifdef XML_DTD + if (entity->is_param) { + int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next); + result = doProlog(parser, internalEncoding, textStart, textEnd, tok, + next, &next, XML_FALSE); + } + else +#endif /* XML_DTD */ + result = doContent(parser, openEntity->startTagLevel, internalEncoding, + textStart, textEnd, &next, XML_FALSE); + + if (result != XML_ERROR_NONE) + return result; + else if (textEnd != next && ps_parsing == XML_SUSPENDED) { + entity->processed = (int)(next - (char *)entity->textPtr); + return result; + } + else { + entity->open = XML_FALSE; + openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = freeInternalEntities; + freeInternalEntities = openEntity; + } + +#ifdef XML_DTD + if (entity->is_param) { + int tok; + processor = prologProcessor; + tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, nextPtr, + (XML_Bool)!ps_finalBuffer); + } + else +#endif /* XML_DTD */ + { + processor = contentProcessor; + /* see externalEntityContentProcessor vs contentProcessor */ + return doContent(parser, parentParser ? 1 : 0, encoding, s, end, + nextPtr, (XML_Bool)!ps_finalBuffer); + } +} + +static enum XML_Error PTRCALL +errorProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + UNUSED(s); + UNUSED(end); + UNUSED(nextPtr); + + return errorCode; +} + +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, + end, pool); + if (result) + return result; + if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) + poolChop(pool); + if (!poolAppendChar(pool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + return XML_ERROR_NONE; +} + +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + for (;;) { + const char *next; + int tok = XmlAttributeValueTok(enc, ptr, end, &next); + switch (tok) { + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, ptr); + if (n < 0) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + if (!isCdata + && n == 0x20 /* space */ + && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (!poolAppendChar(pool, buf[i])) + return XML_ERROR_NO_MEMORY; + } + } + break; + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, ptr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = ptr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_ATTRIBUTE_VALUE_S: + case XML_TOK_DATA_NEWLINE: + if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + if (!poolAppendChar(pool, 0x20)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + char checkEntityDecl; + XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (!poolAppendChar(pool, ch)) + return XML_ERROR_NO_MEMORY; + break; + } + name = poolStoreString(&temp2Pool, enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0); + poolDiscard(&temp2Pool); + /* First, determine if a check for an existing declaration is needed; + if yes, check that the entity exists, and that it is internal. + */ + if (pool == &dtd->pool) /* are we called from prolog? */ + checkEntityDecl = +#ifdef XML_DTD + prologState.documentEntity && +#endif /* XML_DTD */ + (dtd->standalone + ? !openInternalEntities + : !dtd->hasParamEntityRefs); + else /* if (pool == &tempPool): we are called from content */ + checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone; + if (checkEntityDecl) { + if (!entity) + return XML_ERROR_UNDEFINED_ENTITY; + else if (!entity->is_internal) + return XML_ERROR_ENTITY_DECLARED_IN_PE; + } + else if (!entity) { + /* Cannot report skipped entity here - see comments on + skippedEntityHandler. + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + /* Cannot call the default handler because this would be + out of sync with the call to the startElementHandler. + if ((pool == &tempPool) && defaultHandler) + reportDefault(parser, enc, ptr, next); + */ + break; + } + if (entity->open) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + if (entity->notation) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BINARY_ENTITY_REF; + } + if (!entity->textPtr) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; + } + else { + enum XML_Error result; + const XML_Char *textEnd = entity->textPtr + entity->textLen; + entity->open = XML_TRUE; + result = appendAttributeValue(parser, internalEncoding, isCdata, + (char *)entity->textPtr, + (char *)textEnd, pool); + entity->open = XML_FALSE; + if (result) + return result; + } + } + break; + default: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_UNEXPECTED_STATE; + } + ptr = next; + } + /* not reached */ +} + +static enum XML_Error +storeEntityValue(XML_Parser parser, + const ENCODING *enc, + const char *entityTextPtr, + const char *entityTextEnd) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + STRING_POOL *pool = &(dtd->entityValuePool); + enum XML_Error result = XML_ERROR_NONE; +#ifdef XML_DTD + int oldInEntityValue = prologState.inEntityValue; + prologState.inEntityValue = 1; +#endif /* XML_DTD */ + /* never return Null for the value argument in EntityDeclHandler, + since this would indicate an external entity; therefore we + have to make sure that entityValuePool.start is not null */ + if (!pool->blocks) { + if (!poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + } + + for (;;) { + const char *next; + int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: +#ifdef XML_DTD + if (isParamEntity || enc != encoding) { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&tempPool, enc, + entityTextPtr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0); + poolDiscard(&tempPool); + if (!entity) { + /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ + /* cannot report skipped entity here - see comments on + skippedEntityHandler + if (skippedEntityHandler) + skippedEntityHandler(handlerArg, name, 0); + */ + dtd->keepProcessing = dtd->standalone; + goto endEntityValue; + } + if (entity->open) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_RECURSIVE_ENTITY_REF; + goto endEntityValue; + } + if (entity->systemId) { + if (externalEntityRefHandler) { + dtd->paramEntityRead = XML_FALSE; + entity->open = XML_TRUE; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = XML_FALSE; + result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; + goto endEntityValue; + } + entity->open = XML_FALSE; + if (!dtd->paramEntityRead) + dtd->keepProcessing = dtd->standalone; + } + else + dtd->keepProcessing = dtd->standalone; + } + else { + entity->open = XML_TRUE; + result = storeEntityValue(parser, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + + entity->textLen)); + entity->open = XML_FALSE; + if (result) + goto endEntityValue; + } + break; + } +#endif /* XML_DTD */ + /* In the internal subset, PE references are not legal + within markup declarations, e.g entity values in this case. */ + eventPtr = entityTextPtr; + result = XML_ERROR_PARAM_ENTITY_REF; + goto endEntityValue; + case XML_TOK_NONE: + result = XML_ERROR_NONE; + goto endEntityValue; + case XML_TOK_ENTITY_REF: + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, entityTextPtr, next)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + break; + case XML_TOK_TRAILING_CR: + next = entityTextPtr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_DATA_NEWLINE: + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + *(pool->ptr)++ = 0xA; + break; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, entityTextPtr); + if (n < 0) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_BAD_CHAR_REF; + goto endEntityValue; + } + for (i = 0; i < n; i++) { + if (pool->end == pool->ptr && !poolGrow(pool)) { + result = XML_ERROR_NO_MEMORY; + goto endEntityValue; + } + *(pool->ptr)++ = buf[i]; + } + } + break; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + result = XML_ERROR_INVALID_TOKEN; + goto endEntityValue; + default: + if (enc == encoding) + eventPtr = entityTextPtr; + result = XML_ERROR_UNEXPECTED_STATE; + goto endEntityValue; + } + entityTextPtr = next; + } +endEntityValue: +#ifdef XML_DTD + prologState.inEntityValue = oldInEntityValue; +#endif /* XML_DTD */ + return result; +} + +static void FASTCALL +normalizeLines(XML_Char *s) +{ + XML_Char *p; + for (;; s++) { + if (*s == XML_T('\0')) + return; + if (*s == 0xD) + break; + } + p = s; + do { + if (*s == 0xD) { + *p++ = 0xA; + if (*++s == 0xA) + s++; + } + else + *p++ = *s++; + } while (*s); + *p = XML_T('\0'); +} + +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + const XML_Char *target; + XML_Char *data; + const char *tem; + if (!processingInstructionHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + start += enc->minBytesPerChar * 2; + tem = start + XmlNameLength(enc, start); + target = poolStoreString(&tempPool, enc, start, tem); + if (!target) + return 0; + poolFinish(&tempPool); + data = poolStoreString(&tempPool, enc, + XmlSkipS(enc, tem), + end - enc->minBytesPerChar*2); + if (!data) + return 0; + normalizeLines(data); + processingInstructionHandler(handlerArg, target, data); + poolClear(&tempPool); + return 1; +} + +static int +reportComment(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + XML_Char *data; + if (!commentHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + data = poolStoreString(&tempPool, + enc, + start + enc->minBytesPerChar * 4, + end - enc->minBytesPerChar * 3); + if (!data) + return 0; + normalizeLines(data); + commentHandler(handlerArg, data); + poolClear(&tempPool); + return 1; +} + +static void +reportDefault(XML_Parser parser, const ENCODING *enc, + const char *s, const char *end) +{ + if (MUST_CONVERT(enc, s)) { + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + do { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf)); + *eventPP = s; + } while (s != end); + } + else + defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s)); +} + + +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, + XML_Bool isId, const XML_Char *value, XML_Parser parser) +{ + DEFAULT_ATTRIBUTE *att; + if (value || isId) { + /* The handling of default attributes gets messed up if we have + a default which duplicates a non-default. */ + int i; + for (i = 0; i < type->nDefaultAtts; i++) + if (attId == type->defaultAtts[i].id) + return 1; + if (isId && !type->idAtt && !attId->xmlns) + type->idAtt = attId; + } + if (type->nDefaultAtts == type->allocDefaultAtts) { + if (type->allocDefaultAtts == 0) { + type->allocDefaultAtts = 8; + type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts + * sizeof(DEFAULT_ATTRIBUTE)); + if (!type->defaultAtts) + return 0; + } + else { + DEFAULT_ATTRIBUTE *temp; + int count = type->allocDefaultAtts * 2; + temp = (DEFAULT_ATTRIBUTE *) + REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) + return 0; + type->allocDefaultAtts = count; + type->defaultAtts = temp; + } + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; + att->value = value; + att->isCdata = isCdata; + if (!isCdata) + attId->maybeTokenized = XML_TRUE; + type->nDefaultAtts += 1; + return 1; +} + +static int +setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name; + for (name = elementType->name; *name; name++) { + if (*name == XML_T(':')) { + PREFIX *prefix; + const XML_Char *s; + for (s = elementType->name; s != name; s++) { + if (!poolAppendChar(&dtd->pool, *s)) + return 0; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return 0; + prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + elementType->prefix = prefix; + + } + } + return 1; +} + +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, + const char *start, const char *end) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + ATTRIBUTE_ID *id; + const XML_Char *name; + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + name = poolStoreString(&dtd->pool, enc, start, end); + if (!name) + return NULL; + /* skip quotation mark - its storage will be re-used (like in name[-1]) */ + ++name; + id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); + if (!id) + return NULL; + if (id->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!ns) + ; + else if (name[0] == XML_T('x') + && name[1] == XML_T('m') + && name[2] == XML_T('l') + && name[3] == XML_T('n') + && name[4] == XML_T('s') + && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { + if (name[5] == XML_T('\0')) + id->prefix = &dtd->defaultPrefix; + else + id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX)); + id->xmlns = XML_TRUE; + } + else { + int i; + for (i = 0; name[i]; i++) { + /* attributes without prefix are *not* in the default namespace */ + if (name[i] == XML_T(':')) { + int j; + for (j = 0; j < i; j++) { + if (!poolAppendChar(&dtd->pool, name[j])) + return NULL; + } + if (!poolAppendChar(&dtd->pool, XML_T('\0'))) + return NULL; + id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool), + sizeof(PREFIX)); + if (id->prefix->name == poolStart(&dtd->pool)) + poolFinish(&dtd->pool); + else + poolDiscard(&dtd->pool); + break; + } + } + } + } + return id; +} + +#define CONTEXT_SEP XML_T('\f') + +static const XML_Char * +getContext(XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + HASH_TABLE_ITER iter; + XML_Bool needSep = XML_FALSE; + + if (dtd->defaultPrefix.binding) { + int i; + int len; + if (!poolAppendChar(&tempPool, XML_T('='))) + return NULL; + len = dtd->defaultPrefix.binding->uriLen; + if (namespaceSeparator) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) + return NULL; + needSep = XML_TRUE; + } + + hashTableIterInit(&iter, &(dtd->prefixes)); + for (;;) { + int i; + int len; + const XML_Char *s; + PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); + if (!prefix) + break; + if (!prefix->binding) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = prefix->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return NULL; + if (!poolAppendChar(&tempPool, XML_T('='))) + return NULL; + len = prefix->binding->uriLen; + if (namespaceSeparator) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) + return NULL; + needSep = XML_TRUE; + } + + + hashTableIterInit(&iter, &(dtd->generalEntities)); + for (;;) { + const XML_Char *s; + ENTITY *e = (ENTITY *)hashTableIterNext(&iter); + if (!e) + break; + if (!e->open) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return NULL; + for (s = e->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + needSep = XML_TRUE; + } + + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return NULL; + return tempPool.start; +} + +static XML_Bool +setContext(XML_Parser parser, const XML_Char *context) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *s = context; + + while (*context != XML_T('\0')) { + if (*s == CONTEXT_SEP || *s == XML_T('\0')) { + ENTITY *e; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0); + if (e) + e->open = XML_TRUE; + if (*s != XML_T('\0')) + s++; + context = s; + poolDiscard(&tempPool); + } + else if (*s == XML_T('=')) { + PREFIX *prefix; + if (poolLength(&tempPool) == 0) + prefix = &dtd->defaultPrefix; + else { + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool), + sizeof(PREFIX)); + if (!prefix) + return XML_FALSE; + if (prefix->name == poolStart(&tempPool)) { + prefix->name = poolCopyString(&dtd->pool, prefix->name); + if (!prefix->name) + return XML_FALSE; + } + poolDiscard(&tempPool); + } + for (context = s + 1; + *context != CONTEXT_SEP && *context != XML_T('\0'); + context++) + if (!poolAppendChar(&tempPool, *context)) + return XML_FALSE; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return XML_FALSE; + if (addBinding(parser, prefix, NULL, poolStart(&tempPool), + &inheritedBindings) != XML_ERROR_NONE) + return XML_FALSE; + poolDiscard(&tempPool); + if (*context != XML_T('\0')) + ++context; + s = context; + } + else { + if (!poolAppendChar(&tempPool, *s)) + return XML_FALSE; + s++; + } + } + return XML_TRUE; +} + +static void FASTCALL +normalizePublicId(XML_Char *publicId) +{ + XML_Char *p = publicId; + XML_Char *s; + for (s = publicId; *s; s++) { + switch (*s) { + case 0x20: + case 0xD: + case 0xA: + if (p != publicId && p[-1] != 0x20) + *p++ = 0x20; + break; + default: + *p++ = *s; + } + } + if (p != publicId && p[-1] == 0x20) + --p; + *p = XML_T('\0'); +} + +static DTD * +dtdCreate(const XML_Memory_Handling_Suite *ms) +{ + DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD)); + if (p == NULL) + return p; + poolInit(&(p->pool), ms); + poolInit(&(p->entityValuePool), ms); + hashTableInit(&(p->generalEntities), ms); + hashTableInit(&(p->elementTypes), ms); + hashTableInit(&(p->attributeIds), ms); + hashTableInit(&(p->prefixes), ms); +#ifdef XML_DTD + p->paramEntityRead = XML_FALSE; + hashTableInit(&(p->paramEntities), ms); +#endif /* XML_DTD */ + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; + + p->in_eldecl = XML_FALSE; + p->scaffIndex = NULL; + p->scaffold = NULL; + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; + + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; + return p; +} + +static void +dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableClear(&(p->generalEntities)); +#ifdef XML_DTD + p->paramEntityRead = XML_FALSE; + hashTableClear(&(p->paramEntities)); +#endif /* XML_DTD */ + hashTableClear(&(p->elementTypes)); + hashTableClear(&(p->attributeIds)); + hashTableClear(&(p->prefixes)); + poolClear(&(p->pool)); + poolClear(&(p->entityValuePool)); + p->defaultPrefix.name = NULL; + p->defaultPrefix.binding = NULL; + + p->in_eldecl = XML_FALSE; + + ms->free_fcn(p->scaffIndex); + p->scaffIndex = NULL; + ms->free_fcn(p->scaffold); + p->scaffold = NULL; + + p->scaffLevel = 0; + p->scaffSize = 0; + p->scaffCount = 0; + p->contentStringLen = 0; + + p->keepProcessing = XML_TRUE; + p->hasParamEntityRefs = XML_FALSE; + p->standalone = XML_FALSE; +} + +static void +dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + ms->free_fcn(e->defaultAtts); + } + hashTableDestroy(&(p->generalEntities)); +#ifdef XML_DTD + hashTableDestroy(&(p->paramEntities)); +#endif /* XML_DTD */ + hashTableDestroy(&(p->elementTypes)); + hashTableDestroy(&(p->attributeIds)); + hashTableDestroy(&(p->prefixes)); + poolDestroy(&(p->pool)); + poolDestroy(&(p->entityValuePool)); + if (isDocEntity) { + ms->free_fcn(p->scaffIndex); + ms->free_fcn(p->scaffold); + } + ms->free_fcn(p); +} + +/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. + The new DTD has already been initialized. +*/ +static int +dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) +{ + HASH_TABLE_ITER iter; + + /* Copy the prefix table. */ + + hashTableIterInit(&iter, &(oldDtd->prefixes)); + for (;;) { + const XML_Char *name; + const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); + if (!oldP) + break; + name = poolCopyString(&(newDtd->pool), oldP->name); + if (!name) + return 0; + if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) + return 0; + } + + hashTableIterInit(&iter, &(oldDtd->attributeIds)); + + /* Copy the attribute id table. */ + + for (;;) { + ATTRIBUTE_ID *newA; + const XML_Char *name; + const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + + if (!oldA) + break; + /* Remember to allocate the scratch byte before the name. */ + if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) + return 0; + name = poolCopyString(&(newDtd->pool), oldA->name); + if (!name) + return 0; + ++name; + newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, + sizeof(ATTRIBUTE_ID)); + if (!newA) + return 0; + newA->maybeTokenized = oldA->maybeTokenized; + if (oldA->prefix) { + newA->xmlns = oldA->xmlns; + if (oldA->prefix == &oldDtd->defaultPrefix) + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), + oldA->prefix->name, 0); + } + } + + /* Copy the element type table. */ + + hashTableIterInit(&iter, &(oldDtd->elementTypes)); + + for (;;) { + int i; + ELEMENT_TYPE *newE; + const XML_Char *name; + const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(&(newDtd->pool), oldE->name); + if (!name) + return 0; + newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, + sizeof(ELEMENT_TYPE)); + if (!newE) + return 0; + if (oldE->nDefaultAtts) { + newE->defaultAtts = (DEFAULT_ATTRIBUTE *) + ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + if (!newE->defaultAtts) { + ms->free_fcn(newE); + return 0; + } + } + if (oldE->idAtt) + newE->idAtt = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); + newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; + if (oldE->prefix) + newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), + oldE->prefix->name, 0); + for (i = 0; i < newE->nDefaultAtts; i++) { + newE->defaultAtts[i].id = (ATTRIBUTE_ID *) + lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; + if (oldE->defaultAtts[i].value) { + newE->defaultAtts[i].value + = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); + if (!newE->defaultAtts[i].value) + return 0; + } + else + newE->defaultAtts[i].value = NULL; + } + } + + /* Copy the entity tables. */ + if (!copyEntityTable(&(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities))) + return 0; + +#ifdef XML_DTD + if (!copyEntityTable(&(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities))) + return 0; + newDtd->paramEntityRead = oldDtd->paramEntityRead; +#endif /* XML_DTD */ + + newDtd->keepProcessing = oldDtd->keepProcessing; + newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; + newDtd->standalone = oldDtd->standalone; + + /* Don't want deep copying for scaffolding */ + newDtd->in_eldecl = oldDtd->in_eldecl; + newDtd->scaffold = oldDtd->scaffold; + newDtd->contentStringLen = oldDtd->contentStringLen; + newDtd->scaffSize = oldDtd->scaffSize; + newDtd->scaffLevel = oldDtd->scaffLevel; + newDtd->scaffIndex = oldDtd->scaffIndex; + + return 1; +} /* End dtdCopy */ + +static int +copyEntityTable(HASH_TABLE *newTable, + STRING_POOL *newPool, + const HASH_TABLE *oldTable) +{ + HASH_TABLE_ITER iter; + const XML_Char *cachedOldBase = NULL; + const XML_Char *cachedNewBase = NULL; + + hashTableIterInit(&iter, oldTable); + + for (;;) { + ENTITY *newE; + const XML_Char *name; + const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(newPool, oldE->name); + if (!name) + return 0; + newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); + if (!newE) + return 0; + if (oldE->systemId) { + const XML_Char *tem = poolCopyString(newPool, oldE->systemId); + if (!tem) + return 0; + newE->systemId = tem; + if (oldE->base) { + if (oldE->base == cachedOldBase) + newE->base = cachedNewBase; + else { + cachedOldBase = oldE->base; + tem = poolCopyString(newPool, cachedOldBase); + if (!tem) + return 0; + cachedNewBase = newE->base = tem; + } + } + if (oldE->publicId) { + tem = poolCopyString(newPool, oldE->publicId); + if (!tem) + return 0; + newE->publicId = tem; + } + } + else { + const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, + oldE->textLen); + if (!tem) + return 0; + newE->textPtr = tem; + newE->textLen = oldE->textLen; + } + if (oldE->notation) { + const XML_Char *tem = poolCopyString(newPool, oldE->notation); + if (!tem) + return 0; + newE->notation = tem; + } + newE->is_param = oldE->is_param; + newE->is_internal = oldE->is_internal; + } + return 1; +} + +#define INIT_POWER 6 + +static XML_Bool FASTCALL +keyeq(KEY s1, KEY s2) +{ + for (; *s1 == *s2; s1++, s2++) + if (*s1 == 0) + return XML_TRUE; + return XML_FALSE; +} + +static unsigned long FASTCALL +hash(KEY s) +{ + unsigned long h = 0; + while (*s) + h = CHAR_HASH(h, *s++); + return h; +} + +static NAMED * +lookup(HASH_TABLE *table, KEY name, size_t createSize) +{ + size_t i; + if (table->size == 0) { + size_t tsize; + if (!createSize) + return NULL; + table->power = INIT_POWER; + /* table->size is a power of 2 */ + table->size = (size_t)1 << INIT_POWER; + tsize = table->size * sizeof(NAMED *); + table->v = (NAMED **)table->mem->malloc_fcn(tsize); + if (!table->v) { + table->size = 0; + return NULL; + } + memset(table->v, 0, tsize); + i = hash(name) & ((unsigned long)table->size - 1); + } + else { + unsigned long h = hash(name); + unsigned long mask = (unsigned long)table->size - 1; + unsigned char step = 0; + i = h & mask; + while (table->v[i]) { + if (keyeq(name, table->v[i]->name)) + return table->v[i]; + if (!step) + step = PROBE_STEP(h, mask, table->power); + i < step ? (i += table->size - step) : (i -= step); + } + if (!createSize) + return NULL; + + /* check for overflow (table is half full) */ + if (table->used >> (table->power - 1)) { + unsigned char newPower = table->power + 1; + size_t newSize = (size_t)1 << newPower; + unsigned long newMask = (unsigned long)newSize - 1; + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); + if (!newV) + return NULL; + memset(newV, 0, tsize); + for (i = 0; i < table->size; i++) + if (table->v[i]) { + unsigned long newHash = hash(table->v[i]->name); + size_t j = newHash & newMask; + step = 0; + while (newV[j]) { + if (!step) + step = PROBE_STEP(newHash, newMask, newPower); + j < step ? (j += newSize - step) : (j -= step); + } + newV[j] = table->v[i]; + } + table->mem->free_fcn(table->v); + table->v = newV; + table->power = newPower; + table->size = newSize; + i = h & newMask; + step = 0; + while (table->v[i]) { + if (!step) + step = PROBE_STEP(h, newMask, newPower); + i < step ? (i += newSize - step) : (i -= step); + } + } + } + table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize); + if (!table->v[i]) + return NULL; + memset(table->v[i], 0, createSize); + table->v[i]->name = name; + (table->used)++; + return table->v[i]; +} + +static void FASTCALL +hashTableClear(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) { + table->mem->free_fcn(table->v[i]); + table->v[i] = NULL; + } + table->used = 0; +} + +static void FASTCALL +hashTableDestroy(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) + table->mem->free_fcn(table->v[i]); + table->mem->free_fcn(table->v); +} + +static void FASTCALL +hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) +{ + p->power = 0; + p->size = 0; + p->used = 0; + p->v = NULL; + p->mem = ms; +} + +static void FASTCALL +hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) +{ + iter->p = table->v; + iter->end = iter->p + table->size; +} + +static NAMED * FASTCALL +hashTableIterNext(HASH_TABLE_ITER *iter) +{ + while (iter->p != iter->end) { + NAMED *tem = *(iter->p)++; + if (tem) + return tem; + } + return NULL; +} + +static void FASTCALL +poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) +{ + pool->blocks = NULL; + pool->freeBlocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; + pool->mem = ms; +} + +static void FASTCALL +poolClear(STRING_POOL *pool) +{ + if (!pool->freeBlocks) + pool->freeBlocks = pool->blocks; + else { + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + p->next = pool->freeBlocks; + pool->freeBlocks = p; + p = tem; + } + } + pool->blocks = NULL; + pool->start = NULL; + pool->ptr = NULL; + pool->end = NULL; +} + +static void FASTCALL +poolDestroy(STRING_POOL *pool) +{ + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } + p = pool->freeBlocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } +} + +static XML_Char * +poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (;;) { + XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if (ptr == end) + break; + if (!poolGrow(pool)) + return NULL; + } + return pool->start; +} + +static const XML_Char * FASTCALL +poolCopyString(STRING_POOL *pool, const XML_Char *s) +{ + do { + if (!poolAppendChar(pool, *s)) + return NULL; + } while (*s++); + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char * +poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) +{ + if (!pool->ptr && !poolGrow(pool)) + return NULL; + for (; n > 0; --n, s++) { + if (!poolAppendChar(pool, *s)) + return NULL; + } + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char * FASTCALL +poolAppendString(STRING_POOL *pool, const XML_Char *s) +{ + while (*s) { + if (!poolAppendChar(pool, *s)) + return NULL; + s++; + } + return pool->start; +} + +static XML_Char * +poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!poolAppend(pool, enc, ptr, end)) + return NULL; + if (pool->ptr == pool->end && !poolGrow(pool)) + return NULL; + *(pool->ptr)++ = 0; + return pool->start; +} + +static XML_Bool FASTCALL +poolGrow(STRING_POOL *pool) +{ + if (pool->freeBlocks) { + if (pool->start == 0) { + pool->blocks = pool->freeBlocks; + pool->freeBlocks = pool->freeBlocks->next; + pool->blocks->next = NULL; + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + pool->ptr = pool->start; + return XML_TRUE; + } + if (pool->end - pool->start < pool->freeBlocks->size) { + BLOCK *tem = pool->freeBlocks->next; + pool->freeBlocks->next = pool->blocks; + pool->blocks = pool->freeBlocks; + pool->freeBlocks = tem; + memcpy(pool->blocks->s, pool->start, + (pool->end - pool->start) * sizeof(XML_Char)); + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + return XML_TRUE; + } + } + if (pool->blocks && pool->start == pool->blocks->s) { + int blockSize = (int)(pool->end - pool->start)*2; + pool->blocks = (BLOCK *) + pool->mem->realloc_fcn(pool->blocks, + (offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char))); + if (pool->blocks == NULL) + return XML_FALSE; + pool->blocks->size = blockSize; + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + blockSize; + } + else { + BLOCK *tem; + int blockSize = (int)(pool->end - pool->start); + if (blockSize < INIT_BLOCK_SIZE) + blockSize = INIT_BLOCK_SIZE; + else + blockSize *= 2; + tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) + + blockSize * sizeof(XML_Char)); + if (!tem) + return XML_FALSE; + tem->size = blockSize; + tem->next = pool->blocks; + pool->blocks = tem; + if (pool->ptr != pool->start) + memcpy(tem->s, pool->start, + (pool->ptr - pool->start) * sizeof(XML_Char)); + pool->ptr = tem->s + (pool->ptr - pool->start); + pool->start = tem->s; + pool->end = tem->s + blockSize; + } + return XML_TRUE; +} + +static int FASTCALL +nextScaffoldPart(XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + CONTENT_SCAFFOLD * me; + int next; + + if (!dtd->scaffIndex) { + dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int)); + if (!dtd->scaffIndex) + return -1; + dtd->scaffIndex[0] = 0; + } + + if (dtd->scaffCount >= dtd->scaffSize) { + CONTENT_SCAFFOLD *temp; + if (dtd->scaffold) { + temp = (CONTENT_SCAFFOLD *) + REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize *= 2; + } + else { + temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS + * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) + return -1; + dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; + } + dtd->scaffold = temp; + } + next = dtd->scaffCount++; + me = &dtd->scaffold[next]; + if (dtd->scaffLevel) { + CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]]; + if (parent->lastchild) { + dtd->scaffold[parent->lastchild].nextsib = next; + } + if (!parent->childcnt) + parent->firstchild = next; + parent->lastchild = next; + parent->childcnt++; + } + me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; + return next; +} + +static void +build_node(XML_Parser parser, + int src_node, + XML_Content *dest, + XML_Content **contpos, + XML_Char **strpos) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + dest->type = dtd->scaffold[src_node].type; + dest->quant = dtd->scaffold[src_node].quant; + if (dest->type == XML_CTYPE_NAME) { + const XML_Char *src; + dest->name = *strpos; + src = dtd->scaffold[src_node].name; + for (;;) { + *(*strpos)++ = *src; + if (!*src) + break; + src++; + } + dest->numchildren = 0; + dest->children = NULL; + } + else { + unsigned int i; + int cn; + dest->numchildren = dtd->scaffold[src_node].childcnt; + dest->children = *contpos; + *contpos += dest->numchildren; + for (i = 0, cn = dtd->scaffold[src_node].firstchild; + i < dest->numchildren; + i++, cn = dtd->scaffold[cn].nextsib) { + build_node(parser, cn, &(dest->children[i]), contpos, strpos); + } + dest->name = NULL; + } +} + +static XML_Content * +build_model (XML_Parser parser) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + XML_Content *ret; + XML_Content *cpos; + XML_Char * str; + int allocsize = (dtd->scaffCount * sizeof(XML_Content) + + (dtd->contentStringLen * sizeof(XML_Char))); + + ret = (XML_Content *)MALLOC(allocsize); + if (!ret) + return NULL; + + str = (XML_Char *) (&ret[dtd->scaffCount]); + cpos = &ret[1]; + + build_node(parser, 0, ret, &cpos, &str); + return ret; +} + +static ELEMENT_TYPE * +getElementType(XML_Parser parser, + const ENCODING *enc, + const char *ptr, + const char *end) +{ + DTD * const dtd = _dtd; /* save one level of indirection */ + const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); + ELEMENT_TYPE *ret; + + if (!name) + return NULL; + ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); + if (!ret) + return NULL; + if (ret->name != name) + poolDiscard(&dtd->pool); + else { + poolFinish(&dtd->pool); + if (!setElementTypePrefix(parser, ret)) + return NULL; + } + return ret; +} diff --git a/libxsde/xsde/c/expat/xmlrole.c b/libxsde/xsde/c/expat/xmlrole.c new file mode 100644 index 0000000..f1bc407 --- /dev/null +++ b/libxsde/xsde/c/expat/xmlrole.c @@ -0,0 +1,1466 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#include + +#include "config.h" + +#include "expat_external.h" +#include "internal.h" +#include "xmlrole.h" +#include "ascii.h" + +/* Doesn't check: + + that ,| are not mixed in a model group + content of literals + +*/ + +static const char KW_ANY[] = { + ASCII_A, ASCII_N, ASCII_Y, '\0' }; +static const char KW_ATTLIST[] = { + ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; +static const char KW_CDATA[] = { + ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_DOCTYPE[] = { + ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; +static const char KW_ELEMENT[] = { + ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; +static const char KW_EMPTY[] = { + ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; +static const char KW_ENTITIES[] = { + ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, + '\0' }; +static const char KW_ENTITY[] = { + ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; +static const char KW_FIXED[] = { + ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; +static const char KW_ID[] = { + ASCII_I, ASCII_D, '\0' }; +static const char KW_IDREF[] = { + ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; +static const char KW_IDREFS[] = { + ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; +static const char KW_IGNORE[] = { + ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; +static const char KW_IMPLIED[] = { + ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; +static const char KW_INCLUDE[] = { + ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; +static const char KW_NDATA[] = { + ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_NMTOKEN[] = { + ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; +static const char KW_NMTOKENS[] = { + ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, + '\0' }; +static const char KW_NOTATION[] = + { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, + '\0' }; +static const char KW_PCDATA[] = { + ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_PUBLIC[] = { + ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; +static const char KW_REQUIRED[] = { + ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, + '\0' }; +static const char KW_SYSTEM[] = { + ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; + +#ifndef MIN_BYTES_PER_CHAR +#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) +#endif + +#ifdef XML_DTD +#define setTopLevel(state) \ + ((state)->handler = ((state)->documentEntity \ + ? internalSubset \ + : externalSubset1)) +#else /* not XML_DTD */ +#define setTopLevel(state) ((state)->handler = internalSubset) +#endif /* not XML_DTD */ + +typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + +static PROLOG_HANDLER + prolog0, prolog1, prolog2, + doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, + internalSubset, + entity0, entity1, entity2, entity3, entity4, entity5, entity6, + entity7, entity8, entity9, entity10, + notation0, notation1, notation2, notation3, notation4, + attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, + attlist7, attlist8, attlist9, + element0, element1, element2, element3, element4, element5, element6, + element7, +#ifdef XML_DTD + externalSubset0, externalSubset1, + condSect0, condSect1, condSect2, +#endif /* XML_DTD */ + declClose, + error; + +static int FASTCALL common(PROLOG_STATE *state, int tok); + +static int PTRCALL +prolog0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_XML_DECL: + state->handler = prolog1; + return XML_ROLE_XML_DECL; + case XML_TOK_PI: + state->handler = prolog1; + return XML_ROLE_PI; + case XML_TOK_COMMENT: + state->handler = prolog1; + return XML_ROLE_COMMENT; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static int PTRCALL +prolog1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static int PTRCALL +prolog2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static int PTRCALL +doctype0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = doctype1; + return XML_ROLE_DOCTYPE_NAME; + } + return common(state, tok); +} + +static int PTRCALL +doctype1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = doctype3; + return XML_ROLE_DOCTYPE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = doctype2; + return XML_ROLE_DOCTYPE_NONE; + } + break; + } + return common(state, tok); +} + +static int PTRCALL +doctype2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype3; + return XML_ROLE_DOCTYPE_PUBLIC_ID; + } + return common(state, tok); +} + +static int PTRCALL +doctype3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype4; + return XML_ROLE_DOCTYPE_SYSTEM_ID; + } + return common(state, tok); +} + +static int PTRCALL +doctype4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static int PTRCALL +doctype5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static int PTRCALL +internalSubset(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ENTITY)) { + state->handler = entity0; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ATTLIST)) { + state->handler = attlist0; + return XML_ROLE_ATTLIST_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ELEMENT)) { + state->handler = element0; + return XML_ROLE_ELEMENT_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_NOTATION)) { + state->handler = notation0; + return XML_ROLE_NOTATION_NONE; + } + break; + case XML_TOK_PI: + return XML_ROLE_PI; + case XML_TOK_COMMENT: + return XML_ROLE_COMMENT; + case XML_TOK_PARAM_ENTITY_REF: + return XML_ROLE_PARAM_ENTITY_REF; + case XML_TOK_CLOSE_BRACKET: + state->handler = doctype5; + return XML_ROLE_DOCTYPE_NONE; + case XML_TOK_NONE: + return XML_ROLE_NONE; + } + return common(state, tok); +} + +#ifdef XML_DTD + +static int PTRCALL +externalSubset0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + state->handler = externalSubset1; + if (tok == XML_TOK_XML_DECL) + return XML_ROLE_TEXT_DECL; + return externalSubset1(state, tok, ptr, end, enc); +} + +static int PTRCALL +externalSubset1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_COND_SECT_OPEN: + state->handler = condSect0; + return XML_ROLE_NONE; + case XML_TOK_COND_SECT_CLOSE: + if (state->includeLevel == 0) + break; + state->includeLevel -= 1; + return XML_ROLE_NONE; + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_BRACKET: + break; + case XML_TOK_NONE: + if (state->includeLevel) + break; + return XML_ROLE_NONE; + default: + return internalSubset(state, tok, ptr, end, enc); + } + return common(state, tok); +} + +#endif /* XML_DTD */ + +static int PTRCALL +entity0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_PERCENT: + state->handler = entity1; + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = entity2; + return XML_ROLE_GENERAL_ENTITY_NAME; + } + return common(state, tok); +} + +static int PTRCALL +entity1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = entity7; + return XML_ROLE_PARAM_ENTITY_NAME; + } + return common(state, tok); +} + +static int PTRCALL +entity2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity4; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity3; + return XML_ROLE_ENTITY_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +entity3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity4; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + +static int PTRCALL +entity4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity5; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static int PTRCALL +entity5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ENTITY_COMPLETE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { + state->handler = entity6; + return XML_ROLE_ENTITY_NONE; + } + break; + } + return common(state, tok); +} + +static int PTRCALL +entity6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_NOTATION_NAME; + } + return common(state, tok); +} + +static int PTRCALL +entity7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity9; + return XML_ROLE_ENTITY_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity8; + return XML_ROLE_ENTITY_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_ENTITY_NONE; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +entity8(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity9; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + +static int PTRCALL +entity9(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_LITERAL: + state->handler = entity10; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static int PTRCALL +entity10(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ENTITY_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ENTITY_COMPLETE; + } + return common(state, tok); +} + +static int PTRCALL +notation0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_NAME: + state->handler = notation1; + return XML_ROLE_NOTATION_NAME; + } + return common(state, tok); +} + +static int PTRCALL +notation1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = notation3; + return XML_ROLE_NOTATION_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = notation2; + return XML_ROLE_NOTATION_NONE; + } + break; + } + return common(state, tok); +} + +static int PTRCALL +notation2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = notation4; + return XML_ROLE_NOTATION_PUBLIC_ID; + } + return common(state, tok); +} + +static int PTRCALL +notation3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_NOTATION_NONE; + return XML_ROLE_NOTATION_SYSTEM_ID; + } + return common(state, tok); +} + +static int PTRCALL +notation4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NOTATION_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + state->role_none = XML_ROLE_NOTATION_NONE; + return XML_ROLE_NOTATION_SYSTEM_ID; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NOTATION_NO_SYSTEM_ID; + } + return common(state, tok); +} + +static int PTRCALL +attlist0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist1; + return XML_ROLE_ATTLIST_ELEMENT_NAME; + } + return common(state, tok); +} + +static int PTRCALL +attlist1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist2; + return XML_ROLE_ATTRIBUTE_NAME; + } + return common(state, tok); +} + +static int PTRCALL +attlist2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + { + static const char * const types[] = { + KW_CDATA, + KW_ID, + KW_IDREF, + KW_IDREFS, + KW_ENTITY, + KW_ENTITIES, + KW_NMTOKEN, + KW_NMTOKENS, + }; + int i; + for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) + if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { + state->handler = attlist8; + return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; + } + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { + state->handler = attlist5; + return XML_ROLE_ATTLIST_NONE; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = attlist3; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); +} + +static int PTRCALL +attlist3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NMTOKEN: + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist4; + return XML_ROLE_ATTRIBUTE_ENUM_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +attlist4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OR: + state->handler = attlist3; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); +} + +static int PTRCALL +attlist5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OPEN_PAREN: + state->handler = attlist6; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); +} + +static int PTRCALL +attlist6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_NAME: + state->handler = attlist7; + return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +attlist7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_OR: + state->handler = attlist6; + return XML_ROLE_ATTLIST_NONE; + } + return common(state, tok); +} + +/* default value */ +static int PTRCALL +attlist8(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_IMPLIED)) { + state->handler = attlist1; + return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_REQUIRED)) { + state->handler = attlist1; + return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_FIXED)) { + state->handler = attlist9; + return XML_ROLE_ATTLIST_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +attlist9(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ATTLIST_NONE; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_FIXED_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static int PTRCALL +element0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element1; + return XML_ROLE_ELEMENT_NAME; + } + return common(state, tok); +} + +static int PTRCALL +element1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_CONTENT_EMPTY; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_CONTENT_ANY; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = element2; + state->level = 1; + return XML_ROLE_GROUP_OPEN; + } + return common(state, tok); +} + +static int PTRCALL +element2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_PCDATA)) { + state->handler = element3; + return XML_ROLE_CONTENT_PCDATA; + } + break; + case XML_TOK_OPEN_PAREN: + state->level = 2; + state->handler = element6; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static int PTRCALL +element3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_ELEMENT_NONE; + } + return common(state, tok); +} + +static int PTRCALL +element4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element5; + return XML_ROLE_CONTENT_ELEMENT; + } + return common(state, tok); +} + +static int PTRCALL +element5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_ELEMENT_NONE; + } + return common(state, tok); +} + +static int PTRCALL +element6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_OPEN_PAREN: + state->level += 1; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static int PTRCALL +element7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_ELEMENT_NONE; + case XML_TOK_CLOSE_PAREN: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_CLOSE_PAREN_QUESTION: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE_OPT; + case XML_TOK_CLOSE_PAREN_PLUS: + state->level -= 1; + if (state->level == 0) { + state->handler = declClose; + state->role_none = XML_ROLE_ELEMENT_NONE; + } + return XML_ROLE_GROUP_CLOSE_PLUS; + case XML_TOK_COMMA: + state->handler = element6; + return XML_ROLE_GROUP_SEQUENCE; + case XML_TOK_OR: + state->handler = element6; + return XML_ROLE_GROUP_CHOICE; + } + return common(state, tok); +} + +#ifdef XML_DTD + +static int PTRCALL +condSect0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { + state->handler = condSect1; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { + state->handler = condSect2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static int PTRCALL +condSect1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + state->includeLevel += 1; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static int PTRCALL +condSect2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + return XML_ROLE_IGNORE_SECT; + } + return common(state, tok); +} + +#endif /* XML_DTD */ + +static int PTRCALL +declClose(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + switch (tok) { + case XML_TOK_PROLOG_S: + return state->role_none; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return state->role_none; + } + return common(state, tok); +} + +static int PTRCALL +error(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + UNUSED(state); + UNUSED(tok); + UNUSED(ptr); + UNUSED(end); + UNUSED(enc); + + return XML_ROLE_NONE; +} + +static int FASTCALL +common(PROLOG_STATE *state, int tok) +{ +#ifdef XML_DTD + if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) + return XML_ROLE_INNER_PARAM_ENTITY_REF; +#endif + state->handler = error; + return XML_ROLE_ERROR; +} + +void +XmlPrologStateInit(PROLOG_STATE *state) +{ + state->handler = prolog0; +#ifdef XML_DTD + state->documentEntity = 1; + state->includeLevel = 0; + state->inEntityValue = 0; +#endif /* XML_DTD */ +} + +#ifdef XML_DTD + +void +XmlPrologStateInitExternalEntity(PROLOG_STATE *state) +{ + state->handler = externalSubset0; + state->documentEntity = 0; + state->includeLevel = 0; +} + +#endif /* XML_DTD */ diff --git a/libxsde/xsde/c/expat/xmlrole.h b/libxsde/xsde/c/expat/xmlrole.h new file mode 100644 index 0000000..4dd9f06 --- /dev/null +++ b/libxsde/xsde/c/expat/xmlrole.h @@ -0,0 +1,114 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef XmlRole_INCLUDED +#define XmlRole_INCLUDED 1 + +#ifdef __VMS +/* 0 1 2 3 0 1 2 3 + 1234567890123456789012345678901 1234567890123456789012345678901 */ +#define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt +#endif + +#include "xmltok.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + XML_ROLE_ERROR = -1, + XML_ROLE_NONE = 0, + XML_ROLE_XML_DECL, + XML_ROLE_INSTANCE_START, + XML_ROLE_DOCTYPE_NONE, + XML_ROLE_DOCTYPE_NAME, + XML_ROLE_DOCTYPE_SYSTEM_ID, + XML_ROLE_DOCTYPE_PUBLIC_ID, + XML_ROLE_DOCTYPE_INTERNAL_SUBSET, + XML_ROLE_DOCTYPE_CLOSE, + XML_ROLE_GENERAL_ENTITY_NAME, + XML_ROLE_PARAM_ENTITY_NAME, + XML_ROLE_ENTITY_NONE, + XML_ROLE_ENTITY_VALUE, + XML_ROLE_ENTITY_SYSTEM_ID, + XML_ROLE_ENTITY_PUBLIC_ID, + XML_ROLE_ENTITY_COMPLETE, + XML_ROLE_ENTITY_NOTATION_NAME, + XML_ROLE_NOTATION_NONE, + XML_ROLE_NOTATION_NAME, + XML_ROLE_NOTATION_SYSTEM_ID, + XML_ROLE_NOTATION_NO_SYSTEM_ID, + XML_ROLE_NOTATION_PUBLIC_ID, + XML_ROLE_ATTRIBUTE_NAME, + XML_ROLE_ATTRIBUTE_TYPE_CDATA, + XML_ROLE_ATTRIBUTE_TYPE_ID, + XML_ROLE_ATTRIBUTE_TYPE_IDREF, + XML_ROLE_ATTRIBUTE_TYPE_IDREFS, + XML_ROLE_ATTRIBUTE_TYPE_ENTITY, + XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, + XML_ROLE_ATTRIBUTE_ENUM_VALUE, + XML_ROLE_ATTRIBUTE_NOTATION_VALUE, + XML_ROLE_ATTLIST_NONE, + XML_ROLE_ATTLIST_ELEMENT_NAME, + XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, + XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, + XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, + XML_ROLE_FIXED_ATTRIBUTE_VALUE, + XML_ROLE_ELEMENT_NONE, + XML_ROLE_ELEMENT_NAME, + XML_ROLE_CONTENT_ANY, + XML_ROLE_CONTENT_EMPTY, + XML_ROLE_CONTENT_PCDATA, + XML_ROLE_GROUP_OPEN, + XML_ROLE_GROUP_CLOSE, + XML_ROLE_GROUP_CLOSE_REP, + XML_ROLE_GROUP_CLOSE_OPT, + XML_ROLE_GROUP_CLOSE_PLUS, + XML_ROLE_GROUP_CHOICE, + XML_ROLE_GROUP_SEQUENCE, + XML_ROLE_CONTENT_ELEMENT, + XML_ROLE_CONTENT_ELEMENT_REP, + XML_ROLE_CONTENT_ELEMENT_OPT, + XML_ROLE_CONTENT_ELEMENT_PLUS, + XML_ROLE_PI, + XML_ROLE_COMMENT, +#ifdef XML_DTD + XML_ROLE_TEXT_DECL, + XML_ROLE_IGNORE_SECT, + XML_ROLE_INNER_PARAM_ENTITY_REF, +#endif /* XML_DTD */ + XML_ROLE_PARAM_ENTITY_REF +}; + +typedef struct prolog_state { + int (PTRCALL *handler) (struct prolog_state *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + unsigned level; + int role_none; +#ifdef XML_DTD + unsigned includeLevel; + int documentEntity; + int inEntityValue; +#endif /* XML_DTD */ +} PROLOG_STATE; + +void XmlPrologStateInit(PROLOG_STATE *); +#ifdef XML_DTD +void XmlPrologStateInitExternalEntity(PROLOG_STATE *); +#endif /* XML_DTD */ + +#define XmlTokenRole(state, tok, ptr, end, enc) \ + (((state)->handler)(state, tok, ptr, end, enc)) + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlRole_INCLUDED */ diff --git a/libxsde/xsde/c/expat/xmltok.c b/libxsde/xsde/c/expat/xmltok.c new file mode 100644 index 0000000..77ab2e9 --- /dev/null +++ b/libxsde/xsde/c/expat/xmltok.c @@ -0,0 +1,1671 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#include + +#include "config.h" + +#include "expat_external.h" +#include "internal.h" +#include "xmltok.h" +#include "nametab.h" + +#ifdef XML_DTD +#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) +#else +#define IGNORE_SECTION_TOK_VTABLE /* as nothing */ +#endif + +#define VTABLE1 \ + { PREFIX(prologTok), PREFIX(contentTok), \ + PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \ + { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ + PREFIX(sameName), \ + PREFIX(nameMatchesAscii), \ + PREFIX(nameLength), \ + PREFIX(skipS), \ + PREFIX(getAtts), \ + PREFIX(charRefNumber), \ + PREFIX(predefinedEntityName), \ + PREFIX(updatePosition), \ + PREFIX(isPublicId) + +#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) + +#define UCS2_GET_NAMING(pages, hi, lo) \ + (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) + +/* A 2 byte UTF-8 representation splits the characters 11 bits between + the bottom 5 and 6 bits of the bytes. We need 8 bits to index into + pages, 3 bits to add to that index and 5 bits to generate the mask. +*/ +#define UTF8_GET_NAMING2(pages, byte) \ + (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + + ((((byte)[0]) & 3) << 1) \ + + ((((byte)[1]) >> 5) & 1)] \ + & (1 << (((byte)[1]) & 0x1F))) + +/* A 3 byte UTF-8 representation splits the characters 16 bits between + the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index + into pages, 3 bits to add to that index and 5 bits to generate the + mask. +*/ +#define UTF8_GET_NAMING3(pages, byte) \ + (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ + + ((((byte)[1]) >> 2) & 0xF)] \ + << 3) \ + + ((((byte)[1]) & 3) << 1) \ + + ((((byte)[2]) >> 5) & 1)] \ + & (1 << (((byte)[2]) & 0x1F))) + +#define UTF8_GET_NAMING(pages, p, n) \ + ((n) == 2 \ + ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ + : ((n) == 3 \ + ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ + : 0)) + +/* Detection of invalid UTF-8 sequences is based on Table 3.1B + of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/ + with the additional restriction of not allowing the Unicode + code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE). + Implementation details: + (A & 0x80) == 0 means A < 0x80 + and + (A & 0xC0) == 0xC0 means A > 0xBF +*/ + +#define UTF8_INVALID2(p) \ + ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0) + +#define UTF8_INVALID3(p) \ + (((p)[2] & 0x80) == 0 \ + || \ + ((*p) == 0xEF && (p)[1] == 0xBF \ + ? \ + (p)[2] > 0xBD \ + : \ + ((p)[2] & 0xC0) == 0xC0) \ + || \ + ((*p) == 0xE0 \ + ? \ + (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \ + : \ + ((p)[1] & 0x80) == 0 \ + || \ + ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0))) + +#define UTF8_INVALID4(p) \ + (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \ + || \ + ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \ + || \ + ((*p) == 0xF0 \ + ? \ + (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \ + : \ + ((p)[1] & 0x80) == 0 \ + || \ + ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0))) + +static int PTRFASTCALL +isNever(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + UNUSED(p); + + return 0; +} + +static int PTRFASTCALL +utf8_isName2(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); +} + +static int PTRFASTCALL +utf8_isName3(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); +} + +#define utf8_isName4 isNever + +static int PTRFASTCALL +utf8_isNmstrt2(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); +} + +static int PTRFASTCALL +utf8_isNmstrt3(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); +} + +#define utf8_isNmstrt4 isNever + +static int PTRFASTCALL +utf8_isInvalid2(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_INVALID2((const unsigned char *)p); +} + +static int PTRFASTCALL +utf8_isInvalid3(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_INVALID3((const unsigned char *)p); +} + +static int PTRFASTCALL +utf8_isInvalid4(const ENCODING *enc, const char *p) +{ + UNUSED(enc); + + return UTF8_INVALID4((const unsigned char *)p); +} + +struct normal_encoding { + ENCODING enc; + unsigned char type[256]; +#ifdef XML_MIN_SIZE + int (PTRFASTCALL *byteType)(const ENCODING *, const char *); + int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *); + int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *); + int (PTRCALL *charMatches)(const ENCODING *, const char *, int); +#endif /* XML_MIN_SIZE */ + int (PTRFASTCALL *isName2)(const ENCODING *, const char *); + int (PTRFASTCALL *isName3)(const ENCODING *, const char *); + int (PTRFASTCALL *isName4)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *); + int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *); + int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *); +}; + +#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc)) + +#ifdef XML_MIN_SIZE + +#define STANDARD_VTABLE(E) \ + E ## byteType, \ + E ## isNameMin, \ + E ## isNmstrtMin, \ + E ## byteToAscii, \ + E ## charMatches, + +#define ZERO_VTABLE /* as nothing */ + +#else + +#define STANDARD_VTABLE(E) /* as nothing */ + +#define ZERO_VTABLE \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0 + +#endif + +#define NORMAL_VTABLE(E) \ + E ## isName2, \ + E ## isName3, \ + E ## isName4, \ + E ## isNmstrt2, \ + E ## isNmstrt3, \ + E ## isNmstrt4, \ + E ## isInvalid2, \ + E ## isInvalid3, \ + E ## isInvalid4 + +static int FASTCALL checkCharRefNumber(int); + +#include "xmltok_impl.h" +#include "ascii.h" + +#ifdef XML_MIN_SIZE +#define sb_isNameMin isNever +#define sb_isNmstrtMin isNever +#endif + +#ifdef XML_MIN_SIZE +#define MINBPC(enc) ((enc)->minBytesPerChar) +#else +/* minimum bytes per character */ +#define MINBPC(enc) 1 +#endif + +#define SB_BYTE_TYPE(enc, p) \ + (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) + +#ifdef XML_MIN_SIZE +static int PTRFASTCALL +sb_byteType(const ENCODING *enc, const char *p) +{ + return SB_BYTE_TYPE(enc, p); +} +#define BYTE_TYPE(enc, p) \ + (AS_NORMAL_ENCODING(enc)->byteType(enc, p)) +#else +#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) +#endif + +#ifdef XML_MIN_SIZE +#define BYTE_TO_ASCII(enc, p) \ + (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p)) +static int PTRFASTCALL +sb_byteToAscii(const ENCODING *enc, const char *p) +{ + return *p; +} +#else +#define BYTE_TO_ASCII(enc, p) (*(p)) +#endif + +#define IS_NAME_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p)) +#define IS_NMSTRT_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p)) +#define IS_INVALID_CHAR(enc, p, n) \ + (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p)) + +#ifdef XML_MIN_SIZE +#define IS_NAME_CHAR_MINBPC(enc, p) \ + (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p)) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ + (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p)) +#else +#define IS_NAME_CHAR_MINBPC(enc, p) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) +#endif + +#ifdef XML_MIN_SIZE +#define CHAR_MATCHES(enc, p, c) \ + (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c)) +static int PTRCALL +sb_charMatches(const ENCODING *enc, const char *p, int c) +{ + return *p == c; +} +#else +/* c is an ASCII character */ +#define CHAR_MATCHES(enc, p, c) (*(p) == c) +#endif + +#define PREFIX(ident) normal_ ## ident +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ + UTF8_cval1 = 0x00, + UTF8_cval2 = 0xc0, + UTF8_cval3 = 0xe0, + UTF8_cval4 = 0xf0 +}; + +static void PTRCALL +utf8_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + char *to; + const char *from; + + UNUSED(enc); + + if (fromLim - *fromP > toLim - *toP) { + /* Avoid copying partial characters. */ + for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) + if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) + break; + } + for (to = *toP, from = *fromP; from != fromLim; from++, to++) + *to = *from; + *fromP = from; + *toP = to; +} + +static void PTRCALL +utf8_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + unsigned short *to = *toP; + const char *from = *fromP; + while (from != fromLim && to != toLim) { + switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { + case BT_LEAD2: + *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); + from += 2; + break; + case BT_LEAD3: + *to++ = (unsigned short)(((from[0] & 0xf) << 12) + | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); + from += 3; + break; + case BT_LEAD4: + { + unsigned long n; + if (to + 1 == toLim) + goto after; + n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) + | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); + n -= 0x10000; + to[0] = (unsigned short)((n >> 10) | 0xD800); + to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); + to += 2; + from += 4; + } + break; + default: + *to++ = *from++; + break; + } + } +after: + *fromP = from; + *toP = to; +} + +#ifdef XML_NS +static const struct normal_encoding utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; +#endif + +static const struct normal_encoding utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +#ifdef XML_NS + +static const struct normal_encoding internal_utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "iasciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +#endif + +static const struct normal_encoding internal_utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static void PTRCALL +latin1_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + UNUSED(enc); + + for (;;) { + unsigned char c; + if (*fromP == fromLim) + break; + c = (unsigned char)**fromP; + if (c & 0x80) { + if (toLim - *toP < 2) + break; + *(*toP)++ = (char)((c >> 6) | UTF8_cval2); + *(*toP)++ = (char)((c & 0x3f) | 0x80); + (*fromP)++; + } + else { + if (*toP == toLim) + break; + *(*toP)++ = *(*fromP)++; + } + } +} + +static void PTRCALL +latin1_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + UNUSED(enc); + + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = (unsigned char)*(*fromP)++; +} + +#ifdef XML_NS + +static const struct normal_encoding latin1_encoding_ns = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding latin1_encoding = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) ZERO_VTABLE +}; + +static void PTRCALL +ascii_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + UNUSED(enc); + + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = *(*fromP)++; +} + +#ifdef XML_NS + +static const struct normal_encoding ascii_encoding_ns = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding ascii_encoding = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) ZERO_VTABLE +}; + +static int PTRFASTCALL +unicode_byte_type(char hi, char lo) +{ + switch ((unsigned char)hi) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + return BT_LEAD4; + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return BT_TRAIL; + case 0xFF: + switch ((unsigned char)lo) { + case 0xFF: + case 0xFE: + return BT_NONXML; + } + break; + } + return BT_NONASCII; +} + +#define DEFINE_UTF16_TO_UTF8(E) \ +static void PTRCALL \ +E ## toUtf8(const ENCODING *enc, \ + const char **fromP, const char *fromLim, \ + char **toP, const char *toLim) \ +{ \ + const char *from; \ + UNUSED(enc); \ + for (from = *fromP; from != fromLim; from += 2) { \ + int plane; \ + unsigned char lo2; \ + unsigned char lo = GET_LO(from); \ + unsigned char hi = GET_HI(from); \ + switch (hi) { \ + case 0: \ + if (lo < 0x80) { \ + if (*toP == toLim) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = lo; \ + break; \ + } \ + /* fall through */ \ + case 0x1: case 0x2: case 0x3: \ + case 0x4: case 0x5: case 0x6: case 0x7: \ + if (toLim - *toP < 2) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + default: \ + if (toLim - *toP < 3) { \ + *fromP = from; \ + return; \ + } \ + /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ + *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ + *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ + if (toLim - *toP < 4) { \ + *fromP = from; \ + return; \ + } \ + plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ + *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ + *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ + from += 2; \ + lo2 = GET_LO(from); \ + *(*toP)++ = (((lo & 0x3) << 4) \ + | ((GET_HI(from) & 0x3) << 2) \ + | (lo2 >> 6) \ + | 0x80); \ + *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ + break; \ + } \ + } \ + *fromP = from; \ +} + +#define DEFINE_UTF16_TO_UTF16(E) \ +static void PTRCALL \ +E ## toUtf16(const ENCODING *enc, \ + const char **fromP, const char *fromLim, \ + unsigned short **toP, const unsigned short *toLim) \ +{ \ + UNUSED(enc); \ + /* Avoid copying first half only of surrogate */ \ + if (fromLim - *fromP > ((toLim - *toP) << 1) \ + && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ + fromLim -= 2; \ + for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ + *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ +} + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) +#define GET_LO(ptr) ((unsigned char)(ptr)[0]) +#define GET_HI(ptr) ((unsigned char)(ptr)[1]) + +DEFINE_UTF16_TO_UTF8(little2_) +DEFINE_UTF16_TO_UTF16(little2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) +#define GET_LO(ptr) ((unsigned char)(ptr)[1]) +#define GET_HI(ptr) ((unsigned char)(ptr)[0]) + +DEFINE_UTF16_TO_UTF8(big2_) +DEFINE_UTF16_TO_UTF16(big2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define LITTLE2_BYTE_TYPE(enc, p) \ + ((p)[1] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ + : unicode_byte_type((p)[1], (p)[0])) +#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) +#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) +#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) +#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) + +#ifdef XML_MIN_SIZE + +static int PTRFASTCALL +little2_byteType(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TYPE(enc, p); +} + +static int PTRFASTCALL +little2_byteToAscii(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TO_ASCII(enc, p); +} + +static int PTRCALL +little2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return LITTLE2_CHAR_MATCHES(enc, p, c); +} + +static int PTRFASTCALL +little2_isNameMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static int PTRFASTCALL +little2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) little2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +#ifdef XML_NS + +static const struct normal_encoding little2_encoding_ns = { + { VTABLE, 2, 0, +#if BYTEORDER == 1234 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding little2_encoding = { + { VTABLE, 2, 0, +#if BYTEORDER == 1234 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) ZERO_VTABLE +}; + +#if BYTEORDER != 4321 + +#ifdef XML_NS + +static const struct normal_encoding internal_little2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding internal_little2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) ZERO_VTABLE +}; + +#endif + + +#define BIG2_BYTE_TYPE(enc, p) \ + ((p)[0] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ + : unicode_byte_type((p)[0], (p)[1])) +#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) +#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) +#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) +#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) + +#ifdef XML_MIN_SIZE + +static int PTRFASTCALL +big2_byteType(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TYPE(enc, p); +} + +static int PTRFASTCALL +big2_byteToAscii(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TO_ASCII(enc, p); +} + +static int PTRCALL +big2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return BIG2_CHAR_MATCHES(enc, p, c); +} + +static int PTRFASTCALL +big2_isNameMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static int PTRFASTCALL +big2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) big2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +#ifdef XML_NS + +static const struct normal_encoding big2_encoding_ns = { + { VTABLE, 2, 0, +#if BYTEORDER == 4321 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding big2_encoding = { + { VTABLE, 2, 0, +#if BYTEORDER == 4321 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) ZERO_VTABLE +}; + +#if BYTEORDER != 1234 + +#ifdef XML_NS + +static const struct normal_encoding internal_big2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) ZERO_VTABLE +}; + +#endif + +static const struct normal_encoding internal_big2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) ZERO_VTABLE +}; + +#endif + +#undef PREFIX + +static int FASTCALL +streqci(const char *s1, const char *s2) +{ + for (;;) { + char c1 = *s1++; + char c2 = *s2++; + if (ASCII_a <= c1 && c1 <= ASCII_z) + c1 += ASCII_A - ASCII_a; + if (ASCII_a <= c2 && c2 <= ASCII_z) + c2 += ASCII_A - ASCII_a; + if (c1 != c2) + return 0; + if (!c1) + break; + } + return 1; +} + +static void PTRCALL +initUpdatePosition(const ENCODING *enc, const char *ptr, + const char *end, POSITION *pos) +{ + UNUSED(enc); + normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); +} + +static int +toAscii(const ENCODING *enc, const char *ptr, const char *end) +{ + char buf[1]; + char *p = buf; + XmlUtf8Convert(enc, &ptr, end, &p, p + 1); + if (p == buf) + return -1; + else + return buf[0]; +} + +static int FASTCALL +isSpace(int c) +{ + switch (c) { + case 0x20: + case 0xD: + case 0xA: + case 0x9: + return 1; + } + return 0; +} + +/* Return 1 if there's just optional white space or there's an S + followed by name=val. +*/ +static int +parsePseudoAttribute(const ENCODING *enc, + const char *ptr, + const char *end, + const char **namePtr, + const char **nameEndPtr, + const char **valPtr, + const char **nextTokPtr) +{ + int c; + char open; + if (ptr == end) { + *namePtr = NULL; + return 1; + } + if (!isSpace(toAscii(enc, ptr, end))) { + *nextTokPtr = ptr; + return 0; + } + do { + ptr += enc->minBytesPerChar; + } while (isSpace(toAscii(enc, ptr, end))); + if (ptr == end) { + *namePtr = NULL; + return 1; + } + *namePtr = ptr; + for (;;) { + c = toAscii(enc, ptr, end); + if (c == -1) { + *nextTokPtr = ptr; + return 0; + } + if (c == ASCII_EQUALS) { + *nameEndPtr = ptr; + break; + } + if (isSpace(c)) { + *nameEndPtr = ptr; + do { + ptr += enc->minBytesPerChar; + } while (isSpace(c = toAscii(enc, ptr, end))); + if (c != ASCII_EQUALS) { + *nextTokPtr = ptr; + return 0; + } + break; + } + ptr += enc->minBytesPerChar; + } + if (ptr == *namePtr) { + *nextTokPtr = ptr; + return 0; + } + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + while (isSpace(c)) { + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + } + if (c != ASCII_QUOT && c != ASCII_APOS) { + *nextTokPtr = ptr; + return 0; + } + open = (char)c; + ptr += enc->minBytesPerChar; + *valPtr = ptr; + for (;; ptr += enc->minBytesPerChar) { + c = toAscii(enc, ptr, end); + if (c == open) + break; + if (!(ASCII_a <= c && c <= ASCII_z) + && !(ASCII_A <= c && c <= ASCII_Z) + && !(ASCII_0 <= c && c <= ASCII_9) + && c != ASCII_PERIOD + && c != ASCII_MINUS + && c != ASCII_UNDERSCORE) { + *nextTokPtr = ptr; + return 0; + } + } + *nextTokPtr = ptr + enc->minBytesPerChar; + return 1; +} + +static const char KW_version[] = { + ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' +}; + +static const char KW_encoding[] = { + ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' +}; + +static const char KW_standalone[] = { + ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, + ASCII_n, ASCII_e, '\0' +}; + +static const char KW_yes[] = { + ASCII_y, ASCII_e, ASCII_s, '\0' +}; + +static const char KW_no[] = { + ASCII_n, ASCII_o, '\0' +}; + +static int +doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, + const char *, + const char *), + int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingName, + const ENCODING **encoding, + int *standalone) +{ + const char *val = NULL; + const char *name = NULL; + const char *nameEnd = NULL; + ptr += 5 * enc->minBytesPerChar; + end -= 2 * enc->minBytesPerChar; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) + || !name) { + *badPtr = ptr; + return 0; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { + if (!isGeneralTextEntity) { + *badPtr = name; + return 0; + } + } + else { + if (versionPtr) + *versionPtr = val; + if (versionEndPtr) + *versionEndPtr = ptr; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) { + if (isGeneralTextEntity) { + /* a TextDecl must have an EncodingDecl */ + *badPtr = ptr; + return 0; + } + return 1; + } + } + if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { + int c = toAscii(enc, val, end); + if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { + *badPtr = val; + return 0; + } + if (encodingName) + *encodingName = val; + if (encoding) + *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) + return 1; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) + || isGeneralTextEntity) { + *badPtr = name; + return 0; + } + if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { + if (standalone) + *standalone = 1; + } + else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { + if (standalone) + *standalone = 0; + } + else { + *badPtr = val; + return 0; + } + while (isSpace(toAscii(enc, ptr, end))) + ptr += enc->minBytesPerChar; + if (ptr != end) { + *badPtr = ptr; + return 0; + } + return 1; +} + +static int FASTCALL +checkCharRefNumber(int result) +{ + switch (result >> 8) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return -1; + case 0: + if (latin1_encoding.type[result] == BT_NONXML) + return -1; + break; + case 0xFF: + if (result == 0xFFFE || result == 0xFFFF) + return -1; + break; + } + return result; +} + +int FASTCALL +XmlUtf8Encode(int c, char *buf) +{ + enum { + /* minN is minimum legal resulting value for N byte sequence */ + min2 = 0x80, + min3 = 0x800, + min4 = 0x10000 + }; + + if (c < 0) + return 0; + if (c < min2) { + buf[0] = (char)(c | UTF8_cval1); + return 1; + } + if (c < min3) { + buf[0] = (char)((c >> 6) | UTF8_cval2); + buf[1] = (char)((c & 0x3f) | 0x80); + return 2; + } + if (c < min4) { + buf[0] = (char)((c >> 12) | UTF8_cval3); + buf[1] = (char)(((c >> 6) & 0x3f) | 0x80); + buf[2] = (char)((c & 0x3f) | 0x80); + return 3; + } + if (c < 0x110000) { + buf[0] = (char)((c >> 18) | UTF8_cval4); + buf[1] = (char)(((c >> 12) & 0x3f) | 0x80); + buf[2] = (char)(((c >> 6) & 0x3f) | 0x80); + buf[3] = (char)((c & 0x3f) | 0x80); + return 4; + } + return 0; +} + +int FASTCALL +XmlUtf16Encode(int charNum, unsigned short *buf) +{ + if (charNum < 0) + return 0; + if (charNum < 0x10000) { + buf[0] = (unsigned short)charNum; + return 1; + } + if (charNum < 0x110000) { + charNum -= 0x10000; + buf[0] = (unsigned short)((charNum >> 10) + 0xD800); + buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00); + return 2; + } + return 0; +} + +struct unknown_encoding { + struct normal_encoding normal; + CONVERTER convert; + void *userData; + unsigned short utf16[256]; + char utf8[256][4]; +}; + +#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc)) + +int +XmlSizeOfUnknownEncoding(void) +{ + return sizeof(struct unknown_encoding); +} + +static int PTRFASTCALL +unknown_isName(const ENCODING *enc, const char *p) +{ + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); +} + +static int PTRFASTCALL +unknown_isNmstrt(const ENCODING *enc, const char *p) +{ + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); +} + +static int PTRFASTCALL +unknown_isInvalid(const ENCODING *enc, const char *p) +{ + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + int c = uenc->convert(uenc->userData, p); + return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; +} + +static void PTRCALL +unknown_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + char buf[XML_UTF8_ENCODE_MAX]; + for (;;) { + const char *utf8; + int n; + if (*fromP == fromLim) + break; + utf8 = uenc->utf8[(unsigned char)**fromP]; + n = *utf8++; + if (n == 0) { + int c = uenc->convert(uenc->userData, *fromP); + n = XmlUtf8Encode(c, buf); + if (n > toLim - *toP) + break; + utf8 = buf; + *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2)); + } + else { + if (n > toLim - *toP) + break; + (*fromP)++; + } + do { + *(*toP)++ = *utf8++; + } while (--n != 0); + } +} + +static void PTRCALL +unknown_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); + while (*fromP != fromLim && *toP != toLim) { + unsigned short c = uenc->utf16[(unsigned char)**fromP]; + if (c == 0) { + c = (unsigned short) + uenc->convert(uenc->userData, *fromP); + *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2)); + } + else + (*fromP)++; + *(*toP)++ = c; + } +} + +ENCODING * +XmlInitUnknownEncoding(void *mem, + int *table, + CONVERTER convert, + void *userData) +{ + int i; + struct unknown_encoding *e = (struct unknown_encoding *)mem; + for (i = 0; i < (int)sizeof(struct normal_encoding); i++) + ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; + for (i = 0; i < 128; i++) + if (latin1_encoding.type[i] != BT_OTHER + && latin1_encoding.type[i] != BT_NONXML + && table[i] != i) + return 0; + for (i = 0; i < 256; i++) { + int c = table[i]; + if (c == -1) { + e->normal.type[i] = BT_MALFORM; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else if (c < 0) { + if (c < -4) + return 0; + e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2)); + e->utf8[i][0] = 0; + e->utf16[i] = 0; + } + else if (c < 0x80) { + if (latin1_encoding.type[c] != BT_OTHER + && latin1_encoding.type[c] != BT_NONXML + && c != i) + return 0; + e->normal.type[i] = latin1_encoding.type[c]; + e->utf8[i][0] = 1; + e->utf8[i][1] = (char)c; + e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c); + } + else if (checkCharRefNumber(c) < 0) { + e->normal.type[i] = BT_NONXML; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else { + if (c > 0xFFFF) + return 0; + if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NMSTRT; + else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NAME; + else + e->normal.type[i] = BT_OTHER; + e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); + e->utf16[i] = (unsigned short)c; + } + } + e->userData = userData; + e->convert = convert; + if (convert) { + e->normal.isName2 = unknown_isName; + e->normal.isName3 = unknown_isName; + e->normal.isName4 = unknown_isName; + e->normal.isNmstrt2 = unknown_isNmstrt; + e->normal.isNmstrt3 = unknown_isNmstrt; + e->normal.isNmstrt4 = unknown_isNmstrt; + e->normal.isInvalid2 = unknown_isInvalid; + e->normal.isInvalid3 = unknown_isInvalid; + e->normal.isInvalid4 = unknown_isInvalid; + } + e->normal.enc.utf8Convert = unknown_toUtf8; + e->normal.enc.utf16Convert = unknown_toUtf16; + return &(e->normal.enc); +} + +/* If this enumeration is changed, getEncodingIndex and encodings +must also be changed. */ +enum { + UNKNOWN_ENC = -1, + ISO_8859_1_ENC = 0, + US_ASCII_ENC, + UTF_8_ENC, + UTF_16_ENC, + UTF_16BE_ENC, + UTF_16LE_ENC, + /* must match encodingNames up to here */ + NO_ENC +}; + +static const char KW_ISO_8859_1[] = { + ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, + ASCII_MINUS, ASCII_1, '\0' +}; +static const char KW_US_ASCII[] = { + ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, + '\0' +}; +static const char KW_UTF_8[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' +}; +static const char KW_UTF_16[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' +}; +static const char KW_UTF_16BE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, + '\0' +}; +static const char KW_UTF_16LE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, + '\0' +}; + +static int FASTCALL +getEncodingIndex(const char *name) +{ + static const char * const encodingNames[] = { + KW_ISO_8859_1, + KW_US_ASCII, + KW_UTF_8, + KW_UTF_16, + KW_UTF_16BE, + KW_UTF_16LE, + }; + int i; + if (name == NULL) + return NO_ENC; + for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) + if (streqci(name, encodingNames[i])) + return i; + return UNKNOWN_ENC; +} + +/* For binary compatibility, we store the index of the encoding + specified at initialization in the isUtf16 member. +*/ + +#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) +#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) + +/* This is what detects the encoding. encodingTable maps from + encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of + the external (protocol) specified encoding; state is + XML_CONTENT_STATE if we're parsing an external text entity, and + XML_PROLOG_STATE otherwise. +*/ + + +static int +initScan(const ENCODING * const *encodingTable, + const INIT_ENCODING *enc, + int state, + const char *ptr, + const char *end, + const char **nextTokPtr) +{ + const ENCODING **encPtr; + + if (ptr == end) + return XML_TOK_NONE; + encPtr = enc->encPtr; + if (ptr + 1 == end) { + /* only a single byte available for auto-detection */ +#ifndef XML_DTD /* FIXME */ + /* a well-formed document entity must have more than one byte */ + if (state != XML_CONTENT_STATE) + return XML_TOK_PARTIAL; +#endif + /* so we're parsing an external text entity... */ + /* if UTF-16 was externally specified, then we need at least 2 bytes */ + switch (INIT_ENC_INDEX(enc)) { + case UTF_16_ENC: + case UTF_16LE_ENC: + case UTF_16BE_ENC: + return XML_TOK_PARTIAL; + } + switch ((unsigned char)*ptr) { + case 0xFE: + case 0xFF: + case 0xEF: /* possibly first byte of UTF-8 BOM */ + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + /* fall through */ + case 0x00: + case 0x3C: + return XML_TOK_PARTIAL; + } + } + else { + switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { + case 0xFEFF: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XML_TOK_BOM; + /* 00 3C is handled in the default case */ + case 0x3C00: + if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC + || INIT_ENC_INDEX(enc) == UTF_16_ENC) + && state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + case 0xFFFE: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XML_TOK_BOM; + case 0xEFBB: + /* Maybe a UTF-8 BOM (EF BB BF) */ + /* If there's an explicitly specified (external) encoding + of ISO-8859-1 or some flavour of UTF-16 + and this is an external text entity, + don't look for the BOM, + because it might be a legal data. + */ + if (state == XML_CONTENT_STATE) { + int e = INIT_ENC_INDEX(enc); + if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC + || e == UTF_16LE_ENC || e == UTF_16_ENC) + break; + } + if (ptr + 2 == end) + return XML_TOK_PARTIAL; + if ((unsigned char)ptr[2] == 0xBF) { + *nextTokPtr = ptr + 3; + *encPtr = encodingTable[UTF_8_ENC]; + return XML_TOK_BOM; + } + break; + default: + if (ptr[0] == '\0') { + /* 0 isn't a legal data character. Furthermore a document + entity can only start with ASCII characters. So the only + way this can fail to be big-endian UTF-16 if it it's an + external parsed general entity that's labelled as + UTF-16LE. + */ + if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) + break; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + else if (ptr[1] == '\0') { + /* We could recover here in the case: + - parsing an external entity + - second byte is 0 + - no externally specified encoding + - no encoding declaration + by assuming UTF-16LE. But we don't, because this would mean when + presented just with a single byte, we couldn't reliably determine + whether we needed further bytes. + */ + if (state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + break; + } + } + *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); +} + + +#define NS(x) x +#define ns(x) x +#include "xmltok_ns.c" +#undef NS +#undef ns + +#ifdef XML_NS + +#define NS(x) x ## NS +#define ns(x) x ## _ns + +#include "xmltok_ns.c" + +#undef NS +#undef ns + +ENCODING * +XmlInitUnknownEncodingNS(void *mem, + int *table, + CONVERTER convert, + void *userData) +{ + ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); + if (enc) + ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; + return enc; +} + +#endif /* XML_NS */ diff --git a/libxsde/xsde/c/expat/xmltok.h b/libxsde/xsde/c/expat/xmltok.h new file mode 100644 index 0000000..ca867aa --- /dev/null +++ b/libxsde/xsde/c/expat/xmltok.h @@ -0,0 +1,316 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef XmlTok_INCLUDED +#define XmlTok_INCLUDED 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* The following token may be returned by XmlContentTok */ +#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be + start of illegal ]]> sequence */ +/* The following tokens may be returned by both XmlPrologTok and + XmlContentTok. +*/ +#define XML_TOK_NONE -4 /* The string to be scanned is empty */ +#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; + might be part of CRLF sequence */ +#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ +#define XML_TOK_PARTIAL -1 /* only part of a token */ +#define XML_TOK_INVALID 0 + +/* The following tokens are returned by XmlContentTok; some are also + returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. +*/ +#define XML_TOK_START_TAG_WITH_ATTS 1 +#define XML_TOK_START_TAG_NO_ATTS 2 +#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ +#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 +#define XML_TOK_END_TAG 5 +#define XML_TOK_DATA_CHARS 6 +#define XML_TOK_DATA_NEWLINE 7 +#define XML_TOK_CDATA_SECT_OPEN 8 +#define XML_TOK_ENTITY_REF 9 +#define XML_TOK_CHAR_REF 10 /* numeric character reference */ + +/* The following tokens may be returned by both XmlPrologTok and + XmlContentTok. +*/ +#define XML_TOK_PI 11 /* processing instruction */ +#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ +#define XML_TOK_COMMENT 13 +#define XML_TOK_BOM 14 /* Byte order mark */ + +/* The following tokens are returned only by XmlPrologTok */ +#define XML_TOK_PROLOG_S 15 +#define XML_TOK_DECL_OPEN 16 /* */ +#define XML_TOK_NAME 18 +#define XML_TOK_NMTOKEN 19 +#define XML_TOK_POUND_NAME 20 /* #name */ +#define XML_TOK_OR 21 /* | */ +#define XML_TOK_PERCENT 22 +#define XML_TOK_OPEN_PAREN 23 +#define XML_TOK_CLOSE_PAREN 24 +#define XML_TOK_OPEN_BRACKET 25 +#define XML_TOK_CLOSE_BRACKET 26 +#define XML_TOK_LITERAL 27 +#define XML_TOK_PARAM_ENTITY_REF 28 +#define XML_TOK_INSTANCE_START 29 + +/* The following occur only in element type declarations */ +#define XML_TOK_NAME_QUESTION 30 /* name? */ +#define XML_TOK_NAME_ASTERISK 31 /* name* */ +#define XML_TOK_NAME_PLUS 32 /* name+ */ +#define XML_TOK_COND_SECT_OPEN 33 /* */ +#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ +#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ +#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ +#define XML_TOK_COMMA 38 + +/* The following token is returned only by XmlAttributeValueTok */ +#define XML_TOK_ATTRIBUTE_VALUE_S 39 + +/* The following token is returned only by XmlCdataSectionTok */ +#define XML_TOK_CDATA_SECT_CLOSE 40 + +/* With namespace processing this is returned by XmlPrologTok for a + name with a colon. +*/ +#define XML_TOK_PREFIXED_NAME 41 + +#ifdef XML_DTD +#define XML_TOK_IGNORE_SECT 42 +#endif /* XML_DTD */ + +#ifdef XML_DTD +#define XML_N_STATES 4 +#else /* not XML_DTD */ +#define XML_N_STATES 3 +#endif /* not XML_DTD */ + +#define XML_PROLOG_STATE 0 +#define XML_CONTENT_STATE 1 +#define XML_CDATA_SECTION_STATE 2 +#ifdef XML_DTD +#define XML_IGNORE_SECTION_STATE 3 +#endif /* XML_DTD */ + +#define XML_N_LITERAL_TYPES 2 +#define XML_ATTRIBUTE_VALUE_LITERAL 0 +#define XML_ENTITY_VALUE_LITERAL 1 + +/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ +#define XML_UTF8_ENCODE_MAX 4 +/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ +#define XML_UTF16_ENCODE_MAX 2 + +typedef struct position { + /* first line and first column are 0 not 1 */ + XML_Size lineNumber; + XML_Size columnNumber; +} POSITION; + +typedef struct { + const char *name; + const char *valuePtr; + const char *valueEnd; + char normalized; +} ATTRIBUTE; + +struct encoding; +typedef struct encoding ENCODING; + +typedef int (PTRCALL *SCANNER)(const ENCODING *, + const char *, + const char *, + const char **); + +struct encoding { + SCANNER scanners[XML_N_STATES]; + SCANNER literalScanners[XML_N_LITERAL_TYPES]; + int (PTRCALL *sameName)(const ENCODING *, + const char *, + const char *); + int (PTRCALL *nameMatchesAscii)(const ENCODING *, + const char *, + const char *, + const char *); + int (PTRFASTCALL *nameLength)(const ENCODING *, const char *); + const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); + int (PTRCALL *getAtts)(const ENCODING *enc, + const char *ptr, + int attsMax, + ATTRIBUTE *atts); + int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); + int (PTRCALL *predefinedEntityName)(const ENCODING *, + const char *, + const char *); + void (PTRCALL *updatePosition)(const ENCODING *, + const char *ptr, + const char *end, + POSITION *); + int (PTRCALL *isPublicId)(const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr); + void (PTRCALL *utf8Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + char **toP, + const char *toLim); + void (PTRCALL *utf16Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + unsigned short **toP, + const unsigned short *toLim); + int minBytesPerChar; + char isUtf8; + char isUtf16; +}; + +/* Scan the string starting at ptr until the end of the next complete + token, but do not scan past eptr. Return an integer giving the + type of token. + + Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. + + Return XML_TOK_PARTIAL when the string does not contain a complete + token; nextTokPtr will not be set. + + Return XML_TOK_INVALID when the string does not start a valid + token; nextTokPtr will be set to point to the character which made + the token invalid. + + Otherwise the string starts with a valid token; nextTokPtr will be + set to point to the character following the end of that token. + + Each data character counts as a single token, but adjacent data + characters may be returned together. Similarly for characters in + the prolog outside literals, comments and processing instructions. +*/ + + +#define XmlTok(enc, state, ptr, end, nextTokPtr) \ + (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) + +#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) + +#define XmlContentTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) + +#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) + +#ifdef XML_DTD + +#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) + +#endif /* XML_DTD */ + +/* This is used for performing a 2nd-level tokenization on the content + of a literal that has already been returned by XmlTok. +*/ +#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ + (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) + +#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) + +#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ + (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) + +#define XmlNameLength(enc, ptr) \ + (((enc)->nameLength)(enc, ptr)) + +#define XmlSkipS(enc, ptr) \ + (((enc)->skipS)(enc, ptr)) + +#define XmlGetAttributes(enc, ptr, attsMax, atts) \ + (((enc)->getAtts)(enc, ptr, attsMax, atts)) + +#define XmlCharRefNumber(enc, ptr) \ + (((enc)->charRefNumber)(enc, ptr)) + +#define XmlPredefinedEntityName(enc, ptr, end) \ + (((enc)->predefinedEntityName)(enc, ptr, end)) + +#define XmlUpdatePosition(enc, ptr, end, pos) \ + (((enc)->updatePosition)(enc, ptr, end, pos)) + +#define XmlIsPublicId(enc, ptr, end, badPtr) \ + (((enc)->isPublicId)(enc, ptr, end, badPtr)) + +#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) + +#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) + +typedef struct { + ENCODING initEnc; + const ENCODING **encPtr; +} INIT_ENCODING; + +int XmlParseXmlDecl(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); + +int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncoding(void); +const ENCODING *XmlGetUtf16InternalEncoding(void); +int FASTCALL XmlUtf8Encode(int charNumber, char *buf); +int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); +int XmlSizeOfUnknownEncoding(void); + + +typedef int (XMLCALL *CONVERTER) (void *userData, const char *p); + +ENCODING * +XmlInitUnknownEncoding(void *mem, + int *table, + CONVERTER convert, + void *userData); + +int XmlParseXmlDeclNS(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); + +int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncodingNS(void); +const ENCODING *XmlGetUtf16InternalEncodingNS(void); +ENCODING * +XmlInitUnknownEncodingNS(void *mem, + int *table, + CONVERTER convert, + void *userData); +#ifdef __cplusplus +} +#endif + +#endif /* not XmlTok_INCLUDED */ diff --git a/libxsde/xsde/c/expat/xmltok_impl.c b/libxsde/xsde/c/expat/xmltok_impl.c new file mode 100644 index 0000000..b0d23c8 --- /dev/null +++ b/libxsde/xsde/c/expat/xmltok_impl.c @@ -0,0 +1,1792 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef IS_INVALID_CHAR +#define IS_INVALID_CHAR(enc, ptr, n) (0) +#endif + +#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_INVALID_CHAR(enc, ptr, n)) { \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define INVALID_CASES(ptr, nextTokPtr) \ + INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ + case BT_NONXML: \ + case BT_MALFORM: \ + case BT_TRAIL: \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; + +#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NAME_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + case BT_DIGIT: \ + case BT_NAME: \ + case BT_MINUS: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) + +#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) + +#ifndef PREFIX +#define PREFIX(ident) ident +#endif + +/* ptr points to character following " */ + switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { + case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + /* fall through */ + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DECL_OPEN; + case BT_NMSTRT: + case BT_HEX: + ptr += MINBPC(enc); + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static int PTRCALL +PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, + const char *end, int *tokPtr) +{ + int upper = 0; + + UNUSED(enc); + + *tokPtr = XML_TOK_PI; + if (end - ptr != MINBPC(enc)*3) + return 1; + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_x: + break; + case ASCII_X: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_m: + break; + case ASCII_M: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + break; + case ASCII_L: + upper = 1; + break; + default: + return 1; + } + if (upper) + return 0; + *tokPtr = XML_TOK_XML_DECL; + return 1; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CDATA_SECT_CLOSE; + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + case BT_RSQB: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_LT: + return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_AMP: + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_RSQB: + if (ptr + MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { + ptr += MINBPC(enc); + break; + } + if (ptr + 2*MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { + ptr += MINBPC(enc); + break; + } + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_AMP: + case BT_LT: + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following "%" */ + +static int PTRCALL +PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return -XML_TOK_PERCENT; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_PERCENT; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_PARAM_ENTITY_REF; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static int PTRCALL +PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_CR: case BT_LF: case BT_S: + case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: + *nextTokPtr = ptr; + return XML_TOK_POUND_NAME; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -XML_TOK_POUND_NAME; +} + +static int PTRCALL +PREFIX(scanLit)(int open, const ENCODING *enc, + const char *ptr, const char *end, + const char **nextTokPtr) +{ + while (ptr != end) { + int t = BYTE_TYPE(enc, ptr); + switch (t) { + INVALID_CASES(ptr, nextTokPtr) + case BT_QUOT: + case BT_APOS: + ptr += MINBPC(enc); + if (t != open) + break; + if (ptr == end) + return -XML_TOK_LITERAL; + *nextTokPtr = ptr; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_CR: case BT_LF: + case BT_GT: case BT_PERCNT: case BT_LSQB: + return XML_TOK_LITERAL; + default: + return XML_TOK_INVALID; + } + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + +static int PTRCALL +PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + int tok; + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_QUOT: + return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_APOS: + return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LT: + { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_EXCL: + return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_QUEST: + return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_NMSTRT: + case BT_HEX: + case BT_NONASCII: + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + *nextTokPtr = ptr - MINBPC(enc); + return XML_TOK_INSTANCE_START; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + case BT_CR: + if (ptr + MINBPC(enc) == end) { + *nextTokPtr = end; + /* indicate that this might be part of a CR/LF pair */ + return -XML_TOK_PROLOG_S; + } + /* fall through */ + case BT_S: case BT_LF: + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + break; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_LF: + break; + case BT_CR: + /* don't split CR/LF pair */ + if (ptr + MINBPC(enc) != end) + break; + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + } + } + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + case BT_PERCNT: + return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_COMMA: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COMMA; + case BT_LSQB: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_BRACKET; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_BRACKET; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if (ptr + MINBPC(enc) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_COND_SECT_CLOSE; + } + } + *nextTokPtr = ptr; + return XML_TOK_CLOSE_BRACKET; + case BT_LPAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_PAREN; + case BT_RPAR: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_PAREN; + switch (BYTE_TYPE(enc, ptr)) { + case BT_AST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_ASTERISK; + case BT_QUEST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_QUESTION; + case BT_PLUS: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_PLUS; + case BT_CR: case BT_LF: case BT_S: + case BT_GT: case BT_COMMA: case BT_VERBAR: + case BT_RPAR: + *nextTokPtr = ptr; + return XML_TOK_CLOSE_PAREN; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_VERBAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OR; + case BT_GT: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DECL_CLOSE; + case BT_NUM: + return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NAME; \ + break; \ + } \ + if (IS_NAME_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NMTOKEN; \ + break; \ + } \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NMSTRT: + case BT_HEX: + tok = XML_TOK_NAME; + ptr += MINBPC(enc); + break; + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: +#ifdef XML_NS + case BT_COLON: +#endif + tok = XML_TOK_NMTOKEN; + ptr += MINBPC(enc); + break; + case BT_NONASCII: + if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NAME; + break; + } + if (IS_NAME_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NMTOKEN; + break; + } + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_GT: case BT_RPAR: case BT_COMMA: + case BT_VERBAR: case BT_LSQB: case BT_PERCNT: + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return tok; +#ifdef XML_NS + case BT_COLON: + ptr += MINBPC(enc); + switch (tok) { + case XML_TOK_NAME: + if (ptr == end) + return XML_TOK_PARTIAL; + tok = XML_TOK_PREFIXED_NAME; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + default: + tok = XML_TOK_NMTOKEN; + break; + } + break; + case XML_TOK_PREFIXED_NAME: + tok = XML_TOK_NMTOKEN; + break; + } + break; +#endif + case BT_PLUS: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_PLUS; + case BT_AST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_ASTERISK; + case BT_QUEST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_QUESTION; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -tok; +} + +static int PTRCALL +PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, + const char *end, const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LT: + /* this is for inside entity references */ + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_S: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_ATTRIBUTE_VALUE_S; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +static int PTRCALL +PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, + const char *end, const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_PERCNT: + if (ptr == start) { + int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), + end, nextTokPtr); + return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +#ifdef XML_DTD + +static int PTRCALL +PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, + const char *end, const char **nextTokPtr) +{ + int level = 0; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + end = ptr + n; + } + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) + case BT_LT: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { + ++level; + ptr += MINBPC(enc); + } + } + break; + case BT_RSQB: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr += MINBPC(enc); + if (level == 0) { + *nextTokPtr = ptr; + return XML_TOK_IGNORE_SECT; + } + --level; + } + } + break; + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + +#endif /* XML_DTD */ + +static int PTRCALL +PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, + const char **badPtr) +{ + ptr += MINBPC(enc); + end -= MINBPC(enc); + for (; ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + case BT_MINUS: + case BT_APOS: + case BT_LPAR: + case BT_RPAR: + case BT_PLUS: + case BT_COMMA: + case BT_SOL: + case BT_EQUALS: + case BT_QUEST: + case BT_CR: + case BT_LF: + case BT_SEMI: + case BT_EXCL: + case BT_AST: + case BT_PERCNT: + case BT_NUM: +#ifdef XML_NS + case BT_COLON: +#endif + break; + case BT_S: + if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { + *badPtr = ptr; + return 0; + } + break; + case BT_NAME: + case BT_NMSTRT: + if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) + break; + default: + switch (BYTE_TO_ASCII(enc, ptr)) { + case 0x24: /* $ */ + case 0x40: /* @ */ + break; + default: + *badPtr = ptr; + return 0; + } + break; + } + } + return 1; +} + +/* This must only be called for a well-formed start-tag or empty + element tag. Returns the number of attributes. Pointers to the + first attsMax attributes are stored in atts. +*/ + +static int PTRCALL +PREFIX(getAtts)(const ENCODING *enc, const char *ptr, + int attsMax, ATTRIBUTE *atts) +{ + enum { other, inName, inValue } state = inName; + int nAtts = 0; + int open = 0; /* defined when state == inValue; + initialization just to shut up compilers */ + + for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { +#define START_NAME \ + if (state == other) { \ + if (nAtts < attsMax) { \ + atts[nAtts].name = ptr; \ + atts[nAtts].normalized = 1; \ + } \ + state = inName; \ + } +#define LEAD_CASE(n) \ + case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: + case BT_HEX: + START_NAME + break; +#undef START_NAME + case BT_QUOT: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_QUOT; + } + else if (open == BT_QUOT) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_APOS: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_APOS; + } + else if (open == BT_APOS) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_AMP: + if (nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_S: + if (state == inName) + state = other; + else if (state == inValue + && nAtts < attsMax + && atts[nAtts].normalized + && (ptr == atts[nAtts].valuePtr + || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE + || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE + || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) + atts[nAtts].normalized = 0; + break; + case BT_CR: case BT_LF: + /* This case ensures that the first attribute name is counted + Apart from that we could just change state on the quote. */ + if (state == inName) + state = other; + else if (state == inValue && nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_GT: + case BT_SOL: + if (state != inValue) + return nAtts; + break; + default: + break; + } + } + /* not reached */ +} + +static int PTRFASTCALL +PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) +{ + int result = 0; + + UNUSED(enc); + + /* skip &# */ + ptr += 2*MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_x)) { + for (ptr += MINBPC(enc); + !CHAR_MATCHES(enc, ptr, ASCII_SEMI); + ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + switch (c) { + case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: + case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: + result <<= 4; + result |= (c - ASCII_0); + break; + case ASCII_A: case ASCII_B: case ASCII_C: + case ASCII_D: case ASCII_E: case ASCII_F: + result <<= 4; + result += 10 + (c - ASCII_A); + break; + case ASCII_a: case ASCII_b: case ASCII_c: + case ASCII_d: case ASCII_e: case ASCII_f: + result <<= 4; + result += 10 + (c - ASCII_a); + break; + } + if (result >= 0x110000) + return -1; + } + } + else { + for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + result *= 10; + result += (c - ASCII_0); + if (result >= 0x110000) + return -1; + } + } + return checkCharRefNumber(result); +} + +static int PTRCALL +PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, + const char *end) +{ + UNUSED(enc); + + switch ((end - ptr)/MINBPC(enc)) { + case 2: + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + return ASCII_LT; + case ASCII_g: + return ASCII_GT; + } + } + break; + case 3: + if (CHAR_MATCHES(enc, ptr, ASCII_a)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_m)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) + return ASCII_AMP; + } + } + break; + case 4: + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_q: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_u)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_t)) + return ASCII_QUOT; + } + } + break; + case ASCII_a: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_s)) + return ASCII_APOS; + } + } + break; + } + } + return 0; +} + +static int PTRCALL +PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr1)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (*ptr1++ != *ptr2++) \ + return 0; + LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) +#undef LEAD_CASE + /* fall through */ + if (*ptr1++ != *ptr2++) + return 0; + break; + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 1) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 2) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 3) { + if (*ptr2++ != *ptr1++) + return 0; + } + } + } + break; + default: + if (MINBPC(enc) == 1 && *ptr1 == *ptr2) + return 1; + switch (BYTE_TYPE(enc, ptr2)) { + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + return 0; + default: + return 1; + } + } + } + /* not reached */ +} + +static int PTRCALL +PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, + const char *end1, const char *ptr2) +{ + UNUSED(enc); + + for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { + if (ptr1 == end1) + return 0; + if (!CHAR_MATCHES(enc, ptr1, *ptr2)) + return 0; + } + return ptr1 == end1; +} + +static int PTRFASTCALL +PREFIX(nameLength)(const ENCODING *enc, const char *ptr) +{ + const char *start = ptr; + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + ptr += MINBPC(enc); + break; + default: + return (int)(ptr - start); + } + } +} + +static const char * PTRFASTCALL +PREFIX(skipS)(const ENCODING *enc, const char *ptr) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_LF: + case BT_CR: + case BT_S: + ptr += MINBPC(enc); + break; + default: + return ptr; + } + } +} + +static void PTRCALL +PREFIX(updatePosition)(const ENCODING *enc, + const char *ptr, + const char *end, + POSITION *pos) +{ + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_LF: + pos->columnNumber = (XML_Size)-1; + pos->lineNumber++; + ptr += MINBPC(enc); + break; + case BT_CR: + pos->lineNumber++; + ptr += MINBPC(enc); + if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + pos->columnNumber = (XML_Size)-1; + break; + default: + ptr += MINBPC(enc); + break; + } + pos->columnNumber++; + } +} + +#undef DO_LEAD_CASE +#undef MULTIBYTE_CASES +#undef INVALID_CASES +#undef CHECK_NAME_CASE +#undef CHECK_NAME_CASES +#undef CHECK_NMSTRT_CASE +#undef CHECK_NMSTRT_CASES + diff --git a/libxsde/xsde/c/expat/xmltok_impl.h b/libxsde/xsde/c/expat/xmltok_impl.h new file mode 100644 index 0000000..da0ea60 --- /dev/null +++ b/libxsde/xsde/c/expat/xmltok_impl.h @@ -0,0 +1,46 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +enum { + BT_NONXML, + BT_MALFORM, + BT_LT, + BT_AMP, + BT_RSQB, + BT_LEAD2, + BT_LEAD3, + BT_LEAD4, + BT_TRAIL, + BT_CR, + BT_LF, + BT_GT, + BT_QUOT, + BT_APOS, + BT_EQUALS, + BT_QUEST, + BT_EXCL, + BT_SOL, + BT_SEMI, + BT_NUM, + BT_LSQB, + BT_S, + BT_NMSTRT, + BT_COLON, + BT_HEX, + BT_DIGIT, + BT_NAME, + BT_MINUS, + BT_OTHER, /* known not to be a name or name start character */ + BT_NONASCII, /* might be a name or name start character */ + BT_PERCNT, + BT_LPAR, + BT_RPAR, + BT_AST, + BT_PLUS, + BT_COMMA, + BT_VERBAR +}; + +#include diff --git a/libxsde/xsde/c/expat/xmltok_ns.c b/libxsde/xsde/c/expat/xmltok_ns.c new file mode 100644 index 0000000..d2f8938 --- /dev/null +++ b/libxsde/xsde/c/expat/xmltok_ns.c @@ -0,0 +1,106 @@ +const ENCODING * +NS(XmlGetUtf8InternalEncoding)(void) +{ + return &ns(internal_utf8_encoding).enc; +} + +const ENCODING * +NS(XmlGetUtf16InternalEncoding)(void) +{ +#if BYTEORDER == 1234 + return &ns(internal_little2_encoding).enc; +#elif BYTEORDER == 4321 + return &ns(internal_big2_encoding).enc; +#else + const short n = 1; + return (*(const char *)&n + ? &ns(internal_little2_encoding).enc + : &ns(internal_big2_encoding).enc); +#endif +} + +static const ENCODING * const NS(encodings)[] = { + &ns(latin1_encoding).enc, + &ns(ascii_encoding).enc, + &ns(utf8_encoding).enc, + &ns(big2_encoding).enc, + &ns(big2_encoding).enc, + &ns(little2_encoding).enc, + &ns(utf8_encoding).enc /* NO_ENC */ +}; + +static int PTRCALL +NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, + XML_PROLOG_STATE, ptr, end, nextTokPtr); +} + +static int PTRCALL +NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, + XML_CONTENT_STATE, ptr, end, nextTokPtr); +} + +int +NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, + const char *name) +{ + int i = getEncodingIndex(name); + if (i == UNKNOWN_ENC) + return 0; + SET_INIT_ENC_INDEX(p, i); + p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); + p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); + p->initEnc.updatePosition = initUpdatePosition; + p->encPtr = encPtr; + *encPtr = &(p->initEnc); + return 1; +} + +static const ENCODING * +NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) +{ +#define ENCODING_MAX 128 + char buf[ENCODING_MAX]; + char *p = buf; + int i; + XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); + if (ptr != end) + return 0; + *p = 0; + if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) + return enc; + i = getEncodingIndex(buf); + if (i == UNKNOWN_ENC) + return 0; + return NS(encodings)[i]; +} + +int +NS(XmlParseXmlDecl)(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingName, + const ENCODING **encoding, + int *standalone) +{ + return doParseXmlDecl(NS(findEncoding), + isGeneralTextEntity, + enc, + ptr, + end, + badPtr, + versionPtr, + versionEndPtr, + encodingName, + encoding, + standalone); +} diff --git a/libxsde/xsde/c/genx/COPYING b/libxsde/xsde/c/genx/COPYING new file mode 100644 index 0000000..e9b23f6 --- /dev/null +++ b/libxsde/xsde/c/genx/COPYING @@ -0,0 +1,39 @@ +Copyright (c) 2007-2009 Code Synthesis Tools CC. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Original Version: + +Copyright (c) Tim Bray and Sun Microsystems, 2004. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/libxsde/xsde/c/genx/char-props.c b/libxsde/xsde/c/genx/char-props.c new file mode 100644 index 0000000..a4fb16a --- /dev/null +++ b/libxsde/xsde/c/genx/char-props.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2007-2009 Code Synthesis Tools CC. + * Copyright (c) 2004 by Tim Bray and Sun Microsystems. + * + * For copying permission, see the accompanying COPYING file. + */ + +/* + * Construct character-properties tables for genx. + * Quite likely there's a better way. + * This version is generated semi-automatically from the source code of the + * XML specification via emacs global replace and keyboard macros + */ +#include "genx.h" + +static void charProp(char * p, int c, int prop) +{ + p[c] |= prop; +} + +static void rangeProp(char * p, int start, int end, int prop) +{ + int i; + for (i = start; i <= end; i++) + p[i] |= prop; +} + +void genxSetCharProps(char * p) +{ + int i; + + for (i = 0; i <= 0xffff; i++) + p[i] = 0; + + /* per XML 1.0 */ + charProp(p, 0x9, GENX_XML_CHAR); + charProp(p, 0xa, GENX_XML_CHAR); + charProp(p, 0xd, GENX_XML_CHAR); + rangeProp(p, 0x20, 0xd7ff, GENX_XML_CHAR); + rangeProp(p, 0xe000, 0xfffd, GENX_XML_CHAR); + + /* Letter ::= BaseChar | Ideographic */ + rangeProp(p, 0x0041, 0x005A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0061, 0x007A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x00C0, 0x00D6, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x00D8, 0x00F6, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x00F8, 0x00FF, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0100, 0x0131, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0134, 0x013E, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0141, 0x0148, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x014A, 0x017E, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0180, 0x01C3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x01CD, 0x01F0, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x01F4, 0x01F5, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x01FA, 0x0217, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0250, 0x02A8, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x02BB, 0x02C1, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0386, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0388, 0x038A, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x038C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x038E, 0x03A1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x03A3, 0x03CE, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x03D0, 0x03D6, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x03DA, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x03DC, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x03DE, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x03E0, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x03E2, 0x03F3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0401, 0x040C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x040E, 0x044F, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0451, 0x045C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x045E, 0x0481, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0490, 0x04C4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x04C7, 0x04C8, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x04CB, 0x04CC, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x04D0, 0x04EB, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x04EE, 0x04F5, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x04F8, 0x04F9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0531, 0x0556, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0559, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0561, 0x0586, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x05D0, 0x05EA, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x05F0, 0x05F2, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0621, 0x063A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0641, 0x064A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0671, 0x06B7, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x06BA, 0x06BE, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x06C0, 0x06CE, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x06D0, 0x06D3, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x06D5, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x06E5, 0x06E6, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0905, 0x0939, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x093D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0958, 0x0961, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0985, 0x098C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x098F, 0x0990, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0993, 0x09A8, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09AA, 0x09B0, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x09B2, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09B6, 0x09B9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09DC, 0x09DD, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09DF, 0x09E1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09F0, 0x09F1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A05, 0x0A0A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A0F, 0x0A10, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A13, 0x0A28, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A2A, 0x0A30, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A32, 0x0A33, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A35, 0x0A36, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A38, 0x0A39, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A59, 0x0A5C, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0A5E, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A72, 0x0A74, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A85, 0x0A8B, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0A8D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A8F, 0x0A91, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A93, 0x0AA8, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0AAA, 0x0AB0, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0AB2, 0x0AB3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0AB5, 0x0AB9, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0ABD, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0AE0, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B05, 0x0B0C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B0F, 0x0B10, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B13, 0x0B28, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B2A, 0x0B30, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B32, 0x0B33, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B36, 0x0B39, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0B3D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B5C, 0x0B5D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B5F, 0x0B61, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B85, 0x0B8A, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B8E, 0x0B90, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B92, 0x0B95, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B99, 0x0B9A, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0B9C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B9E, 0x0B9F, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0BA3, 0x0BA4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0BA8, 0x0BAA, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0BAE, 0x0BB5, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0BB7, 0x0BB9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C05, 0x0C0C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C0E, 0x0C10, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C12, 0x0C28, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C2A, 0x0C33, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C35, 0x0C39, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C60, 0x0C61, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C85, 0x0C8C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C8E, 0x0C90, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C92, 0x0CA8, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0CAA, 0x0CB3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0CB5, 0x0CB9, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0CDE, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0CE0, 0x0CE1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0D05, 0x0D0C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0D0E, 0x0D10, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0D12, 0x0D28, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0D2A, 0x0D39, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0D60, 0x0D61, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E01, 0x0E2E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E30, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E32, 0x0E33, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E40, 0x0E45, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E81, 0x0E82, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E84, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E87, 0x0E88, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E8A, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E8D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E94, 0x0E97, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E99, 0x0E9F, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EA1, 0x0EA3, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0EA5, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0EA7, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EAA, 0x0EAB, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EAD, 0x0EAE, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0EB0, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EB2, 0x0EB3, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0EBD, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EC0, 0x0EC4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0F40, 0x0F47, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0F49, 0x0F69, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x10A0, 0x10C5, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x10D0, 0x10F6, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1100, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1102, 0x1103, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1105, 0x1107, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1109, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x110B, 0x110C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x110E, 0x1112, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x113C, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x113E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1140, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x114C, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x114E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1150, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1154, 0x1155, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1159, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x115F, 0x1161, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1163, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1165, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1167, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1169, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x116D, 0x116E, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1172, 0x1173, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1175, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x119E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11A8, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11AB, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x11AE, 0x11AF, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x11B7, 0x11B8, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11BA, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x11BC, 0x11C2, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11EB, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11F0, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x11F9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1E00, 0x1E9B, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1EA0, 0x1EF9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F00, 0x1F15, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F18, 0x1F1D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F20, 0x1F45, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F48, 0x1F4D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F50, 0x1F57, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1F59, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1F5B, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1F5D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F5F, 0x1F7D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1F80, 0x1FB4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FB6, 0x1FBC, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x1FBE, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FC2, 0x1FC4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FC6, 0x1FCC, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FD0, 0x1FD3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FD6, 0x1FDB, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FE0, 0x1FEC, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FF2, 0x1FF4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x1FF6, 0x1FFC, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x2126, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x212A, 0x212B, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x212E, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x2180, 0x2182, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x3041, 0x3094, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x30A1, 0x30FA, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x3105, 0x312C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0xAC00, 0xD7A3, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x4E00, 0x9FA5, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x3007, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x3021, 0x3029, GENX_LETTER|GENX_NAMECHAR); + + /* + * NameChar ::= + * Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender + */ + rangeProp(p, 0x0030, 0x0039, GENX_NAMECHAR); + rangeProp(p, 0x0660, 0x0669, GENX_NAMECHAR); + rangeProp(p, 0x06F0, 0x06F9, GENX_NAMECHAR); + rangeProp(p, 0x0966, 0x096F, GENX_NAMECHAR); + rangeProp(p, 0x09E6, 0x09EF, GENX_NAMECHAR); + rangeProp(p, 0x0A66, 0x0A6F, GENX_NAMECHAR); + rangeProp(p, 0x0AE6, 0x0AEF, GENX_NAMECHAR); + rangeProp(p, 0x0B66, 0x0B6F, GENX_NAMECHAR); + rangeProp(p, 0x0BE7, 0x0BEF, GENX_NAMECHAR); + rangeProp(p, 0x0C66, 0x0C6F, GENX_NAMECHAR); + rangeProp(p, 0x0CE6, 0x0CEF, GENX_NAMECHAR); + rangeProp(p, 0x0D66, 0x0D6F, GENX_NAMECHAR); + rangeProp(p, 0x0E50, 0x0E59, GENX_NAMECHAR); + rangeProp(p, 0x0ED0, 0x0ED9, GENX_NAMECHAR); + rangeProp(p, 0x0F20, 0x0F29, GENX_NAMECHAR); + + charProp(p, '.', GENX_NAMECHAR); + charProp(p, '-', GENX_NAMECHAR); + charProp(p, '_', GENX_NAMECHAR); + + rangeProp(p, 0x0300, 0x0345, GENX_NAMECHAR); + rangeProp(p, 0x0360, 0x0361, GENX_NAMECHAR); + rangeProp(p, 0x0483, 0x0486, GENX_NAMECHAR); + rangeProp(p, 0x0591, 0x05A1, GENX_NAMECHAR); + rangeProp(p, 0x05A3, 0x05B9, GENX_NAMECHAR); + rangeProp(p, 0x05BB, 0x05BD, GENX_NAMECHAR); + charProp(p, 0x05BF, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x05C1, 0x05C2, GENX_NAMECHAR); + charProp(p, 0x05C4, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x064B, 0x0652, GENX_NAMECHAR); + charProp(p, 0x0670, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x06D6, 0x06DC, GENX_NAMECHAR); + rangeProp(p, 0x06DD, 0x06DF, GENX_NAMECHAR); + rangeProp(p, 0x06E0, 0x06E4, GENX_NAMECHAR); + rangeProp(p, 0x06E7, 0x06E8, GENX_NAMECHAR); + rangeProp(p, 0x06EA, 0x06ED, GENX_NAMECHAR); + rangeProp(p, 0x0901, 0x0903, GENX_NAMECHAR); + charProp(p, 0x093C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x093E, 0x094C, GENX_NAMECHAR); + charProp(p, 0x094D, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0951, 0x0954, GENX_NAMECHAR); + rangeProp(p, 0x0962, 0x0963, GENX_NAMECHAR); + rangeProp(p, 0x0981, 0x0983, GENX_NAMECHAR); + charProp(p, 0x09BC, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x09BE, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x09BF, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09C0, 0x09C4, GENX_NAMECHAR); + rangeProp(p, 0x09C7, 0x09C8, GENX_NAMECHAR); + rangeProp(p, 0x09CB, 0x09CD, GENX_NAMECHAR); + charProp(p, 0x09D7, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x09E2, 0x09E3, GENX_NAMECHAR); + charProp(p, 0x0A02, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0A3C, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0A3E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0A3F, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0A40, 0x0A42, GENX_NAMECHAR); + rangeProp(p, 0x0A47, 0x0A48, GENX_NAMECHAR); + rangeProp(p, 0x0A4B, 0x0A4D, GENX_NAMECHAR); + rangeProp(p, 0x0A70, 0x0A71, GENX_NAMECHAR); + rangeProp(p, 0x0A81, 0x0A83, GENX_NAMECHAR); + charProp(p, 0x0ABC, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0ABE, 0x0AC5, GENX_NAMECHAR); + rangeProp(p, 0x0AC7, 0x0AC9, GENX_NAMECHAR); + rangeProp(p, 0x0ACB, 0x0ACD, GENX_NAMECHAR); + rangeProp(p, 0x0B01, 0x0B03, GENX_NAMECHAR); + charProp(p, 0x0B3C, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0B3E, 0x0B43, GENX_NAMECHAR); + rangeProp(p, 0x0B47, 0x0B48, GENX_NAMECHAR); + rangeProp(p, 0x0B4B, 0x0B4D, GENX_NAMECHAR); + rangeProp(p, 0x0B56, 0x0B57, GENX_NAMECHAR); + rangeProp(p, 0x0B82, 0x0B83, GENX_NAMECHAR); + rangeProp(p, 0x0BBE, 0x0BC2, GENX_NAMECHAR); + rangeProp(p, 0x0BC6, 0x0BC8, GENX_NAMECHAR); + rangeProp(p, 0x0BCA, 0x0BCD, GENX_NAMECHAR); + charProp(p, 0x0BD7, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0C01, 0x0C03, GENX_NAMECHAR); + rangeProp(p, 0x0C3E, 0x0C44, GENX_NAMECHAR); + rangeProp(p, 0x0C46, 0x0C48, GENX_NAMECHAR); + rangeProp(p, 0x0C4A, 0x0C4D, GENX_NAMECHAR); + rangeProp(p, 0x0C55, 0x0C56, GENX_NAMECHAR); + rangeProp(p, 0x0C82, 0x0C83, GENX_NAMECHAR); + rangeProp(p, 0x0CBE, 0x0CC4, GENX_NAMECHAR); + rangeProp(p, 0x0CC6, 0x0CC8, GENX_NAMECHAR); + rangeProp(p, 0x0CCA, 0x0CCD, GENX_NAMECHAR); + rangeProp(p, 0x0CD5, 0x0CD6, GENX_NAMECHAR); + rangeProp(p, 0x0D02, 0x0D03, GENX_NAMECHAR); + rangeProp(p, 0x0D3E, 0x0D43, GENX_NAMECHAR); + rangeProp(p, 0x0D46, 0x0D48, GENX_NAMECHAR); + rangeProp(p, 0x0D4A, 0x0D4D, GENX_NAMECHAR); + charProp(p, 0x0D57, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E31, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0E34, 0x0E3A, GENX_NAMECHAR); + rangeProp(p, 0x0E47, 0x0E4E, GENX_NAMECHAR); + charProp(p, 0x0EB1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0EB4, 0x0EB9, GENX_NAMECHAR); + rangeProp(p, 0x0EBB, 0x0EBC, GENX_NAMECHAR); + rangeProp(p, 0x0EC8, 0x0ECD, GENX_NAMECHAR); + rangeProp(p, 0x0F18, 0x0F19, GENX_NAMECHAR); + charProp(p, 0x0F35, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0F37, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0F39, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0F3E, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0F3F, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0F71, 0x0F84, GENX_NAMECHAR); + rangeProp(p, 0x0F86, 0x0F8B, GENX_NAMECHAR); + rangeProp(p, 0x0F90, 0x0F95, GENX_NAMECHAR); + charProp(p, 0x0F97, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x0F99, 0x0FAD, GENX_NAMECHAR); + rangeProp(p, 0x0FB1, 0x0FB7, GENX_NAMECHAR); + charProp(p, 0x0FB9, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x20D0, 0x20DC, GENX_NAMECHAR); + charProp(p, 0x20E1, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x302A, 0x302F, GENX_NAMECHAR); + charProp(p, 0x3099, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x309A, GENX_LETTER|GENX_NAMECHAR); + + charProp(p, 0x00B7, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x02D0, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x02D1, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0387, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0640, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0E46, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x0EC6, GENX_LETTER|GENX_NAMECHAR); + charProp(p, 0x3005, GENX_LETTER|GENX_NAMECHAR); + rangeProp(p, 0x3031, 0x3035, GENX_NAMECHAR); + rangeProp(p, 0x309D, 0x309E, GENX_NAMECHAR); + rangeProp(p, 0x30FC, 0x30FE, GENX_NAMECHAR); +} diff --git a/libxsde/xsde/c/genx/genx.c b/libxsde/xsde/c/genx/genx.c new file mode 100644 index 0000000..1ce0527 --- /dev/null +++ b/libxsde/xsde/c/genx/genx.c @@ -0,0 +1,2118 @@ +/* + * Copyright (c) 2007-2009 Code Synthesis Tools CC. + * Copyright (c) 2004 by Tim Bray and Sun Microsystems. + * + * For copying permission, see the accompanying COPYING file. + */ + +#define GENX_VERSION "cs-1" + +#include +#include + +#include "genx.h" + +#define Boolean int +#define True 1 +#define False 0 +#define STRLEN_XMLNS_COLON 6 + + +/******************************* + * writer state + */ +typedef enum +{ + SEQUENCE_NO_DOC, + SEQUENCE_PRE_DOC, + SEQUENCE_POST_DOC, + SEQUENCE_START_TAG, + SEQUENCE_ATTRIBUTES, + SEQUENCE_START_ATTR, + SEQUENCE_CONTENT +} writerSequence; + +/******************************* + * generic pointer list + */ +typedef struct +{ + genxWriter writer; + int count; + int space; + void * * pointers; +} plist; + +/******************************* + * text collector, for attribute values + */ +typedef struct +{ + utf8 buf; + int used; + int space; +} collector; + +/******************************* + * Structs with opaquely-exposed handles + */ + +/* + * This one's tricky, to handle stacking namespaces + * 'declaration' is the current attribute which would be used to + * declare the currently-effective prefix + * 'defDeclaration' is a appropriate declaration when this is being + * used with the default prefix as passed to genxDeclareNamespace + * baroque is true if this namespace has been used with more than one + * prefix, or is the default namespace but has been unset + */ +struct genxNamespace_rec +{ + genxWriter writer; + utf8 name; + int declCount; + Boolean baroque; + genxAttribute declaration; + genxAttribute defaultDecl; +}; + +struct genxElement_rec +{ + genxWriter writer; + utf8 type; + genxNamespace ns; +}; + +typedef enum +{ + ATTR_NSDECL, + ATTR_NAKED, + ATTR_PREFIXED +} attrType; + +struct genxAttribute_rec +{ + genxWriter writer; + utf8 name; + genxNamespace ns; + collector value; + int provided; /* provided for current element? */ + attrType atype; +}; + +/******************************* + * genx's sandbox + */ +struct genxWriter_rec +{ + FILE * file; + genxSender * sender; + genxStatus status; + writerSequence sequence; + char xmlChars[0x10000]; + void * userData; + int nextPrefix; + utf8 empty; + Boolean defaultNsDeclared; + genxAttribute xmlnsEquals; + genxElement nowStarting; + genxAttribute nowStartingAttr; + plist namespaces; + plist elements; + plist attributes; + plist prefixes; + plist stack; + struct genxAttribute_rec arec; + char * etext[100]; + void * (* alloc)(void * userData, int bytes); + void (* dealloc)(void * userData, void * data); +}; + +/******************************* + * Forward declarations + */ +static genxAttribute declareAttribute(genxWriter w, genxNamespace ns, + constUtf8 name, constUtf8 valuestr, + genxStatus * statusP); +static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix); +static genxStatus unsetDefaultNamespace(genxWriter w); +static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr); +void genxSetCharProps(char * p); + +/******************************* + * End of declarations + */ + +/******************************* + * private memory utilities + */ +static void * allocate(genxWriter w, int bytes) +{ + if (w->alloc) + return (void *) (*w->alloc)(w->userData, bytes); + else + return (void *) malloc(bytes); +} + +static void deallocate(genxWriter w, void * data) +{ + if (w->dealloc) + (*w->dealloc)(w->userData, data); + else if (w->alloc == NULL) + free(data); +} + +static utf8 copy(genxWriter w, constUtf8 from) +{ + utf8 temp; + + if ((temp = (utf8) allocate(w, strlen((const char *) from) + 1)) == NULL) + return NULL; + strcpy((char *) temp, (const char *) from); + return temp; +} + +static genxStatus initCollector(genxWriter w, collector * c) +{ + c->space = 100; + if ((c->buf = (utf8) allocate(w, c->space)) == NULL) + return GENX_ALLOC_FAILED; + c->used = 0; + return GENX_SUCCESS; +} + +static genxStatus growCollector(genxWriter w, collector * c, int size) +{ + utf8 newSpace; + + c->space = size * 2; + if ((newSpace = (utf8) allocate(w, c->space)) == NULL) + return GENX_ALLOC_FAILED; + + strncpy((char *) newSpace, (const char *) c->buf, c->used); + newSpace[c->used] = 0; + deallocate(w, c->buf); + c->buf = newSpace; + return GENX_SUCCESS; +} + +static void startCollect(collector * c) +{ + c->used = 0; +} +static void endCollect(collector * c) +{ + c->buf[c->used] = 0; +} + +static genxStatus collectString(genxWriter w, collector * c, constUtf8 string) +{ + int sl = strlen((const char *) string); + + if (sl >= c->space) + if ((w->status = growCollector(w, c, sl)) != GENX_SUCCESS) + return GENX_ALLOC_FAILED; + + strcpy((char *) c->buf, (const char *) string); + return GENX_SUCCESS; +} + +#define collectPiece(w,c,d,size) {if (((c)->used+(size))>=(c)->space){if (((w)->status=growCollector(w,c,(c)->used+(size)))!=GENX_SUCCESS) return (w)->status;}strncpy((char *)(c)->buf+(c)->used,d,size);(c)->used+=size;} + +/******************************* + * private list utilities + */ +static genxStatus initPlist(genxWriter w, plist * pl) +{ + pl->writer = w; + pl->count = 0; + pl->space = 10; + pl->pointers = (void * *) allocate(w, pl->space * sizeof(void *)); + if (pl->pointers == NULL) + return GENX_ALLOC_FAILED; + + return GENX_SUCCESS; +} + +/* + * make room in a plist + */ +static Boolean checkExpand(plist * pl) +{ + void * * newlist; + int i; + + if (pl->count < pl->space) + return True; + + pl->space *= 2; + newlist = (void * *) allocate(pl->writer, pl->space * sizeof(void *)); + if (newlist == NULL) + return False; + for (i = 0; i < pl->count; i++) + newlist[i] = pl->pointers[i]; + deallocate(pl->writer, pl->pointers); + pl->pointers = newlist; + + return True; +} + +/* + * stick something on the end of a plist + */ +static genxStatus listAppend(plist * pl, void * pointer) +{ + if (!checkExpand(pl)) + return GENX_ALLOC_FAILED; + + pl->pointers[pl->count++] = pointer; + return GENX_SUCCESS; +} + +/* + * insert in place, shuffling up + */ +static genxStatus listInsert(plist * pl, void * pointer, int at) +{ + int i; + + if (!checkExpand(pl)) + return GENX_ALLOC_FAILED; + + for (i = pl->count; i > at; i--) + pl->pointers[i] = pl->pointers[i - 1]; + pl->count++; + + pl->pointers[at] = pointer; + return GENX_SUCCESS; +} + +/******************************* + * list lookups + */ + +static genxNamespace findNamespace(plist * pl, constUtf8 uri) +{ + int i; + genxNamespace * nn = (genxNamespace *) pl->pointers; + + for (i = 0; i < pl->count; i++) + if (strcmp((char *) uri, (const char *) nn[i]->name) == 0) + return nn[i]; + + return NULL; +} + +static genxElement findElement(plist * pl, constUtf8 xmlns, constUtf8 type) +{ + int i; + genxElement * ee = (genxElement *) pl->pointers; + + for (i = 0; i < pl->count; i++) + { + if (xmlns == NULL) + { + if (ee[i]->ns == NULL && strcmp((const char *) type, + (const char *) ee[i]->type) == 0) + return ee[i]; + } + else + { + if (ee[i]->ns != NULL && + strcmp((const char *) xmlns, (const char *) ee[i]->ns->name) == 0 && + strcmp((const char *) type, (const char *) ee[i]->type) == 0) + return ee[i]; + } + } + + return NULL; +} + +/* + * store & intern a prefix, after giving it the + * "xmlns:" prefix. Don't allow storing the same one twice unless 'force' + * is set. + */ +static utf8 storePrefix(genxWriter w, constUtf8 prefix, Boolean force) +{ + int high, low; + utf8 * pp = (utf8 *) w->prefixes.pointers; + unsigned char buf[1024]; + + if (prefix[0] == 0) + prefix = (utf8) "xmlns"; + else + { + sprintf((char *) buf, "xmlns:%s", prefix); + prefix = buf; + } + + high = w->prefixes.count; low = -1; + while (high - low > 1) + { + int probe = (high + low) / 2; + if (strcmp((const char *) prefix, (const char *) pp[probe]) < 0) + high = probe; + else + low = probe; + } + + /* already there? */ + if (low != -1 && strcmp((const char *) prefix, (const char *) pp[low]) == 0) + { + if (force) + return pp[low]; + + w->status = GENX_DUPLICATE_PREFIX; + return NULL; + } + + /* copy & insert */ + if ((prefix = copy(w, prefix)) == NULL) + { + w->status = GENX_ALLOC_FAILED; + return NULL; + } + + w->status = listInsert(&w->prefixes, (void *) prefix, high); + if (w->status != GENX_SUCCESS) + return NULL; + + return (utf8) prefix; +} + +/******************************* + * UTF8 bit-banging + */ + +/* + * Retrieve the character pointed at, and advance the pointer; return -1 on + * error + */ +int genxNextUnicodeChar(constUtf8 * sp) +{ + utf8 s = (utf8) *sp; + int c; + + if (*s == 0) + return -1; + + if (*s < 0x80) + c = *s++; + + /* all this encoding sanity-checking taken from section 3.10 of Unicode 4 */ + else if (*s < 0xc2) + goto malformed; + + /* 2-byte encodings, first byte c2 .. df */ + else if (*s < 0xe0) + { + c = (*s++ & 0x1f) << 6; + + /* + * for this common idiom, if ((c & 0xc0) != 0x80) is slightly faster + * on MacOS (PPC) + */ + if (*s < 0x80 || *s > 0xbf) + goto malformed; + + c |= *s++ & 0x3f; + } + + /* 3-byte encodings, first byte e0 .. ef */ + else if (*s < 0xf0) + { + int b0 = *s; + c = (*s++ & 0x0f) << 12; + + if ((b0 == 0xe0 && (*s < 0xa0 || *s > 0xbf)) || + (b0 < 0xed && (*s < 0x80 || *s > 0xbf)) || + (b0 == 0xed && (*s < 0x80 || *s > 0x9f)) || + (b0 > 0xed && (*s < 0x80 || *s > 0xbf))) + goto malformed; + + c |= (*s++ & 0x3f) << 6; + + if (*s < 0x80 || *s > 0xbf) + goto malformed; + + c |= *s++ & 0x3f; + } + + /* 4-byte encodings, first byte f0 .. f4 */ + else if (*s < 0xf5) + { + int b0 = *s; + c = (*s++ & 0x07) << 18; + + if ((b0 == 0xf0 && (*s < 0x90 || *s > 0xbf)) || + (b0 < 0xf4 && (*s < 0x80 || *s > 0xbf)) || + (b0 >= 0xf4 && (*s < 0x80 || *s > 0x8f))) + goto malformed; + + c |= (*s++ & 0x3f) << 12; + + if (*s < 0x80 || *s > 0xbf) + goto malformed; + + c |= (*s++ & 0x3f) << 6; + + if (*s < 0x80 || *s > 0xbf) + goto malformed; + + c |= *s++ & 0x3f; + } + else + goto malformed; + + *sp = s; + return c; + + /* + * this is needed by scrubText, which wants to get the pointer moved + * past the problem area. + */ +malformed: + if (*s) + ++s; + *sp = s; + return -1; +} + +static Boolean isXMLChar(genxWriter w, int c) +{ + if (c < 0) + return False; + else if (c < 0x10000) + return (int) w->xmlChars[c]; + else + return (c <= 0x10ffff); +} + +static Boolean isLetter(genxWriter w, int c) +{ + if (c < 0 || c > 0xffff) + return False; + else + return w->xmlChars[c] & GENX_LETTER; +} + +static Boolean isNameChar(genxWriter w, int c) +{ + if (c < 0 || c > 0xffff) + return False; + else + return w->xmlChars[c] & GENX_NAMECHAR; +} + +/******************************* + * Constructors, setters/getters + */ + +/* + * Construct a new genxWriter + */ +genxWriter genxNew(void * (* alloc)(void * userData, int bytes), + void (* dealloc)(void * userData, void * data), + void * userData) +{ + genxWriter w; + genxNamespace xml; + + if (alloc) + w = (genxWriter) (*alloc)(userData, sizeof(struct genxWriter_rec)); + else + w = (genxWriter) malloc(sizeof(struct genxWriter_rec)); + + if (w == NULL) + return NULL; + + w->status = GENX_SUCCESS; + w->alloc = alloc; + w->dealloc = dealloc; + w->userData = userData; + w->sequence = SEQUENCE_NO_DOC; + + if (initPlist(w, &w->namespaces) != GENX_SUCCESS || + initPlist(w, &w->elements) != GENX_SUCCESS || + initPlist(w, &w->attributes) != GENX_SUCCESS || + initPlist(w, &w->prefixes) != GENX_SUCCESS || + initPlist(w, &w->stack) != GENX_SUCCESS) + return NULL; + + if ((w->status = initCollector(w, &w->arec.value)) != GENX_SUCCESS) + return NULL; + + if ((w->empty = copy(w, (utf8) "")) == NULL) + { + w->status = GENX_ALLOC_FAILED; + return NULL; + } + + w->xmlnsEquals = declareAttribute(w, NULL, (utf8) "xmlns", NULL, &w->status); + if (w->xmlnsEquals == NULL || w->status != GENX_SUCCESS) + return NULL; + w->defaultNsDeclared = False; + + w->nextPrefix = 1; + + genxSetCharProps(w->xmlChars); + + w->etext[GENX_SUCCESS] = "Success"; + w->etext[GENX_BAD_UTF8] = "Bad UTF8"; + w->etext[GENX_NON_XML_CHARACTER] = "Non XML Character"; + w->etext[GENX_BAD_NAME] = "Bad NAME"; + w->etext[GENX_ALLOC_FAILED] = "Memory allocation failed"; + w->etext[GENX_BAD_NAMESPACE_NAME] = "Bad namespace name"; + w->etext[GENX_INTERNAL_ERROR] = "Internal error"; + w->etext[GENX_DUPLICATE_PREFIX] = "Duplicate prefix"; + w->etext[GENX_SEQUENCE_ERROR] = "Call out of sequence"; + w->etext[GENX_NO_START_TAG] = "No Start-tag for EndElement call"; + w->etext[GENX_IO_ERROR] = "I/O error"; + w->etext[GENX_MISSING_VALUE] = "Missing attribute value"; + w->etext[GENX_MALFORMED_COMMENT] = "Malformed comment body"; + w->etext[GENX_MALFORMED_PI] = "?> in PI"; + w->etext[GENX_XML_PI_TARGET] = "Target of PI matches [xX][mM][lL]"; + w->etext[GENX_DUPLICATE_ATTRIBUTE] = + "Same attribute specified more than once"; + w->etext[GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE] = + "Attribute cannot be in default namespace"; + w->etext[GENX_DUPLICATE_NAMESPACE] = + "Declared namespace twice with different prefixes on one element."; + w->etext[GENX_BAD_DEFAULT_DECLARATION] = + "Declared a default namespace on an element which is in no namespace"; + + /* the xml: namespace is pre-wired */ + xml = genxDeclareNamespace(w, (utf8) "http://www.w3.org/XML/1998/namespace", + (utf8) "xml", &w->status); + if (xml == NULL) + return NULL; + xml->declCount = 1; + xml->declaration = xml->defaultDecl; + + return w; +} + +genxStatus genxReset (genxWriter w) +{ + int i; + + /* Clean up the stack. */ + w->stack.count = 0; + + /* Reset namespace declaration counts. The first entry is the pre-wired + xml namespace. */ + ((genxNamespace) w->namespaces.pointers[0])->declCount = 1; + + for (i = 1; i < w->namespaces.count; i++) + { + ((genxNamespace) w->namespaces.pointers[i])->declCount = 0; + ((genxNamespace) w->namespaces.pointers[i])->baroque = False; + } + + w->status = GENX_SUCCESS; + w->sequence = SEQUENCE_NO_DOC; + + return w->status; +} + + +/* + * get/set userData + */ +void genxSetUserData(genxWriter w, void * userData) +{ + w->userData = userData; +} +void * genxGetUserData(genxWriter w) +{ + return w->userData; +} + +/* + * get/set allocator + */ +void genxSetAlloc(genxWriter w, void * (* alloc)(void * userData, int bytes)) +{ + w->alloc = alloc; +} +void genxSetDealloc(genxWriter w, + void (* dealloc)(void * userData, void * data)) +{ + w->dealloc = dealloc; +} +void * (* genxGetAlloc(genxWriter w))(void * userData, int bytes) +{ + return w->alloc; +} +void (* genxGetDealloc(genxWriter w))(void * userData, void * data) +{ + return w->dealloc; +} + +/* + * Clean up + */ +void genxDispose(genxWriter w) +{ + int i; + genxNamespace * nn = (genxNamespace *) w->namespaces.pointers; + genxElement * ee = (genxElement *) w->elements.pointers; + genxAttribute * aa = (genxAttribute *) w->attributes.pointers; + utf8 * pp = (utf8 *) w->prefixes.pointers; + + for (i = 0; i < w->namespaces.count; i++) + { + deallocate(w, nn[i]->name); + deallocate(w, nn[i]); + } + + for (i = 0; i < w->elements.count; i++) + { + deallocate(w, ee[i]->type); + deallocate(w, ee[i]); + } + + for (i = 0; i < w->attributes.count; i++) + { + deallocate(w, aa[i]->name); + deallocate(w, aa[i]->value.buf); + deallocate(w, aa[i]); + } + + for(i = 0; i < w->prefixes.count; i++) + deallocate(w, pp[i]); + + deallocate(w, w->namespaces.pointers); + deallocate(w, w->elements.pointers); + deallocate(w, w->attributes.pointers); + deallocate(w, w->prefixes.pointers); + deallocate(w, w->stack.pointers); + + deallocate(w, w->arec.value.buf); + + deallocate(w, w->empty); + + /* how Oscar dealt with Igli */ + deallocate(w, w); +} + +/******************************* + * External utility routines + */ + +/* + * scan a buffer and report problems with UTF-8 encoding or non-XML characters + */ +genxStatus genxCheckText(genxWriter w, constUtf8 s) +{ + while (*s) + { + int c = genxNextUnicodeChar(&s); + if (c == -1) + return GENX_BAD_UTF8; + + if (!isXMLChar(w, c)) + return GENX_NON_XML_CHARACTER; + } + return GENX_SUCCESS; +} + +/* + * Purify some text + */ +int genxScrubText(genxWriter w, constUtf8 in, utf8 out) +{ + int problems = 0; + constUtf8 last = in; + + while (*in) + { + int c = genxNextUnicodeChar(&in); + if (c == -1) + { + problems++; + last = in; + continue; + } + + if (!isXMLChar(w, c)) + { + problems++; + last = in; + continue; + } + + while (last < in) + *out++ = *last++; + } + *out = 0; + return problems; +} + +/* + * check one character + */ +int genxCharClass(genxWriter w, int c) +{ + int ret = 0; + + if (isXMLChar(w, c)) + ret |= GENX_XML_CHAR; + if (isNameChar(w, c)) + ret |= GENX_NAMECHAR; + if (isLetter(w, c)) + ret |= GENX_LETTER; + return ret; +} + +static genxStatus checkNCName(genxWriter w, constUtf8 name) +{ + int c; + + if (name == NULL || *name == 0) + return GENX_BAD_NAME; + + c = genxNextUnicodeChar(&name); + if (!isLetter(w, c) && c != ':' && c != '_') + return GENX_BAD_NAME; + + while (*name) + { + c = genxNextUnicodeChar(&name); + if (c == -1) + return GENX_BAD_UTF8; + if (!isNameChar(w, c)) + return GENX_BAD_NAME; + } + return GENX_SUCCESS; +} + +char * genxGetErrorMessage(genxWriter w, genxStatus status) +{ + return w->etext[status]; +} +char * genxLastErrorMessage(genxWriter w) +{ + return w->etext[w->status]; +} + +/******************************* + * Declarations: namespace/element/attribute + */ + +/* + * DeclareNamespace - by far the most complex routine in Genx + */ +genxNamespace genxDeclareNamespace(genxWriter w, constUtf8 uri, + constUtf8 defaultPref, + genxStatus * statusP) +{ + genxNamespace ns; + genxAttribute defaultDecl; + unsigned char newPrefix[100]; + + if (uri == NULL || uri[0] == 0) + { + w->status = GENX_BAD_NAMESPACE_NAME; + goto busted; + } + + if ((w->status = genxCheckText(w, uri)) != GENX_SUCCESS) + goto busted; + + /* if a prefix is provided, it has to be an NCname */ + if (defaultPref != NULL && defaultPref[0] != 0 && + (w->status = checkNCName(w, defaultPref)) != GENX_SUCCESS) + goto busted; + + /* previously declared? */ + if ((ns = findNamespace(&w->namespaces, uri))) + { + /* just a lookup, really */ + if ((defaultPref == NULL) || + (defaultPref[0] == 0 && ns->defaultDecl == w->xmlnsEquals) || + (strcmp((const char *) ns->defaultDecl->name + STRLEN_XMLNS_COLON, + (const char *) defaultPref) == 0)) + { + w->status = *statusP = GENX_SUCCESS; + return ns; + } + } + + /* wasn't already declared */ + else + { + + /* make a default prefix if none provided */ + if (defaultPref == NULL) + { + sprintf((char *) newPrefix, "g%d", w->nextPrefix++); + defaultPref = newPrefix; + } + + ns = (genxNamespace) allocate(w, sizeof(struct genxNamespace_rec)); + if (ns == NULL) + { + w->status = GENX_ALLOC_FAILED; + goto busted; + } + ns->writer = w; + ns->baroque = False; + + if ((ns->name = copy(w, uri)) == NULL) + { + w->status = GENX_ALLOC_FAILED; + goto busted; + } + + if ((w->status = listAppend(&w->namespaces, ns)) != GENX_SUCCESS) + goto busted; + ns->defaultDecl = ns->declaration = NULL; + ns->declCount = 0; + } + + if (defaultPref[0] == 0) + { + if (w->defaultNsDeclared) + { + w->status = GENX_DUPLICATE_PREFIX; + goto busted; + } + defaultDecl = w->xmlnsEquals; + w->defaultNsDeclared = True; + } + else + { + /* this catches dupes too */ + if ((defaultPref = storePrefix(w, defaultPref, False)) == NULL) + goto busted; + + defaultDecl = declareAttribute(w, NULL, defaultPref, ns->name, statusP); + if (defaultDecl == NULL || *statusP != GENX_SUCCESS) + { + w->status = *statusP; + return NULL; + } + } + + if (ns->defaultDecl != NULL && defaultDecl != ns->defaultDecl) + ns->baroque = True; + ns->defaultDecl = defaultDecl; + + *statusP = GENX_SUCCESS; + return ns; + +busted: + *statusP = w->status; + return NULL; +} + +/* + * get namespace prefix + */ +utf8 genxGetNamespacePrefix(genxNamespace ns) +{ + if (ns->declaration == NULL) + return NULL; + + if (ns->declaration == ns->writer->xmlnsEquals) + return ns->writer->empty; + + return ns->declaration->name + STRLEN_XMLNS_COLON; +} + +/* + * DeclareElement - see genx.h for details + */ +genxElement genxDeclareElement(genxWriter w, + genxNamespace ns, constUtf8 type, + genxStatus * statusP) +{ + genxElement old; + genxElement el; + + if ((w->status = checkNCName(w, type)) != GENX_SUCCESS) + { + *statusP = w->status; + return NULL; + } + + /* already declared? */ + old = findElement(&w->elements, (ns == NULL) ? NULL : ns->name, type); + if (old) + return old; + + if ((el = (genxElement) allocate(w, sizeof(struct genxElement_rec))) == NULL) + { + w->status = *statusP = GENX_ALLOC_FAILED; + return NULL; + } + + el->writer = w; + el->ns = ns; + if ((el->type = copy(w, type)) == NULL) + { + w->status = *statusP = GENX_ALLOC_FAILED; + return NULL; + } + + if ((w->status = listAppend(&w->elements, el)) != GENX_SUCCESS) + { + *statusP = w->status; + return NULL; + } + + *statusP = GENX_SUCCESS; + return el; +} + +/* + * C14n ordering for attributes: + * - first, namespace declarations by the prefix being declared + * - second, unprefixed attributes by attr name + * - third, prefixed attrs by ns uri then local part + */ +static int orderAttributes(genxAttribute a1, genxAttribute a2) +{ + if (a1->atype == a2->atype) + { + if (a1->atype == ATTR_PREFIXED && a1->ns != a2->ns) + return strcmp((const char *) a1->ns->name, (const char *) a2->ns->name); + else + return strcmp((const char *) a1->name, (const char *) a2->name); + } + + else if (a1->atype == ATTR_NSDECL) + return -1; + + else if (a1->atype == ATTR_NAKED) + { + if (a2->atype == ATTR_NSDECL) + return 1; + else + return -1; + } + + else + return 1; +} + +/* + * internal declare-attribute. This one allows colonized values for + * names, so that you can declare xmlns:-type attributes + */ +static genxAttribute declareAttribute(genxWriter w, genxNamespace ns, + constUtf8 name, constUtf8 valuestr, + genxStatus * statusP) +{ + int high, low; + genxAttribute * aa = (genxAttribute *) w->attributes.pointers; + genxAttribute a; + + w->arec.ns = ns; + w->arec.name = (utf8) name; + + if (ns) + w->arec.atype = ATTR_PREFIXED; + else if (strncmp((const char *) name, "xmlns", STRLEN_XMLNS_COLON - 1) == 0) + w->arec.atype = ATTR_NSDECL; + else + w->arec.atype = ATTR_NAKED; + + if (ns && (ns->defaultDecl == w->xmlnsEquals)) + { + w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE; + goto busted; + } + + /* attribute list has to be kept sorted per c14n rules */ + high = w->attributes.count; low = -1; + while (high - low > 1) + { + int probe = (high + low) / 2; + if (orderAttributes(&w->arec, aa[probe]) < 0) + high = probe; + else + low = probe; + } + + /* if it was already there */ + if (low != -1 && orderAttributes(&w->arec, aa[low]) == 0) + return aa[low]; + + /* not there, build it */ + a = (genxAttribute) allocate(w, sizeof(struct genxAttribute_rec)); + if (a == NULL) + { + w->status = GENX_ALLOC_FAILED; + goto busted; + } + + a->writer = w; + a->ns = ns; + a->provided = False; + a->atype = w->arec.atype; + + if ((a->name = copy(w, name)) == NULL) + { + w->status = GENX_ALLOC_FAILED; + goto busted; + } + + if ((w->status = initCollector(w, &a->value)) != GENX_SUCCESS) + goto busted; + + if (valuestr) + if ((w->status = collectString(w, &a->value, valuestr)) != GENX_SUCCESS) + goto busted; + + w->status = listInsert(&w->attributes, a, high); + if (w->status != GENX_SUCCESS) + goto busted; + + *statusP = GENX_SUCCESS; + return a; + +busted: + *statusP = w->status; + return NULL; +} + +/* + * genxDeclareAttribute - see genx.h for details + */ +genxAttribute genxDeclareAttribute(genxWriter w, + genxNamespace ns, constUtf8 name, + genxStatus * statusP) +{ + if ((w->status = checkNCName(w, name)) != GENX_SUCCESS) + { + *statusP = w->status; + return NULL; + } + + return declareAttribute(w, ns, name, NULL, statusP); +} + +/******************************* + * I/O + */ +static genxStatus sendx(genxWriter w, constUtf8 s) +{ + if (w->sender) + return (*w->sender->send)(w->userData, s); + else + { + if (fputs((const char *) s, w->file) == -1) + return GENX_IO_ERROR; + else + return GENX_SUCCESS; + } +} + +static genxStatus sendxBounded(genxWriter w, constUtf8 start, constUtf8 end) +{ + if (w->sender) + return (*w->sender->sendBounded)(w->userData, start, end); + else + /* Looks like on VxWorks fwrite returns a signed type which causes warnings. */ + if ((unsigned) fwrite(start, 1, end - start, w->file) != (unsigned) (end - start)) + return GENX_IO_ERROR; + else + return GENX_SUCCESS; +} + +#define SendCheck(w,s) if ((w->status=sendx(w,(utf8)s))!=GENX_SUCCESS) return w->status; + +/******************************* + * XML writing routines. The semantics of the externally-facing ones are + * written up in genx.h. Commentary here is implementation notes and + * for internal routines. + */ + +/* + * Start a document + */ +genxStatus genxStartDocFile(genxWriter w, FILE * file) +{ + if (w->sequence != SEQUENCE_NO_DOC) + return w->status = GENX_SEQUENCE_ERROR; + + w->sequence = SEQUENCE_PRE_DOC; + w->file = file; + w->sender = NULL; + return GENX_SUCCESS; +} + +genxStatus genxStartDocSender(genxWriter w, genxSender * sender) +{ + if (w->sequence != SEQUENCE_NO_DOC) + return w->status = GENX_SEQUENCE_ERROR; + + w->sequence = SEQUENCE_PRE_DOC; + w->file = NULL; + w->sender = sender; + return GENX_SUCCESS; +} + +/* + * Write out the attributes we've been gathering up for an element. We save + * them until we've gathered them all so they can be writen in canonical + * order. + * Also, we end the start-tag. + * The trick here is that we keep the attribute list properly sorted as + * we build it, then as each attribute is added, we fill in its value and + * mark the fact that it's been added, in the "provided" field. + */ +static genxStatus writeStartTag(genxWriter w) +{ + int i; + genxAttribute * aa = (genxAttribute *) w->attributes.pointers; + genxElement e = w->nowStarting; + + /* + * make sure the right namespace decls are in effect; + * if they are these might create an error, so ignore it + */ + if (e->ns) + addNamespace(e->ns, NULL); + else + unsetDefaultNamespace(w); + w->status = GENX_SUCCESS; + + SendCheck(w, "<"); + if (e->ns && (e->ns->declaration != w->xmlnsEquals)) + { + SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); + SendCheck(w, ":"); + } + SendCheck(w, e->type); + + for (i = 0; i < w->attributes.count; i++) + { + if (aa[i]->provided) + { + if (aa[i]->ns && aa[i]->ns->baroque && + aa[i]->ns->declaration == w->xmlnsEquals) + return w->status = GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE; + + SendCheck(w, " "); + + if (aa[i]->ns) + { + SendCheck(w, aa[i]->ns->declaration->name + STRLEN_XMLNS_COLON) + SendCheck(w, ":"); + } + SendCheck(w, aa[i]->name); + SendCheck(w, "=\""); + SendCheck(w, aa[i]->value.buf); + SendCheck(w, "\""); + } + } + SendCheck(w, ">"); + return GENX_SUCCESS; +} + +/* + * internal clear-er; no sequence checking + */ +static genxStatus unsetDefaultNamespace(genxWriter w) +{ + int i; + Boolean found = False; + + /* don't put it in if not needed */ + i = w->stack.count - 1; + while (found == False && i > 0) + { + while (w->stack.pointers[i] != NULL) + { + genxAttribute decl = (genxAttribute) w->stack.pointers[i--]; + genxNamespace ns = (genxNamespace) w->stack.pointers[i--]; + + /* if already unset */ + if (ns == NULL) + return w->status = GENX_SUCCESS; + + /* + * the default namespace was declared. This namespace now + * becomes baroque + */ + if (decl == w->xmlnsEquals) + { + ns->baroque = True; + found = True; + break; + } + } + i -= 2; + } + + if (!found) + return GENX_SUCCESS; + + /* + * push a signal on the stack + */ + if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS) + return w->status; + w->status = listAppend(&w->stack, w->xmlnsEquals); + if (w->status != GENX_SUCCESS) + return w->status; + + /* add the xmlns= attribute, it must be the first one */ + return addAttribute(w->xmlnsEquals, w->empty); +} + +/* + * clear the default namespace declaration + */ +genxStatus genxUnsetDefaultNamespace(genxWriter w) +{ + + /* can only do this while in start-tag mode */ + if (w->sequence != SEQUENCE_START_TAG) + return w->status = GENX_SEQUENCE_ERROR; + + return unsetDefaultNamespace(w); +} + +genxStatus genxStartElement(genxElement e) +{ + genxWriter w = e->writer; + int i; + + switch (w->sequence) + { + case SEQUENCE_NO_DOC: + case SEQUENCE_POST_DOC: + case SEQUENCE_START_ATTR: + return w->status = GENX_SEQUENCE_ERROR; + case SEQUENCE_START_TAG: + case SEQUENCE_ATTRIBUTES: + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + break; + case SEQUENCE_PRE_DOC: + case SEQUENCE_CONTENT: + break; + } + + w->sequence = SEQUENCE_START_TAG; + + /* clear provided attributes */ + for (i = 0; i < w->attributes.count; i++) + ((genxAttribute) w->attributes.pointers[i])->provided = 0; + + /* + * push the stack. We push a NULL after a pointer to this element + * because the stack will also contain pointers to the namespace + * attributes that got declared here, so we can keep track of what's + * in effect. I.e. a single stack entry consists logically of a pointer + * to an element object, a NULL, then zero or more pairs of pointers to + * namespace objects/declarations + */ + if ((w->status = listAppend(&w->stack, e)) != GENX_SUCCESS) + return w->status; + if ((w->status = listAppend(&w->stack, NULL)) != GENX_SUCCESS) + return w->status; + + w->nowStarting = e; + + return GENX_SUCCESS; +} + +/* + * internal namespace adder; no sequence checking + */ +static genxStatus addNamespace(genxNamespace ns, constUtf8 prefix) +{ + genxWriter w = ns->writer; + genxAttribute decl; + int i; + genxElement e; + + /* + * first, we'll find the declaring attribute + */ + if (prefix == NULL) + decl = ns->defaultDecl; + else + { + if (prefix[0] == 0) + decl = w->xmlnsEquals; + else + { + if ((prefix = storePrefix(w, prefix, True)) == NULL) + return w->status; + decl = declareAttribute(w, NULL, prefix, ns->name, &w->status); + if (decl == NULL || w->status != GENX_SUCCESS) + return w->status; + } + } + + if (decl != ns->defaultDecl) + ns->baroque = True; + + /* + * avoid doing anything if this namespace is already declared. If + * they've shown good taste we can do this cheaply + */ + if (!ns->baroque) + { + if (ns->declCount > 0) + return w->status = GENX_SUCCESS; + } + else + { + + /* + * First, we'll run all the way up the stack to see if there is + * another declaration for this namespace/prefix in scope, in which + * case it's a no-op; or, if there's another declaration for this + * prefix on another namespace, in which case we have to over-ride + */ + i = w->stack.count - 1; + while (i > 0) + { + while (w->stack.pointers[i] != NULL) + { + genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--]; + genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--]; + + if (ns == otherNs) + { + if (decl == otherDecl) + return w->status = GENX_SUCCESS; + else + { + i = 0; + break; + } + } + else + { + /* different namespace, same prefix? */ + if (decl == otherDecl) + { + i = 0; + break; + } + } + } + i -= 2; + } + } + + /* + * If this namespace is already declared on + * this element (with different prefix/decl) which is an error. + */ + i = w->stack.count - 1; + while (w->stack.pointers[i] != NULL) + { + genxNamespace otherNs; + i--; /* don't need declaration */ + otherNs = (genxNamespace) w->stack.pointers[i--]; + + if (ns == otherNs) + return w->status = GENX_DUPLICATE_NAMESPACE; + } + + /* move pointer from NULL to element */ + --i; + + /* + * It's also an error if this is a default-namespace declaration and the + * element is in no namespace. + */ + e = (genxElement) w->stack.pointers[i]; + if (e->ns == NULL && decl == w->xmlnsEquals) + return w->status = GENX_BAD_DEFAULT_DECLARATION; + + if ((w->status = listAppend(&w->stack, ns)) != GENX_SUCCESS) + return w->status; + if ((w->status = listAppend(&w->stack, decl)) != GENX_SUCCESS) + return w->status; + + ns->declaration = decl; + ns->declCount++; + return addAttribute(decl, ns->name); +} + +/* + * Add a namespace declaration + */ +genxStatus genxAddNamespace(genxNamespace ns, constUtf8 prefix) +{ + if (ns->writer->sequence != SEQUENCE_START_TAG) + return ns->writer->status = GENX_SEQUENCE_ERROR; + + return addNamespace(ns, prefix); +} + +/* + * Private attribute-adding code + * most of the work here is normalizing the value, which is the same + * as regular normalization except for " is replaced by """ + */ +static genxStatus collectAttributeValue (genxWriter w, collector* value, + constUtf8 start, constUtf8 end) +{ + /* If end is NULL then the length of the value is unknown and + the value is 0-terminated. */ + + utf8 last = (utf8) start; + + while (*start && (end == NULL || start < end)) + { + int c = genxNextUnicodeChar(&start); + + if (c == -1) + return w->status = GENX_BAD_UTF8; + + if (!isXMLChar(w, c)) + return w->status = GENX_NON_XML_CHARACTER; + + switch(c) + { + case 9: + collectPiece(w, value, " ", 5); + break; + case 0xa: + collectPiece(w, value, " ", 5); + break; + case 0xd: + collectPiece(w, value, " ", 5); + break; + case '"': + collectPiece(w, value, """, 6); + break; + case '<': + collectPiece(w, value, "<", 4); + break; + case '&': + collectPiece(w, value, "&", 5); + break; + /* + case '>': + collectPiece(w, value, ">", 4); + break; + */ + default: + collectPiece(w, value, (const char *) last, start - last); + break; + } + last = (utf8) start; + } + + return GENX_SUCCESS; +} + +static genxStatus addAttribute(genxAttribute a, constUtf8 valuestr) +{ + genxWriter w = a->writer; + + /* if valuestr not provided, this is an xmlns with a pre-cooked value */ + if (valuestr) + { + startCollect(&a->value); + + if (collectAttributeValue (w, &a->value, valuestr, NULL) != GENX_SUCCESS) + return w->status; + + endCollect(&a->value); + } + + /* now add the namespace attribute; might fail if it's been hand-declared */ + if (a->ns) + addNamespace(a->ns, NULL); + + if (valuestr && a->provided) + return w->status = GENX_DUPLICATE_ATTRIBUTE; + a->provided = 1; + + return GENX_SUCCESS; +} + +/* + * public attribute adder. + * The only difference is that it doesn't allow a NULL value + */ +genxStatus genxAddAttribute(genxAttribute a, constUtf8 valuestr) +{ + if (a->writer->sequence != SEQUENCE_START_TAG && + a->writer->sequence != SEQUENCE_ATTRIBUTES) + return a->writer->status = GENX_SEQUENCE_ERROR; + a->writer->sequence = SEQUENCE_ATTRIBUTES; + + if (valuestr == NULL) + return a->writer->status = GENX_MISSING_VALUE; + + return addAttribute(a, valuestr); +} + +genxStatus genxStartAttribute(genxAttribute a) +{ + genxWriter w = a->writer; + + if (w->sequence != SEQUENCE_START_TAG && + w->sequence != SEQUENCE_ATTRIBUTES) + return w->status = GENX_SEQUENCE_ERROR; + + w->sequence = SEQUENCE_START_ATTR; + w->nowStartingAttr = a; + + startCollect(&a->value); + + return GENX_SUCCESS; +} + +genxStatus genxEndAttribute(genxWriter w) +{ + genxAttribute a; + + if (w->sequence != SEQUENCE_START_ATTR) + return w->status = GENX_SEQUENCE_ERROR; + + a = w->nowStartingAttr; + w->sequence = SEQUENCE_ATTRIBUTES; + + endCollect(&a->value); + + /* now add the namespace attribute; might fail if it's been hand-declared */ + if (a->ns) + addNamespace(a->ns, NULL); + + if (a->provided) + return w->status = GENX_DUPLICATE_ATTRIBUTE; + + a->provided = 1; + + return GENX_SUCCESS; +} + +genxStatus genxEndElement(genxWriter w) +{ + genxElement e; + int i; + + switch (w->sequence) + { + case SEQUENCE_NO_DOC: + case SEQUENCE_PRE_DOC: + case SEQUENCE_POST_DOC: + case SEQUENCE_START_ATTR: + return w->status = GENX_SEQUENCE_ERROR; + case SEQUENCE_START_TAG: + case SEQUENCE_ATTRIBUTES: + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + break; + case SEQUENCE_CONTENT: + break; + } + + /* + * first peek into the stack to find the right namespace declaration + * (if any) so we can properly prefix the end-tag. Have to do this + * before unwinding the stack because that might reset some xmlns + * prefixes to the context in the parent element + */ + for (i = w->stack.count - 1; w->stack.pointers[i] != NULL; i -= 2) + ; + e = (genxElement) w->stack.pointers[--i]; + + SendCheck(w, "ns && e->ns->declaration != w->xmlnsEquals) + { + SendCheck(w, e->ns->declaration->name + STRLEN_XMLNS_COLON); + SendCheck(w, ":"); + } + SendCheck(w, e->type); + SendCheck(w, ">"); + + /* + * pop zero or more namespace declarations, then a null, then the + * start-element declaration off the stack + */ + w->stack.count--; + while (w->stack.pointers[w->stack.count] != NULL) + { + genxNamespace ns = (genxNamespace) w->stack.pointers[--w->stack.count]; + w->stack.count--; /* don't need decl */ + + /* if not a fake unset-default namespace */ + if (ns) + { + /* + * if they've stupidly jammed in their own namespace-prefix + * declarations, we have to go looking to see if there's another + * one in effect + */ + if (ns->baroque) + { + i = w->stack.count; + while (i > 0) + { + while (w->stack.pointers[i] != NULL) + { + genxAttribute otherDecl = (genxAttribute) w->stack.pointers[i--]; + genxNamespace otherNs = (genxNamespace) w->stack.pointers[i--]; + + if (otherNs == ns) + { + ns->declaration = otherDecl; + i = 0; + break; + } + } + + /* skip NULL & element */ + i -= 2; + } + } + ns->declCount--; + if (ns->declCount == 0) + ns->baroque = False; + } + } + + /* pop the NULL */ + --w->stack.count; + if (w->stack.count < 0) + return w->status = GENX_NO_START_TAG; + + if (w->stack.count == 0) + w->sequence = SEQUENCE_POST_DOC; + else + w->sequence = SEQUENCE_CONTENT; + + return GENX_SUCCESS; +} + +/* + * Internal character-adder. It tries to keep the number of sendx() + * calls down by looking at each character but only doing the output + * when it has to escape something; ordinary text gets saved up in + * chunks the start of which is indicated by *breaker. + * c is the character, next points to the UTF8 representing the next + * lastsP indirectly points to the UTF8 representing the + * character, breakerP* indirectly points to the last place genx + * changed the UTF8, e.g. by escaping a '<' + */ +static genxStatus addChar(genxWriter w, int c, constUtf8 next, + constUtf8 * lastsP, constUtf8 * breakerP) +{ + if (c == -1) + return GENX_BAD_UTF8; + + if (!isXMLChar(w, c)) + return GENX_NON_XML_CHARACTER; + + switch(c) + { + case 0xd: + if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) + return w->status; + *breakerP = next; + sendx(w, (utf8) " "); + break; + case '<': + if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) + return w->status; + *breakerP = next; + sendx(w, (utf8) "<"); + break; + case '&': + if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) + return w->status; + *breakerP = next; + sendx(w, (utf8) "&"); + break; + case '>': + if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS) + return w->status; + *breakerP = next; + sendx(w, (utf8) ">"); + break; + default: + break; + } + *lastsP = next; + return GENX_SUCCESS; +} + +genxStatus genxAddText(genxWriter w, constUtf8 start) +{ + constUtf8 lasts = start; + constUtf8 breaker = start; + + if (w->sequence == SEQUENCE_START_TAG || + w->sequence == SEQUENCE_ATTRIBUTES) + { + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + w->sequence = SEQUENCE_CONTENT; + } + + if (w->sequence == SEQUENCE_CONTENT) + { + while (*start) + { + int c = genxNextUnicodeChar(&start); + + w->status = addChar(w, c, start, &lasts, &breaker); + if (w->status != GENX_SUCCESS) + return w->status; + } + return sendxBounded(w, breaker, (utf8) start); + } + else if (w->sequence == SEQUENCE_START_ATTR) + { + return collectAttributeValue (w, &w->nowStartingAttr->value, start, NULL); + } + else + return w->status = GENX_SEQUENCE_ERROR; +} + +genxStatus genxAddBoundedText(genxWriter w, constUtf8 start, constUtf8 end) +{ + constUtf8 lasts = start; + constUtf8 breaker = start; + + if (w->sequence == SEQUENCE_START_TAG || + w->sequence == SEQUENCE_ATTRIBUTES) + { + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + w->sequence = SEQUENCE_CONTENT; + } + + if (w->sequence == SEQUENCE_CONTENT) + { + while (start < end) + { + int c = genxNextUnicodeChar(&start); + + w->status = addChar(w, c, (utf8) start, &lasts, &breaker); + if (w->status != GENX_SUCCESS) + return w->status; + } + return sendxBounded(w, breaker, (utf8) start); + } + else if (w->sequence == SEQUENCE_START_ATTR) + { + return collectAttributeValue (w, &w->nowStartingAttr->value, start, end); + } + else + return w->status = GENX_SEQUENCE_ERROR; +} + +genxStatus genxAddCountedText(genxWriter w, constUtf8 start, int byteCount) +{ + utf8 end = (utf8) (start + byteCount); + + return genxAddBoundedText(w, start, end); +} + +genxStatus genxAddCharacter(genxWriter w, int c) +{ + unsigned char cUTF8[10]; + utf8 lasts, breaker, next; + + if (w->sequence == SEQUENCE_START_TAG || + w->sequence == SEQUENCE_ATTRIBUTES) + { + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + w->sequence = SEQUENCE_CONTENT; + } + + if (!isXMLChar(w, c)) + return w->status = GENX_NON_XML_CHARACTER; + + if (w->sequence == SEQUENCE_START_ATTR) + { + int done = 1; + collector* value = &w->nowStartingAttr->value; + + switch(c) + { + case 9: + collectPiece(w, value, " ", 5); + break; + case 0xa: + collectPiece(w, value, " ", 5); + break; + case 0xd: + collectPiece(w, value, " ", 5); + break; + case '"': + collectPiece(w, value, """, 6); + break; + case '<': + collectPiece(w, value, "<", 4); + break; + case '&': + collectPiece(w, value, "&", 5); + break; + /* + case '>': + collectPiece(w, value, ">", 4); + break; + */ + default: + done = 0; + break; + } + + if (done) + return GENX_SUCCESS; + } + + /* make UTF8 representation of character */ + lasts = breaker = next = cUTF8; + + if (c < 0x80) + *next++ = c; + else if (c < 0x800) + { + *next++ = 0xc0 | (c >> 6); + *next++ = 0x80 | (c & 0x3f); + } + else if (c < 0x10000) + { + *next++ = 0xe0 | (c >> 12); + *next++ = 0x80 | ((c & 0xfc0) >> 6); + *next++ = 0x80 | (c & 0x3f); + } + else + { + *next++ = 0xf0 | (c >> 18); + *next++ = 0x80 | ((c & 0x3f000) >> 12); + *next++ = 0x80 | ((c & 0xfc0) >> 6); + *next++ = 0x80 | (c & 0x3f); + } + *next = 0; + + if (w->sequence == SEQUENCE_CONTENT) + { + w->status = + addChar(w, c, next, (constUtf8 *) &lasts, (constUtf8 *) &breaker); + + if (w->status != GENX_SUCCESS) + return w->status; + + return sendxBounded(w, breaker, next); + } + else if (w->sequence == SEQUENCE_START_ATTR) + { + collectPiece(w, &w->nowStartingAttr->value, + (const char *) cUTF8, next - cUTF8); + return GENX_SUCCESS; + } + else + return w->status = GENX_SEQUENCE_ERROR; +} + +genxStatus genxEndDocument(genxWriter w) +{ + if (w->sequence != SEQUENCE_POST_DOC) + return w->status = GENX_SEQUENCE_ERROR; + + if (w->file) + fflush(w->file); + else + if ((w->status = (*w->sender->flush)(w->userData)) != GENX_SUCCESS) + return w->status; + + w->sequence = SEQUENCE_NO_DOC; + return GENX_SUCCESS; +} + +genxStatus genxComment(genxWriter w, constUtf8 text) +{ + int i; + + if (w->sequence == SEQUENCE_NO_DOC || + w->sequence == SEQUENCE_START_ATTR) + return w->status = GENX_SEQUENCE_ERROR; + + if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS) + return w->status; + + /* no leading '-', no trailing '-', no '--' */ + if (text[0] == '-') + return w->status = GENX_MALFORMED_COMMENT; + for (i = 0; text[i]; i++) + if (text[i] == '-' && (text[i + 1] == '-' || text[i + 1] == 0)) + return w->status = GENX_MALFORMED_COMMENT; + + if (w->sequence == SEQUENCE_START_TAG || + w->sequence == SEQUENCE_ATTRIBUTES) + { + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + w->sequence = SEQUENCE_CONTENT; + } + + else if (w->sequence == SEQUENCE_POST_DOC) + if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) + return w->status; + + if ((w->status = sendx(w, (utf8) "")) != GENX_SUCCESS) + return w->status; + + if (w->sequence == SEQUENCE_PRE_DOC) + if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) + return w->status; + + return GENX_SUCCESS; +} + +genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text) +{ + int i; + + if (w->sequence == SEQUENCE_NO_DOC || + w->sequence == SEQUENCE_START_ATTR) + return w->status = GENX_SEQUENCE_ERROR; + + if ((w->status = genxCheckText(w, target)) != GENX_SUCCESS) + return w->status; + if ((w->status = checkNCName(w, target)) != GENX_SUCCESS) + return w->status; + if ((strlen((const char *) target) >= 3) && + (target[0] == 'x' || target[0] == 'X') && + (target[1] == 'm' || target[1] == 'M') && + (target[2] == 'l' || target[2] == 'L') && + (target[3] == 0)) + return w->status = GENX_XML_PI_TARGET; + + if ((w->status = genxCheckText(w, text)) != GENX_SUCCESS) + return w->status; + + /* no ?> within */ + for (i = 1; text[i]; i++) + if (text[i] == '>' && text[i - 1] == '?') + return w->status = GENX_MALFORMED_PI; + + if (w->sequence == SEQUENCE_START_TAG || + w->sequence == SEQUENCE_ATTRIBUTES) + { + if ((w->status = writeStartTag(w)) != GENX_SUCCESS) + return w->status; + w->sequence = SEQUENCE_CONTENT; + } + + else if (w->sequence == SEQUENCE_POST_DOC) + if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) + return w->status; + + if ((w->status = sendx(w, (utf8) "status; + if ((w->status = sendx(w, target)) != GENX_SUCCESS) + return w->status; + if (text[0]) + { + if ((w->status = sendx(w, (utf8) " ")) != GENX_SUCCESS) + return w->status; + if ((w->status = sendx(w, text)) != GENX_SUCCESS) + return w->status; + } + if ((w->status = sendx(w, (utf8) "?>")) != GENX_SUCCESS) + return w->status; + + if (w->sequence == SEQUENCE_PRE_DOC) + if ((w->status = sendx(w, (utf8) "\n")) != GENX_SUCCESS) + return w->status; + + return GENX_SUCCESS; +} + +/******************************* + * Literal versions of the writing routines + */ +genxStatus genxStartElementLiteral(genxWriter w, + constUtf8 xmlns, constUtf8 type) +{ + genxNamespace ns = NULL; + genxElement e; + + if (xmlns) + { + ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); + if (ns == NULL || w->status != GENX_SUCCESS) + return w->status; + } + e = genxDeclareElement(w, ns, type, &w->status); + if (e == NULL || w->status != GENX_SUCCESS) + return w->status; + + return genxStartElement(e); +} + +genxStatus genxAddAttributeLiteral(genxWriter w, constUtf8 xmlns, + constUtf8 name, constUtf8 value) +{ + genxNamespace ns = NULL; + genxAttribute a; + + if (xmlns) + { + ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); + if (ns == NULL && w->status != GENX_SUCCESS) + return w->status; + } + + a = genxDeclareAttribute(w, ns, name, &w->status); + if (a == NULL || w->status != GENX_SUCCESS) + return w->status; + + return genxAddAttribute(a, value); +} + +genxStatus genxStartAttributeLiteral(genxWriter w, + constUtf8 xmlns, constUtf8 name) +{ + genxNamespace ns = NULL; + genxAttribute a; + + if (xmlns) + { + ns = genxDeclareNamespace(w, xmlns, NULL, &w->status); + if (ns == NULL && w->status != GENX_SUCCESS) + return w->status; + } + + a = genxDeclareAttribute(w, ns, name, &w->status); + if (a == NULL || w->status != GENX_SUCCESS) + return w->status; + + return genxStartAttribute(a); +} + +genxStatus genxAddNamespaceLiteral(genxWriter w, + constUtf8 uri, constUtf8 prefix) +{ + genxNamespace ns = genxDeclareNamespace(w, uri, prefix, &w->status); + if (ns == NULL && w->status != GENX_SUCCESS) + return w->status; + + return genxAddNamespace(ns, NULL); +} + +/* + * return version + */ +char * genxGetVersion() +{ + return GENX_VERSION; +} + diff --git a/libxsde/xsde/c/genx/genx.h b/libxsde/xsde/c/genx/genx.h new file mode 100644 index 0000000..da9f9b7 --- /dev/null +++ b/libxsde/xsde/c/genx/genx.h @@ -0,0 +1,322 @@ + +/* + * genx - C-callable library for generating XML documents + */ + +/* + * Copyright (c) 2007-2009 Code Synthesis Tools CC. + * Copyright (c) 2004 by Tim Bray and Sun Microsystems. + * + * For copying permission, see the accompanying COPYING file. + */ + +#ifndef GENX_H +#define GENX_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Note on error handling: genx routines mostly return + * GENX_SUCCESS (guaranteed to be zero) in normal circumstances, one of + * these other GENX_ values on a memory allocation or I/O failure or if the + * call would result in non-well-formed output. + * You can associate an error message with one of these codes explicitly + * or with the most recent error using genxGetErrorMessage() and + * genxLastErrorMessage(); see below. + */ +typedef enum +{ + GENX_SUCCESS = 0, + GENX_BAD_UTF8, + GENX_NON_XML_CHARACTER, + GENX_BAD_NAME, + GENX_ALLOC_FAILED, + GENX_BAD_NAMESPACE_NAME, + GENX_INTERNAL_ERROR, + GENX_DUPLICATE_PREFIX, + GENX_SEQUENCE_ERROR, + GENX_NO_START_TAG, + GENX_IO_ERROR, + GENX_MISSING_VALUE, + GENX_MALFORMED_COMMENT, + GENX_XML_PI_TARGET, + GENX_MALFORMED_PI, + GENX_DUPLICATE_ATTRIBUTE, + GENX_ATTRIBUTE_IN_DEFAULT_NAMESPACE, + GENX_DUPLICATE_NAMESPACE, + GENX_BAD_DEFAULT_DECLARATION +} genxStatus; + +/* character types */ +#define GENX_XML_CHAR 1 +#define GENX_LETTER 2 +#define GENX_NAMECHAR 4 + +/* a UTF-8 string */ +typedef unsigned char * utf8; +typedef const unsigned char * constUtf8; + +/* + * genx's own types + */ +typedef struct genxWriter_rec * genxWriter; +typedef struct genxNamespace_rec * genxNamespace; +typedef struct genxElement_rec * genxElement; +typedef struct genxAttribute_rec * genxAttribute; + +/* + * Constructors, set/get + */ + +/* + * Create a new writer. For generating multiple XML documents, it's most + * efficient to re-use the same genx object. However, you can only write + * one document at a time with a writer. + * Returns NULL if it fails, which can only be due to an allocation failure. + */ +genxWriter genxNew(void * (*alloc)(void * userData, int bytes), + void (* dealloc)(void * userData, void * data), + void * userData); + +/* + * Reset the writer object back into usable state after an error or + * interruption. + */ +genxStatus genxReset (genxWriter w); + +/* + * Dispose of a writer, freeing all associated memory + */ +void genxDispose(genxWriter w); + +/* + * Set/get + */ + +/* + * The userdata pointer will be passed to memory-allocation + * and I/O callbacks. If not set, genx will pass NULL + */ +void genxSetUserData(genxWriter w, void * userData); +void * genxGetUserData(genxWriter w); + +/* + * User-provided memory allocator, if desired. For example, if you were + * in an Apache module, you could arrange for genx to use ap_palloc by + * making the pool accessible via the userData call. + * The "dealloc" is to be used to free memory allocated with "alloc". If + * alloc is provided but dealloc is NULL, genx will not attempt to free + * the memory; this would be appropriate in an Apache context. + * If "alloc" is not provided, genx routines use malloc() to allocate memory + */ +void genxSetAlloc(genxWriter w, + void * (* alloc)(void * userData, int bytes)); +void genxSetDealloc(genxWriter w, + void (* dealloc)(void * userData, void * data)); +void * (* genxGetAlloc(genxWriter w))(void * userData, int bytes); +void (* genxGetDealloc(genxWriter w))(void * userData, void * data); + +/* + * Get the prefix associated with a namespace + */ +utf8 genxGetNamespacePrefix(genxNamespace ns); + +/* + * Declaration functions + */ + +/* + * Declare a namespace. The provided prefix is the default but can be + * overridden by genxAddNamespace. If no default prefiix is provided, + * genx will generate one of the form g-%d. + * On error, returns NULL and signals via statusp + */ +genxNamespace genxDeclareNamespace(genxWriter w, + constUtf8 uri, constUtf8 prefix, + genxStatus * statusP); + +/* + * Declare an element + * If something failed, returns NULL and sets the status code via statusP + */ +genxElement genxDeclareElement(genxWriter w, + genxNamespace ns, constUtf8 type, + genxStatus * statusP); + +/* + * Declare an attribute + */ +genxAttribute genxDeclareAttribute(genxWriter w, + genxNamespace ns, + constUtf8 name, genxStatus * statusP); + +/* + * Writing XML + */ + +/* + * Start a new document. + */ +genxStatus genxStartDocFile(genxWriter w, FILE * file); + +/* + * Caller-provided I/O package. + * First form is for a null-terminated string. + * for second, if you have s="abcdef" and want to send "abc", you'd call + * sendBounded(userData, s, s + 3) + */ +typedef struct +{ + genxStatus (* send)(void * userData, constUtf8 s); + genxStatus (* sendBounded)(void * userData, constUtf8 start, constUtf8 end); + genxStatus (* flush)(void * userData); +} genxSender; + +genxStatus genxStartDocSender(genxWriter w, genxSender * sender); + +/* + * End a document. Calls "flush" + */ +genxStatus genxEndDocument(genxWriter w); + +/* + * Write a comment + */ +genxStatus genxComment(genxWriter w, constUtf8 text); + +/* + * Write a PI + */ +genxStatus genxPI(genxWriter w, constUtf8 target, constUtf8 text); + +/* + * Start an element + */ +genxStatus genxStartElementLiteral(genxWriter w, + constUtf8 xmlns, constUtf8 type); + +/* + * Start a predeclared element + * - element must have been declared + */ +genxStatus genxStartElement(genxElement e); + +/* + * Write an attribute + */ +genxStatus genxAddAttributeLiteral(genxWriter w, constUtf8 xmlns, + constUtf8 name, constUtf8 value); + +/* + * Start an attribute + */ +genxStatus genxStartAttributeLiteral(genxWriter w, + constUtf8 xmlns, constUtf8 name); + +/* + * Write a predeclared attribute + */ +genxStatus genxAddAttribute(genxAttribute a, constUtf8 value); + +/* + * Start a predeclared attribute + */ +genxStatus genxStartAttribute(genxAttribute a); + +/* + * End an attribute + */ +genxStatus genxEndAttribute(genxWriter w); + +/* + * add a namespace declaration + */ +genxStatus genxAddNamespaceLiteral(genxWriter w, + constUtf8 uri, constUtf8 prefix); + +/* + * add a predefined namespace declaration + */ +genxStatus genxAddNamespace(genxNamespace ns, constUtf8 prefix); + +/* + * Clear default namespace declaration + */ +genxStatus genxUnsetDefaultNamespace(genxWriter w); + +/* + * Write an end tag + */ +genxStatus genxEndElement(genxWriter w); + +/* + * Write some text + * You can't write any text outside the root element, except with + * genxComment and genxPI + */ +genxStatus genxAddText(genxWriter w, constUtf8 start); +genxStatus genxAddCountedText(genxWriter w, constUtf8 start, int byteCount); +genxStatus genxAddBoundedText(genxWriter w, constUtf8 start, constUtf8 end); + +/* + * Write one character. The integer value is the Unicode character + * value, as usually expressed in U+XXXX notation. + */ +genxStatus genxAddCharacter(genxWriter w, int c); + +/* + * Utility routines + */ + +/* + * Return the Unicode character encoded by the UTF-8 pointed-to by the + * argument, and advance the argument past the encoding of the character. + * Returns -1 if the UTF-8 is malformed, in which case advances the + * argument to point at the first byte past the point past the malformed + * ones. + */ +int genxNextUnicodeChar(constUtf8 * sp); + +/* + * Scan a buffer allegedly full of UTF-8 encoded XML characters; return + * one of GENX_SUCCESS, GENX_BAD_UTF8, or GENX_NON_XML_CHARACTER + */ +genxStatus genxCheckText(genxWriter w, constUtf8 s); + +/* + * return character status, the OR of GENX_XML_CHAR, + * GENX_LETTER, and GENX_NAMECHAR + */ +int genxCharClass(genxWriter w, int c); + +/* + * Silently wipe any non-XML characters out of a chunk of text. + * If you call this on a string before you pass it addText or + * addAttribute, you will never get an error from genx unless + * (a) there's a bug in your software, e.g. a malformed element name, or + * (b) there's a memory allocation or I/O error + * The output can never be longer than the input. + * Returns true if any changes were made. + */ +int genxScrubText(genxWriter w, constUtf8 in, utf8 out); + +/* + * return error messages + */ +char * genxGetErrorMessage(genxWriter w, genxStatus status); +char * genxLastErrorMessage(genxWriter w); + +/* + * return version + */ +char * genxGetVersion(); + +#ifdef __cplusplus +} +#endif + +#endif /* GENX_H */ diff --git a/libxsde/xsde/cxx/buffer.cxx b/libxsde/xsde/cxx/buffer.cxx new file mode 100644 index 0000000..17bcd9e --- /dev/null +++ b/libxsde/xsde/cxx/buffer.cxx @@ -0,0 +1,145 @@ +// file : xsde/cxx/buffer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy + +#include + +namespace xsde +{ + namespace cxx + { + // c-tors + // + +#ifdef XSDE_EXCEPTIONS + buffer:: + buffer (size_t size) + : data_ (0), size_ (0), capacity_ (0) + { + capacity (size); + size_ = size; + } + + buffer:: + buffer (size_t size, size_t cap) + : data_ (0), size_ (0), capacity_ (0) + { + if (size > cap) + throw bounds (); + + capacity (cap); + size_ = size; + } + + buffer:: + buffer (const void* data, size_t size) + : data_ (0), size_ (0), capacity_ (0) + { + capacity (size); + size_ = size; + + if (size_) + memcpy (data_, data, size_); + } + + buffer:: + buffer (const void* data, size_t size, size_t cap) + : data_ (0), size_ (0), capacity_ (0) + { + if (size > cap) + throw bounds (); + + capacity (cap); + size_ = size; + + if (size_) + memcpy (data_, data, size_); + } + + buffer:: + buffer (void* data, size_t size, size_t cap, ownership_value) + : data_ (0), size_ (0), capacity_ (0) + { + if (size > cap) + throw bounds (); + + data_ = reinterpret_cast (data); + size_ = size; + capacity_ = cap; + } +#endif // XSDE_EXCEPTIONS + + // + // + +#ifdef XSDE_EXCEPTIONS + bool buffer:: + capacity (size_t capacity, bool copy) + { + if (size_ > capacity) + throw bounds (); + + if (capacity <= capacity_) + { + return false; // Do nothing if shrinking is requested. + } + else + { + char* data = reinterpret_cast (operator new (capacity)); + + if (copy && size_ > 0) + memcpy (data, data_, size_); + + if (data_) + operator delete (data_); + + data_ = data; + capacity_ = capacity; + + return true; + } + } +#else + buffer::error buffer:: + capacity (size_t capacity, bool copy, bool* moved) + { + if (size_ > capacity) + return error_bounds; + + if (capacity <= capacity_) + { + // Do nothing if shrinking is requested. + // + if (moved) + *moved = false; + } + else + { + char* data = reinterpret_cast (operator new (capacity)); + + if (data != 0) + { + if (copy && size_ > 0) + memcpy (data, data_, size_); + + if (data_) + operator delete (data_); + + data_ = data; + capacity_ = capacity; + + if (moved) + *moved = true; + } + else + return error_no_memory; + } + + return error_none; + } +#endif + } +} diff --git a/libxsde/xsde/cxx/buffer.hxx b/libxsde/xsde/cxx/buffer.hxx new file mode 100644 index 0000000..e219de3 --- /dev/null +++ b/libxsde/xsde/cxx/buffer.hxx @@ -0,0 +1,149 @@ +// file : xsde/cxx/buffer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_BUFFER_HXX +#define XSDE_CXX_BUFFER_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + // Binary buffer. Used for the base64Binary and hexBinary types. + // + class buffer + { + public: +#ifdef XSDE_EXCEPTIONS + class bounds {}; // Out of bounds exception. +#else + enum error + { + error_none, + error_bounds, + error_no_memory + }; +#endif + + public: + ~buffer (); + buffer (); + +#ifdef XSDE_EXCEPTIONS + explicit + buffer (size_t size); + buffer (size_t size, size_t capacity); + buffer (const void* data, size_t size); + buffer (const void* data, size_t size, size_t capacity); + + enum ownership_value { assume_ownership }; + + // This constructor assumes ownership of the memory passed. + // + buffer (void* data, size_t size, size_t capacity, ownership_value); +#endif + + private: + buffer (const buffer&); + + buffer& + operator= (const buffer&); + + public: +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + attach (void* data, size_t size, size_t capacity); + + void* + detach (); + + void + swap (buffer&); + + public: + size_t + capacity () const; + + // Returns true if the underlying buffer has moved. + // +#ifdef XSDE_EXCEPTIONS + bool + capacity (size_t); +#else + error + capacity (size_t); + + error + capacity (size_t, bool& moved); +#endif + + public: + size_t + size () const; + + // Returns true if the underlying buffer has moved. + // +#ifdef XSDE_EXCEPTIONS + bool + size (size_t); +#else + error + size (size_t); + + error + size (size_t, bool& moved); +#endif + + public: + const char* + data () const; + + char* + data (); + + const char* + begin () const; + + char* + begin (); + + const char* + end () const; + + char* + end (); + + private: +#ifdef XSDE_EXCEPTIONS + bool + capacity (size_t capacity, bool copy); +#else + error + capacity (size_t capacity, bool copy, bool* moved); +#endif + + private: + char* data_; + size_t size_; + size_t capacity_; + }; + + bool + operator== (const buffer&, const buffer&); + + bool + operator!= (const buffer&, const buffer&); + } +} + +#include + +#endif // XSDE_CXX_BUFFER_HXX diff --git a/libxsde/xsde/cxx/buffer.ixx b/libxsde/xsde/cxx/buffer.ixx new file mode 100644 index 0000000..78f3633 --- /dev/null +++ b/libxsde/xsde/cxx/buffer.ixx @@ -0,0 +1,213 @@ +// file : xsde/cxx/buffer.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcmp + +namespace xsde +{ + namespace cxx + { + // c-tors & d-tor + // + inline buffer:: + ~buffer () + { + if (data_) + operator delete (data_); + } + + inline buffer:: + buffer () + : data_ (0), size_ (0), capacity_ (0) + { + } + +#ifndef XSDE_EXCEPTIONS + inline buffer::error buffer:: +#else + inline void buffer:: +#endif + attach (void* data, size_t size, size_t cap) + { + if (size > cap) + { +#ifdef XSDE_EXCEPTIONS + throw bounds (); +#else + return error_bounds; +#endif + } + + if (data_) + operator delete (data_); + + data_ = reinterpret_cast (data); + size_ = size; + capacity_ = cap; + +#ifndef XSDE_EXCEPTIONS + return error_none; +#endif + } + + inline void* buffer:: + detach () + { + void* r = data_; + + data_ = 0; + size_ = 0; + capacity_ = 0; + + return r; + } + + inline void buffer:: + swap (buffer& other) + { + char* d = data_; + size_t s = size_; + size_t c = capacity_; + + data_ = other.data_; + size_ = other.size_; + capacity_ = other.capacity_; + + other.data_ = d; + other.size_ = s; + other.capacity_ = c; + } + + // + // + inline size_t buffer:: + capacity () const + { + return capacity_; + } + +#ifdef XSDE_EXCEPTIONS + inline bool buffer:: + capacity (size_t cap) + { + return capacity (cap, true); + } +#else + inline buffer::error buffer:: + capacity (size_t cap) + { + return capacity (cap, true, 0); + } + + inline buffer::error buffer:: + capacity (size_t cap, bool& moved) + { + return capacity (cap, true, &moved); + } +#endif + + inline size_t buffer:: + size () const + { + return size_; + } + +#ifdef XSDE_EXCEPTIONS + inline bool buffer:: + size (size_t size) + { + bool r = false; + + if (size > capacity_) + r = capacity (size); + + size_ = size; + + return r; + } +#else + inline buffer::error buffer:: + size (size_t size) + { + error r = error_none; + + if (size > capacity_) + r = capacity (size); + + if (r == error_none) + size_ = size; + + return r; + } + + inline buffer::error buffer:: + size (size_t size, bool& moved) + { + error r = error_none; + moved = false; + + if (size > capacity_) + r = capacity (size, moved); + + if (r == error_none) + size_ = size; + + return r; + } +#endif + + // + // + inline const char* buffer:: + data () const + { + return data_; + } + + inline char* buffer:: + data () + { + return data_; + } + + inline const char* buffer:: + begin () const + { + return data_; + } + + inline char* buffer:: + begin () + { + return data_; + } + + inline const char* buffer:: + end () const + { + return data_ + size_; + } + + inline char* buffer:: + end () + { + return data_ + size_; + } + + inline bool + operator== (const buffer& x, const buffer& y) + { + return x.size () == y.size () && + memcmp (x.data (), y.data (), x.size ()) == 0; + } + + inline bool + operator!= (const buffer& x, const buffer& y) + { + return !(x == y); + } + } +} + diff --git a/libxsde/xsde/cxx/compilers/vc-6/post.hxx b/libxsde/xsde/cxx/compilers/vc-6/post.hxx new file mode 100644 index 0000000..a889512 --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-6/post.hxx @@ -0,0 +1,6 @@ +// file : xsde/cxx/compilers/vc-6/post.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#pragma warning (pop) diff --git a/libxsde/xsde/cxx/compilers/vc-6/pre.hxx b/libxsde/xsde/cxx/compilers/vc-6/pre.hxx new file mode 100644 index 0000000..fc9d78e --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-6/pre.hxx @@ -0,0 +1,33 @@ +// file : xsde/cxx/compilers/vc-6/pre.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +// These warnings had to be disabled "for good". +// +#pragma warning (disable:4505) // unreferenced local function has been removed + +#ifdef XSDE_REUSE_STYLE_MIXIN +#pragma warning (disable:4250) // inherits via dominance +#endif + + +// Push warning state. +// +#pragma warning (push, 3) + + +// Disabled warnings. +// +#pragma warning (disable:4355) // passing 'this' to a member +#pragma warning (disable:4584) // is already a base-class +#pragma warning (disable:4800) // forcing value to bool +#pragma warning (disable:4275) // non dll-interface base +#pragma warning (disable:4251) // base needs to have dll-interface + + +// Elevated warnings. +// +#pragma warning (2:4239) // standard doesn't allow this conversion diff --git a/libxsde/xsde/cxx/compilers/vc-7/post.hxx b/libxsde/xsde/cxx/compilers/vc-7/post.hxx new file mode 100644 index 0000000..867ae06 --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-7/post.hxx @@ -0,0 +1,6 @@ +// file : xsde/cxx/compilers/vc-7/post.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#pragma warning (pop) diff --git a/libxsde/xsde/cxx/compilers/vc-7/pre.hxx b/libxsde/xsde/cxx/compilers/vc-7/pre.hxx new file mode 100644 index 0000000..d3678cf --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-7/pre.hxx @@ -0,0 +1,37 @@ +// file : xsde/cxx/compilers/vc-7/pre.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#if (_MSC_VER < 1310) +# error Microsoft Visual C++ 7.0 (.NET 2002) is not supported. +#endif + +#include + +// These warnings had to be disabled "for good". +// +#pragma warning (disable:4505) // unreferenced local function has been + +#ifdef XSDE_REUSE_STYLE_MIXIN +#pragma warning (disable:4250) // inherits via dominance +#endif + + +// Push warning state. +// +#pragma warning (push, 3) + + +// Disabled warnings. +// +#pragma warning (disable:4355) // passing 'this' to a member +#pragma warning (disable:4584) // is already a base-class +#pragma warning (disable:4800) // forcing value to bool +#pragma warning (disable:4275) // non dll-interface base +#pragma warning (disable:4251) // base needs to have dll-interface + + +// Elevated warnings. +// +#pragma warning (2:4239) // standard doesn't allow this conversion diff --git a/libxsde/xsde/cxx/compilers/vc-8/post.hxx b/libxsde/xsde/cxx/compilers/vc-8/post.hxx new file mode 100644 index 0000000..eb93d5f --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-8/post.hxx @@ -0,0 +1,6 @@ +// file : xsde/cxx/compilers/vc-8/post.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#pragma warning (pop) diff --git a/libxsde/xsde/cxx/compilers/vc-8/pre.hxx b/libxsde/xsde/cxx/compilers/vc-8/pre.hxx new file mode 100644 index 0000000..d9c4baf --- /dev/null +++ b/libxsde/xsde/cxx/compilers/vc-8/pre.hxx @@ -0,0 +1,30 @@ +// file : xsde/cxx/compilers/vc-8/pre.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +// These warnings had to be disabled "for good". +// +#ifdef XSDE_REUSE_STYLE_MIXIN +#pragma warning (disable:4250) // inherits via dominance +#endif + + +// Push warning state. +// +#pragma warning (push, 3) + + +// Disabled warnings. +// +#pragma warning (disable:4355) // passing 'this' to a member +#pragma warning (disable:4800) // forcing value to bool +#pragma warning (disable:4275) // non dll-interface base +#pragma warning (disable:4251) // base needs to have dll-interface + + +// Elevated warnings. +// +#pragma warning (2:4239) // standard doesn't allow this conversion diff --git a/libxsde/xsde/cxx/config.hxx b/libxsde/xsde/cxx/config.hxx new file mode 100644 index 0000000..359aaf2 --- /dev/null +++ b/libxsde/xsde/cxx/config.hxx @@ -0,0 +1,27 @@ +// file : xsde/cxx/config.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_CONFIG_HXX +#define XSDE_CXX_CONFIG_HXX + +#include + +// Macro to suppress unused variable warning. +// +#define XSDE_UNUSED(x) (void)x + +// Using strtof appears to be highly non-portable. +// +#undef XSDE_STRTOF + +// The snprintf function on Win32 and WinCE is called _snprintf. +// +#ifdef XSDE_SNPRINTF +# if defined(XSDE_PLATFORM_WIN32) || defined(XSDE_PLATFORM_WINCE) +# define snprintf _snprintf +# endif +#endif + +#endif // XSDE_CXX_CONFIG_HXX diff --git a/libxsde/xsde/cxx/date-time.hxx b/libxsde/xsde/cxx/date-time.hxx new file mode 100644 index 0000000..2ec701d --- /dev/null +++ b/libxsde/xsde/cxx/date-time.hxx @@ -0,0 +1,415 @@ +// file : xsde/cxx/date-time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_DATE_TIME_HXX +#define XSDE_CXX_DATE_TIME_HXX + +namespace xsde +{ + namespace cxx + { + // + // + class time_zone + { + public: + time_zone (); + time_zone (short hours, short minutes); + + // Returns true if time zone is specified. + // + bool + zone_present () const; + + // Resets the time zone to the 'not specified' state. + // + void + zone_reset (); + + short + zone_hours () const; + + void + zone_hours (short); + + short + zone_minutes () const; + + void + zone_minutes (short); + + private: + bool present_; + short hours_; + short minutes_; + }; + + bool + operator== (const time_zone&, const time_zone&); + + bool + operator!= (const time_zone&, const time_zone&); + + // + // + class gday: public time_zone + { + public: + gday (); + explicit + gday (unsigned short day); + gday (unsigned short day, short zone_hours, short zone_minutes); + + unsigned short + day () const; + + void + day (unsigned short); + + private: + unsigned short day_; + }; + + bool + operator== (const gday&, const gday&); + + bool + operator!= (const gday&, const gday&); + + // + // + class gmonth: public time_zone + { + public: + gmonth (); + explicit + gmonth (unsigned short month); + gmonth (unsigned short month, short zone_hours, short zone_minutes); + + unsigned short + month () const; + + void + month (unsigned short); + + private: + unsigned short month_; + }; + + bool + operator== (const gmonth&, const gmonth&); + + bool + operator!= (const gmonth&, const gmonth&); + + // + // + class gyear: public time_zone + { + public: + gyear (); + explicit + gyear (int year); + gyear (int year, short zone_hours, short zone_minutes); + + int + year () const; + + void + year (int); + + private: + int year_; + }; + + bool + operator== (const gyear&, const gyear&); + + bool + operator!= (const gyear&, const gyear&); + + // + // + class gmonth_day: public time_zone + { + public: + gmonth_day (); + gmonth_day (unsigned short month, unsigned short day); + gmonth_day (unsigned short month, unsigned short day, + short zone_hours, short zone_minutes); + + unsigned short + month () const; + + void + month (unsigned short); + + unsigned short + day () const; + + void + day (unsigned short); + + private: + unsigned short month_; + unsigned short day_; + }; + + bool + operator== (const gmonth_day&, const gmonth_day&); + + bool + operator!= (const gmonth_day&, const gmonth_day&); + + // + // + class gyear_month: public time_zone + { + public: + gyear_month (); + gyear_month (int year, unsigned short month); + gyear_month (int year, unsigned short month, + short zone_hours, short zone_minutes); + + int + year () const; + + void + year (int); + + unsigned short + month () const; + + void + month (unsigned short); + + private: + int year_; + unsigned short month_; + }; + + bool + operator== (const gyear_month&, const gyear_month&); + + bool + operator!= (const gyear_month&, const gyear_month&); + + // + // + class date: public time_zone + { + public: + date (); + date (int year, unsigned short month, unsigned short day); + date (int year, unsigned short month, unsigned short day, + short zone_hours, short zone_minutes); + + int + year () const; + + void + year (int); + + unsigned short + month () const; + + void + month (unsigned short); + + unsigned short + day () const; + + void + day (unsigned short); + + private: + int year_; + unsigned short month_; + unsigned short day_; + }; + + bool + operator== (const date&, const date&); + + bool + operator!= (const date&, const date&); + + // + // + class time: public time_zone + { + public: + time (); + time (unsigned short hours, unsigned short minutes, double seconds); + time (unsigned short hours, unsigned short minutes, double seconds, + short zone_hours, short zone_minutes); + + unsigned short + hours () const; + + void + hours (unsigned short); + + unsigned short + minutes () const; + + void + minutes (unsigned short); + + double + seconds () const; + + void + seconds (double); + + private: + unsigned short hours_; + unsigned short minutes_; + double seconds_; + }; + + bool + operator== (const time&, const time&); + + bool + operator!= (const time&, const time&); + + // + // + class date_time: public time_zone + { + public: + date_time (); + date_time (int year, unsigned short month, unsigned short day, + unsigned short hours, unsigned short minutes, double seconds); + + date_time (int year, unsigned short month, unsigned short day, + unsigned short hours, unsigned short minutes, double seconds, + short zone_hours, short zone_minutes); + + int + year () const; + + void + year (int); + + unsigned short + month () const; + + void + month (unsigned short); + + unsigned short + day () const; + + void + day (unsigned short); + + unsigned short + hours () const; + + void + hours (unsigned short); + + unsigned short + minutes () const; + + void + minutes (unsigned short); + + double + seconds () const; + + void + seconds (double); + + private: + int year_; + unsigned short month_; + unsigned short day_; + unsigned short hours_; + unsigned short minutes_; + double seconds_; + }; + + bool + operator== (const date_time&, const date_time&); + + bool + operator!= (const date_time&, const date_time&); + + // + // + class duration + { + public: + duration (); + duration (bool negative, + unsigned int years, unsigned int months, unsigned int days, + unsigned int hours, unsigned int minutes, double seconds); + + bool + negative () const; + + void + negative (bool); + + unsigned int + years () const; + + void + years (unsigned int); + + unsigned int + months () const; + + void + months (unsigned int); + + unsigned int + days () const; + + void + days (unsigned int); + + unsigned int + hours () const; + + void + hours (unsigned int); + + unsigned int + minutes () const; + + void + minutes (unsigned int); + + double + seconds () const; + + void + seconds (double); + + private: + bool negative_; + unsigned int years_; + unsigned int months_; + unsigned int days_; + unsigned int hours_; + unsigned int minutes_; + double seconds_; + }; + + bool + operator== (const duration&, const duration&); + + bool + operator!= (const duration&, const duration&); + } +} + +#include + +#endif // XSDE_CXX_DATE_TIME_HXX diff --git a/libxsde/xsde/cxx/date-time.ixx b/libxsde/xsde/cxx/date-time.ixx new file mode 100644 index 0000000..d51d00c --- /dev/null +++ b/libxsde/xsde/cxx/date-time.ixx @@ -0,0 +1,725 @@ +// file : xsde/cxx/date-time.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + // time_zone + // + inline time_zone:: + time_zone () + : present_ (false) + { + } + + inline time_zone:: + time_zone (short h, short m) + : present_ (true), hours_ (h), minutes_ (m) + { + } + + inline bool time_zone:: + zone_present () const + { + return present_; + } + + inline void time_zone:: + zone_reset () + { + present_ = false; + } + + inline short time_zone:: + zone_hours () const + { + return hours_; + } + + inline void time_zone:: + zone_hours (short h) + { + hours_ = h; + present_ = true; + } + + inline short time_zone:: + zone_minutes () const + { + return minutes_; + } + + inline void time_zone:: + zone_minutes (short m) + { + minutes_ = m; + present_ = true; + } + + inline bool + operator== (const time_zone& x, const time_zone& y) + { + return x.zone_present () + ? y.zone_present () && + x.zone_hours () == y.zone_hours () && + x.zone_minutes () == y.zone_minutes () + : !y.zone_present (); + } + + inline bool + operator!= (const time_zone& x, const time_zone& y) + { + return !(x == y); + } + + // gday + // + inline gday:: + gday () + { + } + + inline gday:: + gday (unsigned short day) + : day_ (day) + { + } + + inline gday:: + gday (unsigned short day, short zone_h, short zone_m) + : time_zone (zone_h, zone_m), day_ (day) + { + } + + inline unsigned short gday:: + day () const + { + return day_; + } + + inline void gday:: + day (unsigned short day) + { + day_ = day; + } + + inline bool + operator== (const gday& x, const gday& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.day () == y.day () && xz == yz; + } + + inline bool + operator!= (const gday& x, const gday& y) + { + return !(x == y); + } + + // gmonth + // + inline gmonth:: + gmonth () + { + } + + inline gmonth:: + gmonth (unsigned short month) + : month_ (month) + { + } + + inline gmonth:: + gmonth (unsigned short month, short zone_h, short zone_m) + : time_zone (zone_h, zone_m), month_ (month) + { + } + + inline unsigned short gmonth:: + month () const + { + return month_; + } + + inline void gmonth:: + month (unsigned short month) + { + month_ = month; + } + + inline bool + operator== (const gmonth& x, const gmonth& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.month () == y.month () && xz == yz; + } + + inline bool + operator!= (const gmonth& x, const gmonth& y) + { + return !(x == y); + } + + // gyear + // + inline gyear:: + gyear () + { + } + + inline gyear:: + gyear (int year) + : year_ (year) + { + } + + inline gyear:: + gyear (int year, short zone_h, short zone_m) + : time_zone (zone_h, zone_m), year_ (year) + { + } + + inline int gyear:: + year () const + { + return year_; + } + + inline void gyear:: + year (int year) + { + year_ = year; + } + + inline bool + operator== (const gyear& x, const gyear& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.year () == y.year () && xz == yz; + } + + inline bool + operator!= (const gyear& x, const gyear& y) + { + return !(x == y); + } + + // gmonth_day + // + inline gmonth_day:: + gmonth_day () + { + } + + inline gmonth_day:: + gmonth_day (unsigned short month, unsigned short day) + : month_ (month), day_ (day) + { + } + + inline gmonth_day:: + gmonth_day (unsigned short month, unsigned short day, + short zone_h, short zone_m) + : time_zone (zone_h, zone_m), month_ (month), day_ (day) + { + } + + inline unsigned short gmonth_day:: + month () const + { + return month_; + } + + inline void gmonth_day:: + month (unsigned short month) + { + month_ = month; + } + + inline unsigned short gmonth_day:: + day () const + { + return day_; + } + + inline void gmonth_day:: + day (unsigned short day) + { + day_ = day; + } + + inline bool + operator== (const gmonth_day& x, const gmonth_day& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.month () == y.month () && + x.day () == y.day () && + xz == yz; + } + + inline bool + operator!= (const gmonth_day& x, const gmonth_day& y) + { + return !(x == y); + } + + // gyear_month + // + inline gyear_month:: + gyear_month () + { + } + + inline gyear_month:: + gyear_month (int year, unsigned short month) + : year_ (year), month_ (month) + { + } + + inline gyear_month:: + gyear_month (int year, unsigned short month, + short zone_h, short zone_m) + : time_zone (zone_h, zone_m), year_ (year), month_ (month) + { + } + + inline int gyear_month:: + year () const + { + return year_; + } + + inline void gyear_month:: + year (int year) + { + year_ = year; + } + + inline unsigned short gyear_month:: + month () const + { + return month_; + } + + inline void gyear_month:: + month (unsigned short month) + { + month_ = month; + } + + inline bool + operator== (const gyear_month& x, const gyear_month& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.year () == y.year () && + x.month () == y.month () && + xz == yz; + } + + inline bool + operator!= (const gyear_month& x, const gyear_month& y) + { + return !(x == y); + } + + // date + // + inline date:: + date () + { + } + + inline date:: + date (int year, unsigned short month, unsigned short day) + : year_ (year), month_ (month), day_ (day) + { + } + + inline date:: + date (int year, unsigned short month, unsigned short day, + short zone_h, short zone_m) + : time_zone (zone_h, zone_m), + year_ (year), month_ (month), day_ (day) + { + } + + inline int date:: + year () const + { + return year_; + } + + inline void date:: + year (int year) + { + year_ = year; + } + + inline unsigned short date:: + month () const + { + return month_; + } + + inline void date:: + month (unsigned short month) + { + month_ = month; + } + + inline unsigned short date:: + day () const + { + return day_; + } + + inline void date:: + day (unsigned short day) + { + day_ = day; + } + + inline bool + operator== (const date& x, const date& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.year () == y.year () && + x.month () == y.month () && + x.day () == y.day () && + xz == yz; + } + + inline bool + operator!= (const date& x, const date& y) + { + return !(x == y); + } + + // time + // + inline time:: + time () + { + } + + inline time:: + time (unsigned short hours, unsigned short minutes, double seconds) + : hours_ (hours), minutes_ (minutes), seconds_ (seconds) + { + } + + inline time:: + time (unsigned short hours, unsigned short minutes, double seconds, + short zone_h, short zone_m) + : time_zone (zone_h, zone_m), + hours_ (hours), minutes_ (minutes), seconds_ (seconds) + { + } + + inline unsigned short time:: + hours () const + { + return hours_; + } + + inline void time:: + hours (unsigned short hours) + { + hours_ = hours; + } + + inline unsigned short time:: + minutes () const + { + return minutes_; + } + + inline void time:: + minutes (unsigned short minutes) + { + minutes_ = minutes; + } + + inline double time:: + seconds () const + { + return seconds_; + } + + inline void time:: + seconds (double seconds) + { + seconds_ = seconds; + } + + inline bool + operator== (const time& x, const time& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.hours () == y.hours () && + x.minutes () == y.minutes () && + x.seconds () == y.seconds () && + xz == yz; + } + + inline bool + operator!= (const time& x, const time& y) + { + return !(x == y); + } + + // date_time + // + inline date_time:: + date_time () + { + } + + inline date_time:: + date_time (int year, unsigned short month, unsigned short day, + unsigned short hours, unsigned short minutes, double seconds) + : year_ (year), month_ (month), day_ (day), + hours_ (hours), minutes_ (minutes), seconds_ (seconds) + { + } + + inline date_time:: + date_time (int year, unsigned short month, unsigned short day, + unsigned short hours, unsigned short minutes, double seconds, + short zone_h, short zone_m) + : time_zone (zone_h, zone_m), + year_ (year), month_ (month), day_ (day), + hours_ (hours), minutes_ (minutes), seconds_ (seconds) + { + } + + inline int date_time:: + year () const + { + return year_; + } + + inline void date_time:: + year (int year) + { + year_ = year; + } + + inline unsigned short date_time:: + month () const + { + return month_; + } + + inline void date_time:: + month (unsigned short month) + { + month_ = month; + } + + inline unsigned short date_time:: + day () const + { + return day_; + } + + inline void date_time:: + day (unsigned short day) + { + day_ = day; + } + + inline unsigned short date_time:: + hours () const + { + return hours_; + } + + inline void date_time:: + hours (unsigned short hours) + { + hours_ = hours; + } + + inline unsigned short date_time:: + minutes () const + { + return minutes_; + } + + inline void date_time:: + minutes (unsigned short minutes) + { + minutes_ = minutes; + } + + inline double date_time:: + seconds () const + { + return seconds_; + } + + inline void date_time:: + seconds (double seconds) + { + seconds_ = seconds; + } + + inline bool + operator== (const date_time& x, const date_time& y) + { + const time_zone& xz = x; + const time_zone& yz = y; + + return x.year () == y.year () && + x.month () == y.month () && + x.day () == y.day () && + x.hours () == y.hours () && + x.minutes () == y.minutes () && + x.seconds () == y.seconds () && + xz == yz; + } + + inline bool + operator!= (const date_time& x, const date_time& y) + { + return !(x == y); + } + + // duration + // + inline duration:: + duration () + { + } + + inline duration:: + duration (bool negative, + unsigned int years, unsigned int months, unsigned int days, + unsigned int hours, unsigned int minutes, double seconds) + : negative_ (negative), + years_ (years), months_ (months), days_ (days), + hours_ (hours), minutes_ (minutes), seconds_ (seconds) + { + } + + inline bool duration:: + negative () const + { + return negative_; + } + + inline void duration:: + negative (bool negative) + { + negative_ = negative; + } + + inline unsigned int duration:: + years () const + { + return years_; + } + + inline void duration:: + years (unsigned int years) + { + years_ = years; + } + + inline unsigned int duration:: + months () const + { + return months_; + } + + inline void duration:: + months (unsigned int months) + { + months_ = months; + } + + inline unsigned int duration:: + days () const + { + return days_; + } + + inline void duration:: + days (unsigned int days) + { + days_ = days; + } + + inline unsigned int duration:: + hours () const + { + return hours_; + } + + inline void duration:: + hours (unsigned int hours) + { + hours_ = hours; + } + + inline unsigned int duration:: + minutes () const + { + return minutes_; + } + + inline void duration:: + minutes (unsigned int minutes) + { + minutes_ = minutes; + } + + inline double duration:: + seconds () const + { + return seconds_; + } + + inline void duration:: + seconds (double seconds) + { + seconds_ = seconds; + } + + inline bool + operator== (const duration& x, const duration& y) + { + return x.negative () == y.negative () && + x.years () == y.years () && + x.months () == y.months () && + x.days () == y.days () && + x.hours () == y.hours () && + x.minutes () == y.minutes () && + x.seconds () == y.seconds (); + } + + inline bool + operator!= (const duration& x, const duration& y) + { + return !(x == y); + } + } +} diff --git a/libxsde/xsde/cxx/errno.hxx b/libxsde/xsde/cxx/errno.hxx new file mode 100644 index 0000000..1669ec5 --- /dev/null +++ b/libxsde/xsde/cxx/errno.hxx @@ -0,0 +1,23 @@ +// file : xsde/cxx/errno.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_ERRNO_HXX +#define XSDE_CXX_ERRNO_HXX + +namespace xsde +{ + namespace cxx + { + int + get_errno (); + + void + set_errno (int); + } +} + +#include + +#endif // XSDE_CXX_ERRNO_HXX diff --git a/libxsde/xsde/cxx/errno.ixx b/libxsde/xsde/cxx/errno.ixx new file mode 100644 index 0000000..f817bbc --- /dev/null +++ b/libxsde/xsde/cxx/errno.ixx @@ -0,0 +1,44 @@ +// file : xsde/cxx/errno.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#ifdef XSDE_PLATFORM_WINCE +# include // Get/SetLastError +#else +# include +#endif + +namespace xsde +{ + namespace cxx + { +#ifdef XSDE_PLATFORM_WINCE + inline int + get_errno () + { + return static_cast (GetLastError ()); + } + + inline void + set_errno (int e) + { + SetLastError (static_cast (e)); + } +#else + inline int + get_errno () + { + return errno; + } + + inline void + set_errno (int e) + { + errno = e; + } +#endif + } +} diff --git a/libxsde/xsde/cxx/exceptions.hxx b/libxsde/xsde/cxx/exceptions.hxx new file mode 100644 index 0000000..26ed4a9 --- /dev/null +++ b/libxsde/xsde/cxx/exceptions.hxx @@ -0,0 +1,21 @@ +// file : xsde/cxx/exceptions.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_EXCEPTIONS_HXX +#define XSDE_CXX_EXCEPTIONS_HXX + +#include // std::exception + +namespace xsde +{ + namespace cxx + { + struct exception: std::exception + { + }; + } +} + +#endif // XSDE_CXX_EXCEPTIONS_HXX diff --git a/libxsde/xsde/cxx/hashmap.cxx b/libxsde/xsde/cxx/hashmap.cxx new file mode 100644 index 0000000..c5d9079 --- /dev/null +++ b/libxsde/xsde/cxx/hashmap.cxx @@ -0,0 +1,210 @@ +// file : xsde/cxx/hashmap.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memset, memcpy, strlen, strcmp, strncmp + +#include + +namespace xsde +{ + namespace cxx + { + // const_iterator + // + hashmap_const_iterator:: + hashmap_const_iterator (const hashmap& map, size_t b) + : map_ (&map), bucket_ (b), element_ (0) + { + // Get it to the first actual element if any. + // + for (; bucket_ < map_->bcount_; ++bucket_) + { + hashmap::bucket* p = map_->buckets_[bucket_]; + if (p && p->size_) + break; + } + } + + const void* hashmap_const_iterator:: + operator* () const + { + typedef hashmap::bucket bucket; + typedef hashmap::element element; + + bucket* p = map_->buckets_[bucket_]; + const char* b = reinterpret_cast (p) + sizeof (bucket); + b += element_ * (sizeof (element) + map_->esize_); + return b + sizeof (element); + } + + hashmap_const_iterator& hashmap_const_iterator:: + operator++ () + { + if (bucket_ < map_->bcount_) + { + hashmap::bucket* p = map_->buckets_[bucket_]; + + if (p->size_ > element_ + 1) + ++element_; + else + { + element_ = 0; + + for (++bucket_; bucket_ < map_->bcount_; ++bucket_) + { + p = map_->buckets_[bucket_]; + if (p && p->size_) + break; + } + } + } + + return *this; + } + + // hashmap + // + hashmap:: + ~hashmap () + { +#ifndef XSDE_EXCEPTIONS + if (buckets_ != 0) + { +#endif + for (size_t i = 0; i < bcount_; ++i) + { + if (buckets_[i]) + operator delete (buckets_[i]); + } + + delete[] buckets_; + +#ifndef XSDE_EXCEPTIONS + } +#endif + } + + + hashmap:: + hashmap (size_t bcount, size_t esize) + : esize_ (esize), ecount_ (0), bcount_ (bcount), buckets_ (0) + { +#ifndef XSDE_EXCEPTIONS + error_ = error_none; +#endif + + buckets_ = new bucket*[bcount_]; + +#ifndef XSDE_EXCEPTIONS + if (buckets_ == 0) + { + error_ = error_no_memory; + return; + } +#endif + memset (buckets_, 0, sizeof (bucket*) * bcount_); + } + + void hashmap:: + insert (const char* key, void* value) + { + size_t h = hash (key); + bucket*& p = *(buckets_ + h % bcount_); + + if (p == 0) + { + // No elements in this bucket yet. Start with capacity for 2 + // elements. + // + p = static_cast ( + operator new (sizeof (bucket) + 2 * (sizeof (element) + esize_))); + +#ifndef XSDE_EXCEPTIONS + if (p == 0) + { + error_ = error_no_memory; + return; + } +#endif + p->size_ = 0; + p->capacity_ = 2; + } + + if (p->size_ == p->capacity_) + { + // No more space in this bucket. Create a bigger bucket. + // + size_t c = p->size_ * 2; + bucket* n = static_cast ( + operator new (sizeof (bucket) + c * (sizeof (element) + esize_))); + +#ifndef XSDE_EXCEPTIONS + if (n == 0) + { + error_ = error_no_memory; + return; + } +#endif + n->size_ = p->size_; + n->capacity_ = c; + + char* src = reinterpret_cast (p) + sizeof (bucket); + char* dst = reinterpret_cast (n) + sizeof (bucket); + + memcpy (dst, src, p->size_ * (sizeof (element) + esize_)); + + operator delete (p); + p = n; + } + + char* data = reinterpret_cast (p) + sizeof (bucket) + + p->size_ * (sizeof (element) + esize_); + + element* e = reinterpret_cast (data); + e->hash_ = h; + e->key_ = key; + + memcpy (data + sizeof (element), value, esize_); + + p->size_++; + ecount_++; + } + + const void* hashmap:: + find (const char* key) const + { + size_t h = hash (key); + const bucket* p = *(buckets_ + h % bcount_); + + if (p) + { + const char* b = reinterpret_cast (p) + sizeof (bucket); + const char* e = b + p->size_ * (sizeof (element) + esize_); + + for (; b < e; b += sizeof (element) + esize_) + { + const element* e = reinterpret_cast (b); + + if (e->hash_ == h && strcmp (e->key_, key) == 0) + return b + sizeof (element); + } + } + + return 0; + } + + size_t hashmap:: + max_bucket_size () const + { + size_t r = 0; + for (size_t i = 0; i < bcount_; ++i) + { + if (buckets_[i] != 0 && buckets_[i]->size_ > r) + r = buckets_[i]->size_; + } + return r; + } + } +} diff --git a/libxsde/xsde/cxx/hashmap.hxx b/libxsde/xsde/cxx/hashmap.hxx new file mode 100644 index 0000000..29c47e7 --- /dev/null +++ b/libxsde/xsde/cxx/hashmap.hxx @@ -0,0 +1,156 @@ +// file : xsde/cxx/hashmap.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_HASHMAP_HXX +#define XSDE_CXX_HASHMAP_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + class hashmap; + + class hashmap_const_iterator + { + public: + hashmap_const_iterator (const hashmap& map, size_t bucket); + + // Forward iterator requirements. + // + const void* + operator* () const; + + hashmap_const_iterator& + operator++ (); + + hashmap_const_iterator + operator++ (int); + + friend bool + operator== (const hashmap_const_iterator& i, + const hashmap_const_iterator& j); + private: + const hashmap* map_; + size_t bucket_; + size_t element_; + }; + + bool + operator!= (const hashmap_const_iterator& i, + const hashmap_const_iterator& j); + + // Special-purpose, light-weight C-string to POD hashmap. Some of + // its characteristics: + // + // - number of buckets does not grow (no re-hashing) + // - removal of items is not supported + // - key and value (POD) are not deep-copied + // - empty bucket is cheap (1 pointer) + // + class hashmap + { + public: +#ifndef XSDE_EXCEPTIONS + enum error + { + error_none, + error_no_memory + }; + + error + _error () const; +#endif + + public: + ~hashmap (); + hashmap (size_t buckets, size_t element_size); + + private: + hashmap (hashmap&); + + hashmap& + operator= (hashmap&); + + public: + void + insert (const char* key, void* value); + + const void* + find (const char* key) const; + + public: + bool + empty () const; + + size_t + size () const; + + // Return the maximum number of elements in a single bucket. + // + size_t + max_bucket_size () const; + + public: + typedef hashmap_const_iterator const_iterator; + + const_iterator + begin () const; + + const_iterator + end () const; + + public: + static size_t + hash (const char*); + + static size_t + hash (const char*, size_t n); + + static size_t + hash (size_t hash, const char*); + + static size_t + hash (size_t hash, const char*, size_t n); + + protected: + struct bucket + { + size_t size_; + size_t capacity_; + }; + + struct element + { + size_t hash_; + const char* key_; + }; + + protected: + const bucket* + find (size_t hash) const; + + private: + friend class hashmap_const_iterator; + + size_t esize_; // element size + size_t ecount_; // element count + size_t bcount_; // bucket count + bucket** buckets_; + +#ifndef XSDE_EXCEPTIONS + protected: + error error_; +#endif + }; + } +} + +#include + +#endif // XSDE_CXX_HASHMAP_HXX diff --git a/libxsde/xsde/cxx/hashmap.ixx b/libxsde/xsde/cxx/hashmap.ixx new file mode 100644 index 0000000..a2d2a1b --- /dev/null +++ b/libxsde/xsde/cxx/hashmap.ixx @@ -0,0 +1,177 @@ +// file : xsde/cxx/hashmap.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + // const_iterator + // + inline hashmap_const_iterator hashmap_const_iterator:: + operator++ (int) + { + hashmap_const_iterator r (*this); + ++(*this); + return r; + } + + inline bool + operator== (const hashmap_const_iterator& i, + const hashmap_const_iterator& j) + { + return i.map_ == j.map_ && + i.bucket_ == j.bucket_ && + i.element_ == j.element_; + } + + inline bool + operator!= (const hashmap_const_iterator& i, + const hashmap_const_iterator& j) + { + return !(i == j); + } + + // hashmap + // + +#ifndef XSDE_EXCEPTIONS + inline hashmap::error hashmap:: + _error () const + { + return error_; + } +#endif + + inline bool hashmap:: + empty () const + { + return ecount_ == 0; + } + + inline size_t hashmap:: + size () const + { + return ecount_; + } + + inline const hashmap::bucket* hashmap:: + find (size_t h) const + { + return *(buckets_ + h % bcount_); + } + + inline hashmap::const_iterator hashmap:: + begin () const + { + return const_iterator (*this, ecount_ ? 0 : bcount_); + } + + inline hashmap::const_iterator hashmap:: + end () const + { + return const_iterator (*this, bcount_); + } + + // Fowler/Noll/Vo (FNV) hash (type FNV-1a) + // +#if XSDE_ARCH_WIDTH == 32 + inline size_t hashmap:: + hash (const char* s) + { + size_t r = static_cast (2166136261UL); + for (; *s != 0; ++s) + { + r ^= static_cast (*s); + r *= static_cast (16777619UL); + } + return r; + } + + inline size_t hashmap:: + hash (const char* s, size_t n) + { + size_t r = static_cast (2166136261UL); + for (; n > 0; --n) + { + r ^= static_cast (*s++); + r *= static_cast (16777619UL); + } + return r; + } + + inline size_t hashmap:: + hash (size_t h, const char* s) + { + for (; *s != 0; ++s) + { + h ^= static_cast (*s); + h *= static_cast (16777619UL); + } + return h; + } + + inline size_t hashmap:: + hash (size_t h, const char* s, size_t n) + { + for (; n > 0; --n) + { + h ^= static_cast (*s++); + h *= static_cast (16777619UL); + } + return h; + } + +#elif XSDE_ARCH_WIDTH == 64 + + inline size_t hashmap:: + hash (const char* s) + { + size_t r = static_cast (14695981039346656037ULL); + for (; *s != 0; ++s) + { + r ^= static_cast (*s); + r *= static_cast (1099511628211ULL); + } + return r; + } + + inline size_t hashmap:: + hash (const char* s, size_t n) + { + size_t r = static_cast (14695981039346656037ULL); + for (; n > 0; --n) + { + r ^= static_cast (*s++); + r *= static_cast (1099511628211ULL); + } + return r; + } + + inline size_t hashmap:: + hash (size_t h, const char* s) + { + for (; *s != 0; ++s) + { + h ^= static_cast (*s); + h *= static_cast (1099511628211ULL); + } + return h; + } + + inline size_t hashmap:: + hash (size_t h, const char* s, size_t n) + { + for (; n > 0; --n) + { + h ^= static_cast (*s++); + h *= static_cast (1099511628211ULL); + } + return h; + } +#else +#error there is no suitable hash function for this architecture width +#endif // XSDE_ARCH_WIDTH + } +} diff --git a/libxsde/xsde/cxx/hybrid/any-type.hxx b/libxsde/xsde/cxx/hybrid/any-type.hxx new file mode 100644 index 0000000..db512c2 --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/any-type.hxx @@ -0,0 +1,26 @@ +// file : xsde/cxx/hybrid/any-type.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_HYBRID_ANY_TYPE_HXX +#define XSDE_CXX_HYBRID_ANY_TYPE_HXX + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + struct any_type + { + }; + + struct any_simple_type + { + }; + } + } +} + +#endif // XSDE_CXX_HYBRID_ANY_TYPE_HXX diff --git a/libxsde/xsde/cxx/hybrid/base.hxx b/libxsde/xsde/cxx/hybrid/base.hxx new file mode 100644 index 0000000..75753bc --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/base.hxx @@ -0,0 +1,370 @@ +// file : xsde/cxx/hybrid/base.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_HYBRID_BASE_HXX +#define XSDE_CXX_HYBRID_BASE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + // boolean + // + struct boolean_base + { + bool base_value () const {return x_;} + bool& base_value () {return x_;} + void base_value (bool x) {x_ = x;} + + operator const bool& () const {return x_;} + operator bool& () {return x_;} + + boolean_base& operator= (bool x) {x_ = x; return *this;} + + protected: + bool x_; + }; + + // byte + // + struct byte_base + { + signed char base_value () const {return x_;} + signed char& base_value () {return x_;} + void base_value (signed char x) {x_ = x;} + + operator const signed char& () const {return x_;} + operator signed char& () {return x_;} + + byte_base& operator= (signed char x) {x_ = x; return *this;} + + protected: + signed char x_; + }; + + // unsigned_byte + // + struct unsigned_byte_base + { + unsigned char base_value () const {return x_;} + unsigned char& base_value () {return x_;} + void base_value (unsigned char x) {x_ = x;} + + operator const unsigned char& () const {return x_;} + operator unsigned char& () {return x_;} + + unsigned_byte_base& + operator= (unsigned char x) {x_ = x; return *this;} + + protected: + unsigned char x_; + }; + + // short + // + struct short_base + { + short base_value () const {return x_;} + short& base_value () {return x_;} + void base_value (short x) {x_ = x;} + + operator const short& () const {return x_;} + operator short& () {return x_;} + + short_base& operator= (short x) {x_ = x; return *this;} + + protected: + short x_; + }; + + // unsigned_short + // + struct unsigned_short_base + { + unsigned short base_value () const {return x_;} + unsigned short& base_value () {return x_;} + void base_value (unsigned short x) {x_ = x;} + + operator const unsigned short& () const {return x_;} + operator unsigned short& () {return x_;} + + unsigned_short_base& + operator= (unsigned short x) {x_ = x; return *this;} + + protected: + unsigned short x_; + }; + + // int + // + struct int_base + { + int base_value () const {return x_;} + int& base_value () {return x_;} + void base_value (int x) {x_ = x;} + + operator const int& () const {return x_;} + operator int& () {return x_;} + + int_base& operator= (int x) {x_ = x; return *this;} + + protected: + int x_; + }; + + // unsigned_int + // + struct unsigned_int_base + { + unsigned int base_value () const {return x_;} + unsigned int& base_value () {return x_;} + void base_value (unsigned int x) {x_ = x;} + + operator const unsigned int& () const {return x_;} + operator unsigned int& () {return x_;} + + unsigned_int_base& operator= (unsigned int x) {x_ = x; return *this;} + + protected: + unsigned int x_; + }; + + // long + // +#ifdef XSDE_LONGLONG + struct long_base + { + long long base_value () const {return x_;} + long long& base_value () {return x_;} + void base_value (long long x) {x_ = x;} + + operator const long long& () const {return x_;} + operator long long& () {return x_;} + + long_base& operator= (long long x) {x_ = x; return *this;} + + protected: + long long x_; + }; +#else + struct long_base + { + long base_value () const {return x_;} + long& base_value () {return x_;} + void base_value (long x) {x_ = x;} + + operator const long& () const {return x_;} + operator long& () {return x_;} + + long_base& operator= (long x) {x_ = x; return *this;} + + protected: + long x_; + }; +#endif + + + // unsigned_long + // +#ifdef XSDE_LONGLONG + struct unsigned_long_base + { + unsigned long long base_value () const {return x_;} + unsigned long long& base_value () {return x_;} + void base_value (unsigned long long x) {x_ = x;} + + operator const unsigned long long& () const {return x_;} + operator unsigned long long& () {return x_;} + + unsigned_long_base& + operator= (unsigned long long x) {x_ = x; return *this;} + + protected: + unsigned long long x_; + }; +#else + struct unsigned_long_base + { + unsigned long base_value () const {return x_;} + unsigned long& base_value () {return x_;} + void base_value (unsigned long x) {x_ = x;} + + operator const unsigned long& () const {return x_;} + operator unsigned long& () {return x_;} + + unsigned_long_base& + operator= (unsigned long x) {x_ = x; return *this;} + + protected: + unsigned long x_; + }; +#endif + + // integer + // + struct integer_base + { + long base_value () const {return x_;} + long& base_value () {return x_;} + void base_value (long x) {x_ = x;} + + operator const long& () const {return x_;} + operator long& () {return x_;} + + integer_base& operator= (long x) {x_ = x; return *this;} + + protected: + long x_; + }; + + // negative_integer + // + struct negative_integer_base + { + long base_value () const {return x_;} + long& base_value () {return x_;} + void base_value (long x) {x_ = x;} + + operator const long& () const {return x_;} + operator long& () {return x_;} + + negative_integer_base& operator= (long x) {x_ = x; return *this;} + + protected: + long x_; + }; + + // non_positive_integer + // + struct non_positive_integer_base + { + long base_value () const {return x_;} + long& base_value () {return x_;} + void base_value (long x) {x_ = x;} + + operator const long& () const {return x_;} + operator long& () {return x_;} + + non_positive_integer_base& operator= (long x) {x_ = x; return *this;} + + protected: + long x_; + }; + + // positive_integer + // + struct positive_integer_base + { + unsigned long base_value () const {return x_;} + unsigned long& base_value () {return x_;} + void base_value (unsigned long x) {x_ = x;} + + operator const unsigned long& () const {return x_;} + operator unsigned long& () {return x_;} + + positive_integer_base& + operator= (unsigned long x) {x_ = x; return *this;} + + protected: + unsigned long x_; + }; + + // non_negative_integer + // + struct non_negative_integer_base + { + unsigned long base_value () const {return x_;} + unsigned long& base_value () {return x_;} + void base_value (unsigned long x) {x_ = x;} + + operator const unsigned long& () const {return x_;} + operator unsigned long& () {return x_;} + + non_negative_integer_base& + operator= (unsigned long x) {x_ = x; return *this;} + + protected: + unsigned long x_; + }; + + // float + // + struct float_base + { + float base_value () const {return x_;} + float& base_value () {return x_;} + void base_value (float x) {x_ = x;} + + operator const float& () const {return x_;} + operator float& () {return x_;} + + float_base& operator= (float x) {x_ = x; return *this;} + + protected: + float x_; + }; + + // double + // + struct double_base + { + double base_value () const {return x_;} + double& base_value () {return x_;} + void base_value (double x) {x_ = x;} + + operator const double& () const {return x_;} + operator double& () {return x_;} + + double_base& operator= (double x) {x_ = x; return *this;} + + protected: + double x_; + }; + + // decimal + // + struct decimal_base + { + double base_value () const {return x_;} + double& base_value () {return x_;} + void base_value (double x) {x_ = x;} + + operator const double& () const {return x_;} + operator double& () {return x_;} + + decimal_base& operator= (double x) {x_ = x; return *this;} + + protected: + double x_; + }; + + // string + // + struct string_base + { + string_base () : x_ (0) {} + ~string_base () {delete[] x_;} + + const char* base_value () const {return x_;} + char* base_value () {return x_;} + void base_value (char* x) {delete[] x_; x_ = x;} + + operator const char* () const {return x_;} + operator char* () {return x_;} + + string_base& operator= (char* x) {delete[] x_; x_ = x; return *this;} + + protected: + char* x_; + }; + } + } +} + +#endif // XSDE_CXX_HYBRID_BASE_HXX diff --git a/libxsde/xsde/cxx/hybrid/sequence.cxx b/libxsde/xsde/cxx/hybrid/sequence.cxx new file mode 100644 index 0000000..da16e95 --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/sequence.cxx @@ -0,0 +1,31 @@ +// file : xsde/cxx/hybrid/sequence.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + // + // data_seq + // + + void data_seq:: + clear () + { + if (destructor_) + { + for (size_t i = 0; i < size_; ++i) + destructor_ (static_cast (data_)[i], i); + } + + size_ = 0; + } + } + } +} diff --git a/libxsde/xsde/cxx/hybrid/sequence.hxx b/libxsde/xsde/cxx/hybrid/sequence.hxx new file mode 100644 index 0000000..d7f6dcb --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/sequence.hxx @@ -0,0 +1,921 @@ +// file : xsde/cxx/hybrid/sequence.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_HYBRID_SEQUENCE_HXX +#define XSDE_CXX_HYBRID_SEQUENCE_HXX + +#include // size_t, ptrdiff_t + +#include +#include + +#ifdef XSDE_STL +# include +#else +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + // Sequence with fixed-length POD elements. + // + template + class pod_seq: public sequence_base + { + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef T* iterator; + typedef const T* const_iterator; + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + T& + front (); + + const T& + front () const; + + T& + back (); + + const T& + back () const; + + T& + operator[] (size_t); + + const T& + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (const T&); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, const T&); + + error + insert (iterator, const T&, iterator& result); +#else + iterator + insert (iterator, const T&); +#endif + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (pod_seq&); + }; + + // Sequence with fixed-length elements. + // + template + class fix_seq: public sequence_base + { + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef T* iterator; + typedef const T* const_iterator; + + public: + ~fix_seq (); + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + T& + front (); + + const T& + front () const; + + T& + back (); + + const T& + back () const; + + T& + operator[] (size_t); + + const T& + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (const T&); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, const T&); + + error + insert (iterator, const T&, iterator& result); +#else + iterator + insert (iterator, const T&); +#endif + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (fix_seq&); + + private: + static void + move_ (void* dst, void* src, size_t n); + + static void + move_forward_ (void* p, size_t n); + +#ifdef XSDE_EXCEPTIONS + static void + move_backward_ (void* p, size_t n, size_t& size); +#else + static void + move_backward_ (void* p, size_t n); +#endif + +#ifdef XSDE_EXCEPTIONS + struct guard + { + guard (T* p, size_t& n) : p_ (p), n_ (n) {} + + ~guard () + { + if (p_) + for (; n_ > 0; --n_) + p_[n_ - 1].~T (); + } + + void + release () { p_ = 0; } + + private: + T* p_; + size_t& n_; + }; +#endif + }; + + // Sequence with variable-length elements. + // + template + class var_iterator + { + public: + typedef T value_type; + typedef T& reference; + typedef T* pointer; + + typedef ptrdiff_t difference_type; + + public: + var_iterator () + : i_ (0) + { + } + + explicit + var_iterator (T** i) + : i_ (i) + { + } + + public: + // Forward iterator requirements. + // + T& + operator* () const + { + return **i_; + } + + T* + operator-> () const + { + return *i_; + } + + var_iterator& + operator++ () + { + ++i_; + return *this; + } + + var_iterator + operator++ (int) + { + var_iterator r (*this); + ++i_; + return r; + } + + // Bidirectional iterator requirements. + // + var_iterator& + operator-- () + { + --i_; + return *this; + } + + var_iterator + operator-- (int) + { + var_iterator r (*this); + --i_; + return r; + } + + // Random access iterator requirements. + // + T& + operator[] (ptrdiff_t n) const + { + return *(i_[n]); + } + + var_iterator& + operator+= (ptrdiff_t n) + { + i_ += n; + return *this; + } + + var_iterator + operator+ (ptrdiff_t n) const + { + return var_iterator (i_ + n); + } + + var_iterator& + operator-= (ptrdiff_t n) + { + i_ -= n; + return *this; + } + + var_iterator + operator- (ptrdiff_t n) const + { + return var_iterator (i_ - n); + } + + public: + T** i_; + }; + + template + class var_const_iterator + { + public: + typedef const T value_type; + typedef const T& reference; + typedef const T* pointer; + + typedef ptrdiff_t difference_type; + + public: + var_const_iterator () + : i_ (0) + { + } + + var_const_iterator (var_iterator j) + : i_ (const_cast (j.i_)) + { + } + + explicit + var_const_iterator (const T** i) + : i_ (i) + { + } + + var_const_iterator& + operator= (var_const_iterator j) + { + i_ = j.i_; + return *this; + } + + var_const_iterator& + operator= (var_iterator j) + { + i_ = const_cast (j.i_); + return *this; + } + + public: + // Forward iterator requirements. + // + const T& + operator* () const + { + return **i_; + } + + const T* + operator-> () const + { + return *i_; + } + + var_const_iterator& + operator++ () + { + ++i_; + return *this; + } + + var_const_iterator + operator++ (int) + { + var_const_iterator r (*this); + ++i_; + return r; + } + + // Bidirectional iterator requirements. + // + var_const_iterator& + operator-- () + { + --i_; + return *this; + } + + var_const_iterator + operator-- (int) + { + var_const_iterator r (*this); + --i_; + return r; + } + + // Random access iterator requirements. + // + const T& + operator[] (ptrdiff_t n) const + { + return *(i_[n]); + } + + var_const_iterator& + operator+= (ptrdiff_t n) + { + i_ += n; + return *this; + } + + var_const_iterator + operator+ (ptrdiff_t n) const + { + return var_const_iterator (i_ + n); + } + + var_const_iterator& + operator-= (ptrdiff_t n) + { + i_ -= n; + return *this; + } + + var_const_iterator + operator- (ptrdiff_t n) const + { + return var_const_iterator (i_ - n); + } + + public: + const T** i_; + }; + + // Forward iterator requirements. + // + template + inline bool + operator== (var_iterator i, var_iterator j) + { + return i.i_ == j.i_; + } + + template + inline bool + operator== (var_const_iterator i, var_const_iterator j) + { + return i.i_ == j.i_; + } + + template + inline bool + operator== (var_iterator i, var_const_iterator j) + { + // eVC++ 4.0 needs the cast. + // + return const_cast (i.i_) == j.i_; + } + + template + inline bool + operator== (var_const_iterator i, var_iterator j) + { + return i.i_ == const_cast (j.i_); + } + + template + inline bool + operator!= (var_iterator i, var_iterator j) + { + return i.i_ != j.i_; + } + + template + inline bool + operator!= (var_const_iterator i, var_const_iterator j) + { + return i.i_ != j.i_; + } + + template + inline bool + operator!= (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) != j.i_; + } + + template + inline bool + operator!= (var_const_iterator i, var_iterator j) + { + return i.i_ != const_cast (j.i_); + } + + // Random access iterator requirements + // + template + inline bool + operator< (var_iterator i, var_iterator j) + { + return i.i_ < j.i_; + } + + template + inline bool + operator< (var_const_iterator i, var_const_iterator j) + { + return i.i_ < j.i_; + } + + template + inline bool + operator< (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) < j.i_; + } + + template + inline bool + operator< (var_const_iterator i, var_iterator j) + { + return i.i_ < const_cast (j.i_); + } + + template + inline bool + operator> (var_iterator i, var_iterator j) + { + return i.i_ > j.i_; + } + + template + inline bool + operator> (var_const_iterator i, var_const_iterator j) + { + return i.i_ > j.i_; + } + + template + inline bool + operator> (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) > j.i_; + } + + template + inline bool + operator> (var_const_iterator i, var_iterator j) + { + return i.i_ > const_cast (j.i_); + } + + template + inline bool + operator<= (var_iterator i, var_iterator j) + { + return i.i_ <= j.i_; + } + + template + inline bool + operator<= (var_const_iterator i, var_const_iterator j) + { + return i.i_ <= j.i_; + } + + template + inline bool + operator<= (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) <= j.i_; + } + + template + inline bool + operator<= (var_const_iterator i, var_iterator j) + { + return i.i_ <= const_cast (j.i_); + } + + template + inline bool + operator>= (var_iterator i, var_iterator j) + { + return i.i_ >= j.i_; + } + + template + inline bool + operator>= (var_const_iterator i, var_const_iterator j) + { + return i.i_ >= j.i_; + } + + template + inline bool + operator>= (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) >= j.i_; + } + + template + inline bool + operator>= (var_const_iterator i, var_iterator j) + { + return i.i_ >= const_cast (j.i_); + } + + template + inline ptrdiff_t + operator- (var_iterator i, var_iterator j) + { + return i.i_ - j.i_; + } + + template + inline ptrdiff_t + operator- (var_const_iterator i, var_const_iterator j) + { + return i.i_ - j.i_; + } + + template + inline ptrdiff_t + operator- (var_iterator i, var_const_iterator j) + { + return const_cast (i.i_) - j.i_; + } + + template + inline ptrdiff_t + operator- (var_const_iterator i, var_iterator j) + { + return i.i_ - const_cast (j.i_); + } + + template + inline var_iterator + operator+ (ptrdiff_t n, var_iterator i) + { + return var_iterator (i.i_ + n); + } + + template + inline var_iterator + operator+ (ptrdiff_t n, var_const_iterator i) + { + return var_const_iterator (i.i_ + n); + } + + // + // + template + class var_seq: public sequence_base + { + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef var_iterator iterator; + typedef var_const_iterator const_iterator; + + public: + ~var_seq (); + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + T& + front (); + + const T& + front () const; + + T& + back (); + + const T& + back () const; + + T& + operator[] (size_t); + + const T& + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (T*); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, T*); + + error + insert (iterator, T*, iterator& result); +#else + iterator + insert (iterator, T*); +#endif + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (var_seq&); + +#ifdef XSDE_EXCEPTIONS + private: + struct guard + { + ~guard () { delete p_; } + guard (T* p) : p_ (p) {} + + void + release () { p_ = 0; } + + private: + T* p_; + }; +#endif + }; + + + // String sequence. + // + typedef string_sequence str_seq; + + + // Custom data sequence. + // + class data_seq: public sequence_base + { + public: + typedef void* value_type; + typedef void** pointer; + typedef const void** const_pointer; + typedef void* reference; + typedef const void* const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef void** iterator; + typedef const void* const* const_iterator; + + public: + ~data_seq (); + data_seq (); + + typedef void (*destroy_func) (void* data, size_t pos); + + void + destructor (destroy_func); + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + void* + front (); + + const void* + front () const; + + void* + back (); + + const void* + back () const; + + void* + operator[] (size_t); + + const void* + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (void*); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, void*); + + error + insert (iterator, void*, iterator& result); +#else + iterator + insert (iterator, void*); +#endif + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (data_seq&); + + private: + destroy_func destructor_; + }; + } + } +} + +#include +#include + +#endif // XSDE_CXX_HYBRID_SEQUENCE_HXX diff --git a/libxsde/xsde/cxx/hybrid/sequence.ixx b/libxsde/xsde/cxx/hybrid/sequence.ixx new file mode 100644 index 0000000..c1566d2 --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/sequence.ixx @@ -0,0 +1,881 @@ +// file : xsde/cxx/hybrid/sequence.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // placement new + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + // + // pod_seq + // + + template + inline size_t pod_seq:: + max_size () const + { + return size_t (-1) / sizeof (T); + } + + template + inline void pod_seq:: + swap (pod_seq& x) + { + swap_ (x); + } + + template + inline T* pod_seq:: + begin () + { + return static_cast (data_); + } + + template + inline const T* pod_seq:: + begin () const + { + // g++ 2.95 does not like static_cast here. + // + return (const T*) (data_); + } + + template + inline T* pod_seq:: + end () + { + return static_cast (data_) + size_; + } + + template + inline const T* pod_seq:: + end () const + { + return ((const T*) (data_)) + size_; + } + + template + inline T& pod_seq:: + front () + { + return *static_cast (data_); + } + + template + inline const T& pod_seq:: + front () const + { + return *((const T*) (data_)); + } + + template + inline T& pod_seq:: + back () + { + return static_cast (data_)[size_ - 1]; + } + + template + inline const T& pod_seq:: + back () const + { + return ((const T*) (data_))[size_ - 1]; + } + + template + inline T& pod_seq:: + operator[] (size_t i) + { + return static_cast (data_)[i]; + } + + template + inline const T& pod_seq:: + operator[] (size_t i) const + { + return ((const T*) (data_))[i]; + } + + template + inline void pod_seq:: + clear () + { + size_ = 0; + } + + template + inline void pod_seq:: + pop_back () + { + --size_; + } + + template + inline T* pod_seq:: + erase (T* i) + { + if (i != static_cast (data_) + (size_ - 1)) + erase_ (i, sizeof (T), 0); + else + --size_; + + return i; + } + +#ifdef XSDE_EXCEPTIONS + template + inline void pod_seq:: + push_back (const T& x) + { + if (capacity_ < size_ + 1) + grow_ (0, sizeof (T), 0); + + static_cast (data_)[size_++] = x; + } + + template + inline T* pod_seq:: + insert (T* i, const T& x) + { + T* p = static_cast (insert_ (i, sizeof (T), 0, 0)); + *p = x; + return p; + } + + template + inline void pod_seq:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (T), 0); + } +#else + template + inline sequence_base::error pod_seq:: + push_back (const T& x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (T), 0); + + if (r == error_none) + static_cast (data_)[size_++] = x; + + return r; + } + + template + inline sequence_base::error pod_seq:: + insert (T* i, const T& x) + { + T* p = static_cast (insert_ (i, sizeof (T), 0, 0)); + + if (p) + { + *p = x; + return error_none; + } + else + return error_no_memory; + } + + template + inline sequence_base::error pod_seq:: + insert (T* i, const T& x, T*& r) + { + T* p = static_cast (insert_ (i, sizeof (T), 0, 0)); + + if (p) + { + *p = x; + r = p; + return error_none; + } + else + return error_no_memory; + } + + template + inline sequence_base::error pod_seq:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (T), 0); + return r; + } +#endif + + // + // fix_seq + // + + template + inline fix_seq:: + ~fix_seq () + { + clear (); + } + + template + inline size_t fix_seq:: + max_size () const + { + return size_t (-1) / sizeof (T); + } + + template + inline void fix_seq:: + swap (fix_seq& x) + { + swap_ (x); + } + + template + inline T* fix_seq:: + begin () + { + return static_cast (data_); + } + + template + inline const T* fix_seq:: + begin () const + { + return (const T*) (data_); + } + + template + inline T* fix_seq:: + end () + { + return static_cast (data_) + size_; + } + + template + inline const T* fix_seq:: + end () const + { + return ((const T*) (data_)) + size_; + } + + template + inline T& fix_seq:: + front () + { + return *static_cast (data_); + } + + template + inline const T& fix_seq:: + front () const + { + return *((const T*) (data_)); + } + + template + inline T& fix_seq:: + back () + { + return static_cast (data_)[size_ - 1]; + } + + template + inline const T& fix_seq:: + back () const + { + return ((const T*) (data_))[size_ - 1]; + } + + template + inline T& fix_seq:: + operator[] (size_t i) + { + return static_cast (data_)[i]; + } + + template + inline const T& fix_seq:: + operator[] (size_t i) const + { + return ((const T*) (data_))[i]; + } + + template + inline void fix_seq:: + pop_back () + { + static_cast (data_)[size_ - 1].~T (); + --size_; + } + + template + inline T* fix_seq:: + erase (T* i) + { + if (i != static_cast (data_) + (size_ - 1)) + erase_ (i, sizeof (T), &move_forward_); + else + { + static_cast (data_)[size_ - 1].~T (); + --size_; + } + + return i; + } + +#ifdef XSDE_EXCEPTIONS + template + inline void fix_seq:: + push_back (const T& x) + { + if (capacity_ < size_ + 1) + grow_ (0, sizeof (T), &move_); + + new (static_cast (data_) + size_) T (x); + size_++; + } + + template + inline T* fix_seq:: + insert (T* i, const T& x) + { + T* p = static_cast ( + insert_ (i, sizeof (T), &move_, &move_backward_)); + *p = x; + return p; + } + + template + inline void fix_seq:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (T), &move_); + } +#else + template + inline sequence_base::error fix_seq:: + push_back (const T& x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (T), &move_); + + if (r == error_none) + { + new (static_cast (data_) + size_) T (x); + size_++; + } + + return r; + } + + template + inline sequence_base::error fix_seq:: + insert (T* i, const T& x) + { + T* p = static_cast ( + insert_ (i, sizeof (T), &move_, &move_backward_)); + + if (p) + { + *p = x; + return error_none; + } + else + return error_no_memory; + } + + template + inline sequence_base::error fix_seq:: + insert (T* i, const T& x, T*& r) + { + T* p = static_cast ( + insert_ (i, sizeof (T), &move_, &move_backward_)); + + if (p) + { + *p = x; + r = p; + return error_none; + } + else + return error_no_memory; + } + + template + inline sequence_base::error fix_seq:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (T), &move_); + return r; + } +#endif + + // + // var_seq + // + + template + inline var_seq:: + ~var_seq () + { + clear (); + } + + template + inline size_t var_seq:: + max_size () const + { + return size_t (-1) / sizeof (T*); + } + + template + inline void var_seq:: + swap (var_seq& x) + { + swap_ (x); + } + + template + inline var_iterator var_seq:: + begin () + { + return iterator (static_cast (data_)); + } + + template + inline var_const_iterator var_seq:: + begin () const + { + return const_iterator ((const T**) (data_)); + } + + template + inline var_iterator var_seq:: + end () + { + return iterator (static_cast (data_) + size_); + } + + template + inline var_const_iterator var_seq:: + end () const + { + return const_iterator (((const T**) (data_)) + size_); + } + + template + inline T& var_seq:: + front () + { + return **static_cast (data_); + } + + template + inline const T& var_seq:: + front () const + { + // g++ 2.95 does not like static_cast here. + // + return **((const T* const*) (data_)); + } + + template + inline T& var_seq:: + back () + { + return *(static_cast (data_)[size_ - 1]); + } + + template + inline const T& var_seq:: + back () const + { + return *(((const T* const*) (data_))[size_ - 1]); + } + + template + inline T& var_seq:: + operator[] (size_t i) + { + return *(static_cast (data_)[i]); + } + + template + inline const T& var_seq:: + operator[] (size_t i) const + { + return *(((const T* const*) (data_))[i]); + } + + template + inline void var_seq:: + pop_back () + { + delete static_cast (data_)[size_ - 1]; + --size_; + } + + template + inline var_iterator var_seq:: + erase (iterator i) + { + delete *i.i_; + + if (i.i_ != static_cast (data_) + (size_ - 1)) + erase_ (i.i_, sizeof (T*), 0); + else + --size_; + + return i; + } + +#ifdef XSDE_EXCEPTIONS + template + inline void var_seq:: + push_back (T* x) + { + guard g (x); + + if (capacity_ < size_ + 1) + grow_ (0, sizeof (T*), 0); + + static_cast (data_)[size_++] = x; + + g.release (); + } + + template + inline var_iterator var_seq:: + insert (iterator i, T* x) + { + guard g (x); + T** p = static_cast (insert_ (i.i_, sizeof (T*), 0, 0)); + *p = x; + g.release (); + return iterator (p); + } + + template + inline void var_seq:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (T*), 0); + } +#else + template + inline sequence_base::error var_seq:: + push_back (T* x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (T*), 0); + + if (r == error_none) + static_cast (data_)[size_++] = x; + else + delete x; + + return r; + } + + template + inline sequence_base::error var_seq:: + insert (iterator i, T* x) + { + T** p = static_cast (insert_ (i.i_, sizeof (T*), 0, 0)); + + if (p) + { + *p = x; + return error_none; + } + else + { + delete x; + return error_no_memory; + } + } + + template + inline sequence_base::error var_seq:: + insert (iterator i, T* x, iterator& r) + { + T** p = static_cast (insert_ (i.i_, sizeof (T*), 0, 0)); + + if (p) + { + *p = x; + r.i_ = p; + return error_none; + } + else + { + delete x; + return error_no_memory; + } + } + + template + inline sequence_base::error var_seq:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (T*), 0); + return r; + } +#endif + + // + // data_seq + // + + inline data_seq:: + ~data_seq () + { + clear (); + } + + inline data_seq:: + data_seq () + : destructor_ (0) + { + } + + inline void data_seq:: + destructor (data_seq::destroy_func d) + { + destructor_ = d; + } + + inline size_t data_seq:: + max_size () const + { + return size_t (-1) / sizeof (void*); + } + + inline void data_seq:: + swap (data_seq& x) + { + swap_ (x); + } + + inline data_seq::iterator data_seq:: + begin () + { + return static_cast (data_); + } + + inline data_seq::const_iterator data_seq:: + begin () const + { + // g++ 2.95 does not like static_cast here. + // + return (const void* const*) (data_); + } + + inline data_seq::iterator data_seq:: + end () + { + return static_cast (data_) + size_; + } + + inline data_seq::const_iterator data_seq:: + end () const + { + return ((const void* const*) (data_)) + size_; + } + + inline void* data_seq:: + front () + { + return *static_cast (data_); + } + + inline const void* data_seq:: + front () const + { + return *((const void* const*) (data_)); + } + + inline void* data_seq:: + back () + { + return static_cast (data_)[size_ - 1]; + } + + inline const void* data_seq:: + back () const + { + return ((const void* const*) (data_))[size_ - 1]; + } + + inline void* data_seq:: + operator[] (size_t i) + { + return static_cast (data_)[i]; + } + + inline const void* data_seq:: + operator[] (size_t i) const + { + return ((const void* const*) (data_))[i]; + } + + inline void data_seq:: + pop_back () + { + if (destructor_) + destructor_ (static_cast (data_)[size_ - 1], size_ - 1); + --size_; + } + + inline data_seq::iterator data_seq:: + erase (iterator i) + { + if (destructor_) + destructor_ (*i, i - static_cast (data_)); + + if (i != static_cast (data_) + (size_ - 1)) + erase_ (i, sizeof (void*), 0); + else + --size_; + + return i; + } + +#ifdef XSDE_EXCEPTIONS + namespace data_seq_bits + { + struct guard + { + ~guard () { if (p_ && d_) d_ (p_, i_); } + guard (data_seq::destroy_func d, void* p, size_t i) + : d_ (d), p_ (p), i_ (i) {} + + void + release () { p_ = 0; } + + private: + data_seq::destroy_func d_; + void* p_; + size_t i_; + }; + } + + inline void data_seq:: + push_back (void* x) + { + data_seq_bits::guard g (destructor_, x, size_); + + if (capacity_ < size_ + 1) + grow_ (0, sizeof (void*), 0); + + static_cast (data_)[size_++] = x; + + g.release (); + } + + inline data_seq::iterator data_seq:: + insert (iterator i, void* x) + { + data_seq_bits::guard g ( + destructor_, x, i - static_cast (data_)); + + void** p = static_cast (insert_ (i, sizeof (void*), 0, 0)); + *p = x; + g.release (); + return p; + } + + inline void data_seq:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (void*), 0); + } +#else + inline sequence_base::error data_seq:: + push_back (void* x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (void*), 0); + + if (r == error_none) + static_cast (data_)[size_++] = x; + else + { + if (destructor_) + destructor_ (x, size_); + } + + return r; + } + + inline sequence_base::error data_seq:: + insert (iterator i, void* x) + { + size_t pos = i - static_cast (data_); + void** p = static_cast (insert_ (i, sizeof (void*), 0, 0)); + + if (p) + { + *p = x; + return error_none; + } + else + { + if (destructor_) + destructor_ (x, pos); + return error_no_memory; + } + } + + inline sequence_base::error data_seq:: + insert (iterator i, void* x, iterator& r) + { + size_t pos = i - static_cast (data_); + void** p = static_cast (insert_ (i, sizeof (void*), 0, 0)); + + if (p) + { + *p = x; + r = p; + return error_none; + } + else + { + if (destructor_) + destructor_ (x, pos); + return error_no_memory; + } + } + + inline sequence_base::error data_seq:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (void*), 0); + return r; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/hybrid/sequence.txx b/libxsde/xsde/cxx/hybrid/sequence.txx new file mode 100644 index 0000000..12faa99 --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/sequence.txx @@ -0,0 +1,133 @@ +// file : xsde/cxx/hybrid/sequence.txx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // placement new + +namespace xsde +{ + namespace cxx + { + namespace hybrid + { + // + // fix_seq + // + + template + void fix_seq:: + clear () + { + for (size_t i = 0; i < size_; ++i) + static_cast (data_)[i].~T (); + + size_ = 0; + } + +#ifdef XSDE_EXCEPTIONS + template + void fix_seq:: + move_ (void* dst, void* src, size_t n) + { + T* d = static_cast (dst); + T* s = static_cast (src); + + // The copy c-tor can throw in which case we need to destroy + // whatever objects we already copied into d. + // + size_t i = 0; + guard g (d, i); + + for (; i < n; i++) + new (d + i) T (s[i]); + + g.release (); + + for (size_t j = 0; j < n; j++) + s[j].~T (); + } +#else + template + void fix_seq:: + move_ (void* dst, void* src, size_t n) + { + T* d = static_cast (dst); + T* s = static_cast (src); + + for (size_t i = 0; i < n; i++) + { + new (d + i) T (s[i]); + s[i].~T (); + } + } +#endif + + template + void fix_seq:: + move_forward_ (void* p, size_t n) + { + // We are moving a sequence of elements one position to the left. + // The tricky part is to make sure we are in at least destructable + // state if things turn bad. We assume that there is a valid + // element at position p. + // + T* d = static_cast (p); + + for (size_t i = 0; i < n; i++) + d[i] = d[i + 1]; + + d[n].~T (); + } + +#ifdef XSDE_EXCEPTIONS + template + void fix_seq:: + move_backward_ (void* p, size_t n, size_t& size) + { + // We are moving a sequence of elements one position to the right. + // The tricky part is to make sure we are in at least destructable + // state if things turn bad. + // + T* d = static_cast (p); + T* e = d + n; + + new (e) T; + size++; + + for (size_t i = n; i > 0; i--) + d[i] = d[i - 1]; + } +#else + template + void fix_seq:: + move_backward_ (void* p, size_t n) + { + // We are moving a sequence of elements one position to the right. + // + T* d = static_cast (p); + T* e = d + n; + + new (e) T; + + for (size_t i = n; i > 0; i--) + d[i] = d[i - 1]; + } +#endif + + // + // var_seq + // + + template + void var_seq:: + clear () + { + for (size_t i = 0; i < size_; ++i) + delete static_cast (data_)[i]; + + size_ = 0; + } + } + } +} diff --git a/libxsde/xsde/cxx/hybrid/xml-schema.hxx b/libxsde/xsde/cxx/hybrid/xml-schema.hxx new file mode 100644 index 0000000..d4b7cdb --- /dev/null +++ b/libxsde/xsde/cxx/hybrid/xml-schema.hxx @@ -0,0 +1,23 @@ +// file : xsde/cxx/hybrid/xml-schema.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_HYBRID_XML_SCHEMA_HXX +#define XSDE_CXX_HYBRID_XML_SCHEMA_HXX + +#include +#include + +#ifdef XSDE_STL +# include +# include +#else +# include +# include +#endif + +#include +#include + +#endif // XSDE_CXX_HYBRID_XML_SCHEMA_HXX diff --git a/libxsde/xsde/cxx/parser/context.cxx b/libxsde/xsde/cxx/parser/context.cxx new file mode 100644 index 0000000..264ffd5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/context.cxx @@ -0,0 +1,18 @@ +// file : xsde/cxx/parser/context.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + } + } +} diff --git a/libxsde/xsde/cxx/parser/context.hxx b/libxsde/xsde/cxx/parser/context.hxx new file mode 100644 index 0000000..2b79be9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/context.hxx @@ -0,0 +1,139 @@ +// file : xsde/cxx/parser/context.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_CONTEXT_HXX +#define XSDE_CXX_PARSER_CONTEXT_HXX + +#include + +#include // size_t + +#include + +#ifndef XSDE_EXCEPTIONS +# include +#endif + +#ifdef XSDE_PARSER_VALIDATION +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace parser + { + struct parser_base; + + struct parser_state + { + parser_state (); + + // Depth is maintained only when we don't have a parser for a + // document fragment or if we are handling a wildcard in which + // case the any flag should be set. + // + parser_base* parser_; + size_t depth_; + bool any_; + }; + + class context + { + public: + context (XML_Parser xml_parser); + + public: + XML_Parser + xml_parser (); + + // Error handling via codes. + // + public: + + // Application error. + // +#ifndef XSDE_EXCEPTIONS + public: + int + app_error () const; + + void + app_error (int); +#endif + + // Schema error. + // +#ifdef XSDE_PARSER_VALIDATION + public: + typedef cxx::schema_error::value schema_error_t; + + schema_error_t + schema_error () const; + + void + schema_error (schema_error_t); +#endif + + // System error. + // +#ifndef XSDE_EXCEPTIONS + public: + typedef cxx::sys_error::value sys_error_t; + + sys_error_t + sys_error () const; + + void + sys_error (sys_error_t); +#endif + + // Implementation details. + // +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + public: + enum error_type_t + { + error_none = 0, + error_app, + error_schema, + error_sys + }; + + error_type_t + error_type () const; + + protected: + error_type_t error_type_; + + union + { +#ifndef XSDE_EXCEPTIONS + int app; +#endif +#ifdef XSDE_PARSER_VALIDATION + schema_error_t schema; +#endif +#ifndef XSDE_EXCEPTIONS + sys_error_t sys; +#endif + } error_code_; + +#endif // XSDE_PARSER_VALIDATION || !XSDE_EXCEPTIONS + + public: + parser_state current_; + + protected: + XML_Parser xml_parser_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_CONTEXT_HXX diff --git a/libxsde/xsde/cxx/parser/context.ixx b/libxsde/xsde/cxx/parser/context.ixx new file mode 100644 index 0000000..00093d6 --- /dev/null +++ b/libxsde/xsde/cxx/parser/context.ixx @@ -0,0 +1,91 @@ +// file : xsde/cxx/parser/context.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // parser_state + // + inline parser_state:: + parser_state () + : parser_ (0), depth_ (0), any_ (false) + { + } + + // context + // + inline context:: + context (XML_Parser xml_parser) + : xml_parser_ (xml_parser) + { +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + error_type_ = error_none; +#endif + } + + inline XML_Parser context:: + xml_parser () + { + return xml_parser_; + } + + // + // +#ifndef XSDE_EXCEPTIONS + inline int context:: + app_error () const + { + return error_code_.app; + } + + inline void context:: + app_error (int e) + { + error_type_ = error_app; + error_code_.app = e; + } + + inline void context:: + sys_error (sys_error_t e) + { + error_type_ = error_sys; + error_code_.sys = e; + } + + inline context::sys_error_t context:: + sys_error () const + { + return error_code_.sys; + } +#endif + +#ifdef XSDE_PARSER_VALIDATION + inline context::schema_error_t context:: + schema_error () const + { + return error_code_.schema; + } + + inline void context:: + schema_error (schema_error_t e) + { + error_type_ = error_schema; + error_code_.schema = e; + } +#endif + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + inline context::error_type_t context:: + error_type () const + { + return error_type_; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/parser/elements.cxx b/libxsde/xsde/cxx/parser/elements.cxx new file mode 100644 index 0000000..4273ab8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/elements.cxx @@ -0,0 +1,201 @@ +// file : xsde/cxx/parser/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // parser_base + // + parser_base:: + ~parser_base () + { + } + + void parser_base:: + pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->pre (); +#endif + } + + void parser_base:: + _pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_pre (); +#endif + } + + void parser_base:: + _post () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_post (); +#endif + } + +#ifdef XSDE_REUSE_STYLE_TIEIN + +#ifdef XSDE_POLYMORPHIC + void parser_base:: + _start_any_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (impl_) + impl_->_start_any_element (ns, name, type); + } +#else + void parser_base:: + _start_any_element (const ro_string& ns, + const ro_string& name) + { + if (impl_) + impl_->_start_any_element (ns, name); + } +#endif + + void parser_base:: + _end_any_element (const ro_string& ns, + const ro_string& name) + { + if (impl_) + impl_->_end_any_element (ns, name); + } + + void parser_base:: + _any_attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + if (impl_) + impl_->_any_attribute (ns, name, value); + } + + void parser_base:: + _any_characters (const ro_string& s) + { + if (impl_) + impl_->_any_characters (s); + } +#else // !XSDE_REUSE_STYLE_TIEIN + +#ifdef XSDE_POLYMORPHIC + void parser_base:: + _start_any_element (const ro_string&, + const ro_string&, + const char*) + { + } +#else + void parser_base:: + _start_any_element (const ro_string&, + const ro_string&) + { + } +#endif + + void parser_base:: + _end_any_element (const ro_string&, + const ro_string&) + { + } + + void parser_base:: + _any_attribute (const ro_string&, + const ro_string&, + const ro_string&) + { + } + + void parser_base:: + _any_characters (const ro_string&) + { + } +#endif // XSDE_REUSE_STYLE_TIEIN + + + void parser_base:: + _pre_impl (context& c) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + assert (parent_ == 0); + + // Set the parent_ pointers in the tied-in implementations. + // + _set_parent_chain (); +#endif + context_ = &c; + + previous_ = c.current_; + + c.current_.parser_ = this; + c.current_.depth_ = 0; + c.current_.any_ = false; + + _pre (); + } + + void parser_base:: + _post_impl () + { +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (!context_->error_type ()) +#endif + _post (); + + context_->current_ = previous_; + context_ = 0; + } + +#ifdef XSDE_POLYMORPHIC + const char* parser_base:: + _dynamic_type () const + { + return 0; + } +#endif + + void parser_base:: + _reset () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_reset (); +#endif + +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif + context_ = 0; + + previous_.parser_ = 0; + previous_.depth_ = 0; + previous_.any_ = false; + } + +#if defined (XSDE_REUSE_STYLE_TIEIN) && !defined (XSDE_EXCEPTIONS) + const parser_base* parser_base:: + _ultimate_impl () const + { + const parser_base* p = impl_; + for (; p->impl_ != 0; p = p->impl_) /*noop*/; + return p; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/parser/elements.hxx b/libxsde/xsde/cxx/parser/elements.hxx new file mode 100644 index 0000000..5ce1e09 --- /dev/null +++ b/libxsde/xsde/cxx/parser/elements.hxx @@ -0,0 +1,248 @@ +// file : xsde/cxx/parser/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_ELEMENTS_HXX +#define XSDE_CXX_PARSER_ELEMENTS_HXX + +#include +#include + +#ifdef XSDE_PARSER_VALIDATION +# include +#endif + +#ifndef XSDE_EXCEPTIONS +# include +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // pre() and post() are overridable pre/post callbacks, i.e., the + // derived parser can override them without calling the base version. + // _pre() and _post() are not overridable pre/post callbacks in the + // sense that the derived parser may override them but has to call + // the base version. The call sequence is as shown below: + // + // pre () + // _pre () + // _post () + // post () + // + struct parser_base + { + virtual + ~parser_base (); + + parser_base (); + +#ifdef XSDE_REUSE_STYLE_TIEIN + parser_base (parser_base* impl, void*); +#endif + + public: + virtual void + pre (); + + virtual void + _pre (); + + // The type argument is a type name and namespace from the + // xsi:type attribute in the form " " with + // the space and namespace part absent if the type does not + // have a namespace or 0 if xsi:type is not present. + // +#ifdef XSDE_POLYMORPHIC + virtual void + _start_element (const ro_string& ns, + const ro_string& name, + const char* type) = 0; +#else + virtual void + _start_element (const ro_string& ns, + const ro_string& name) = 0; +#endif + + virtual void + _end_element (const ro_string& ns, + const ro_string& name) = 0; + + virtual void + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) = 0; + + virtual void + _characters (const ro_string&) = 0; + + virtual void + _post (); + + // The post() signature varies depending on the parser return + // type. + // + + public: + // The following functions are called when wildcard content is + // encountered. Override them to handle mixed content models, + // any/anyAttribute, and anyType/anySimpleType. By default + // these functions do nothing. + // +#ifdef XSDE_POLYMORPHIC + virtual void + _start_any_element (const ro_string& ns, + const ro_string& name, + const char* type); +#else + virtual void + _start_any_element (const ro_string& ns, + const ro_string& name); +#endif + + virtual void + _end_any_element (const ro_string& ns, + const ro_string& name); + + virtual void + _any_attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value); + + virtual void + _any_characters (const ro_string&); + + public: + // Implementation callbacks for _pre and _post. The _pre and _post + // callbacks should never be called directly. Instead, the *_impl + // versions should be used. By default _pre_impl and _post_impl + // simply call _pre and _post respectively. + // + virtual void + _pre_impl (context&); + + virtual void + _post_impl (); + +#ifdef XSDE_POLYMORPHIC + public: + // Dynamic type in the form " " with + // the space and namespace part absent if the type does + // not have a namespace. + // + virtual const char* + _dynamic_type () const; +#endif + + public: + context& + _context (); + + // Reset the parser state after an error. + // + virtual void + _reset (); + + // Error handling via codes. If the error is set while parser + // is in the context, the error is set in the context, instead + // of the parser. Since pre() and post() calls are not in + // context, the parser stores application and system errors + // locally for this case. + // + +#ifndef XSDE_EXCEPTIONS + public: + error + _error () const; + + // Set application error. + // + void + _app_error (int); + + int + _app_error () const; +#endif + + // Schema error. + // +#ifdef XSDE_PARSER_VALIDATION + public: + void + _schema_error (context::schema_error_t); +#endif + + // System error. + // +#ifndef XSDE_EXCEPTIONS + public: + context::sys_error_t + _sys_error () const; + + void + _sys_error (context::sys_error_t); +#endif + + // Implementation. + // + +#ifndef XSDE_EXCEPTIONS + public: + enum error_type_t + { + error_none = 0, + error_app, + error_sys + }; + + error_type_t + _error_type () const; + + void + _copy_error (context&) const; + + private: + error_type_t error_type_; + + union + { + int app; + context::sys_error_t sys; + } error_code_; +#endif + + protected: + bool resetting_; + context* context_; + +#ifdef XSDE_REUSE_STYLE_TIEIN + protected: + parser_base* parent_; + parser_base* impl_; + + void + _set_parent_chain (); + +#ifndef XSDE_EXCEPTIONS + const parser_base* + _ultimate_impl () const; +#endif +#endif + + protected: + parser_state previous_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_ELEMENTS_HXX diff --git a/libxsde/xsde/cxx/parser/elements.ixx b/libxsde/xsde/cxx/parser/elements.ixx new file mode 100644 index 0000000..ef47209 --- /dev/null +++ b/libxsde/xsde/cxx/parser/elements.ixx @@ -0,0 +1,221 @@ +// file : xsde/cxx/parser/elements.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + inline parser_base:: + parser_base () + : resetting_ (false), context_ (0) + { +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + parent_ = 0; + impl_ = 0; +#endif + } + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline parser_base:: + parser_base (parser_base* impl, void*) + : resetting_ (false), context_ (0) + { +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif + parent_ = 0; + impl_ = impl; + } +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline void parser_base:: + _set_parent_chain () + { + if (impl_ && impl_->parent_ == 0) + { + for (parser_base* p = impl_; p != 0; p = p->impl_) + p->parent_ = this; + } + } +#endif + + inline context& parser_base:: + _context () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + return *(parent_ ? parent_->context_ : context_); +#else + return *context_; +#endif + } + + // Error handling. + // +#ifndef XSDE_EXCEPTIONS + inline error parser_base:: + _error () const + { + // Unlike context, which is stored in the top-level + // parser, error state is stored in the "bottom-level" + // implementation. It is done this way since the error + // handling mechanism can be used in constructors which + // would otherwise require passing the pointer to parent + // parser to each implementation's c-tor. + // +#ifdef XSDE_REUSE_STYLE_TIEIN + const parser_base* p = !impl_ ? this : _ultimate_impl (); +#else + const parser_base* p = this; +#endif + switch (p->error_type_) + { + case error_sys: + { + return error (p->error_code_.sys); + } + case error_app: + { + return error (p->error_code_.app, 0, 0); + } + default: + { + return error (); + } + } + } + + inline void parser_base:: + _app_error (int e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + parser_base* p = parent_ ? parent_ : this; +#else + parser_base* p = this; +#endif + + if (p->context_ != 0) + { + p->context_->app_error (e); + } + else + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (!impl_) + p = this; + else + for (p = impl_; p->impl_ != 0; p = p->impl_) /*noop*/ ; +#endif + p->error_type_ = error_app; + p->error_code_.app = e; + } + } + + inline int parser_base:: + _app_error () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const parser_base* p = !impl_ ? this : _ultimate_impl (); +#else + const parser_base* p = this; +#endif + return p->error_code_.app; + } + + inline void parser_base:: + _sys_error (context::sys_error_t e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + parser_base* p = parent_ ? parent_ : this; +#else + parser_base* p = this; +#endif + if (p->context_ != 0) + { + p->context_->sys_error (e); + } + else + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (!impl_) + p = this; + else + for (p = impl_; p->impl_ != 0; p = p->impl_) /*noop*/; +#endif + p->error_type_ = error_sys; + p->error_code_.sys = e; + } + } + + inline context::sys_error_t parser_base:: + _sys_error () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const parser_base* p = !impl_ ? this : _ultimate_impl (); +#else + const parser_base* p = this; +#endif + return p->error_code_.sys; + } + + inline parser_base::error_type_t parser_base:: + _error_type () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const parser_base* p = !impl_ ? this : _ultimate_impl (); +#else + const parser_base* p = this; +#endif + return p->error_type_; + } + + inline void parser_base:: + _copy_error (context& ctx) const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const parser_base* p = !impl_ ? this : _ultimate_impl (); +#else + const parser_base* p = this; +#endif + + switch (p->error_type_) + { + case error_app: + { + ctx.app_error (p->error_code_.app); + break; + } + case error_sys: + { + ctx.sys_error (p->error_code_.sys); + break; + } + default: + break; + } + } +#endif // XSDE_EXCEPTIONS + +#ifdef XSDE_PARSER_VALIDATION + inline void parser_base:: + _schema_error (context::schema_error_t e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + parser_base* p = parent_ ? parent_ : this; +#else + parser_base* p = this; +#endif + p->context_->schema_error (e); + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/parser/error.cxx b/libxsde/xsde/cxx/parser/error.cxx new file mode 100644 index 0000000..94e2534 --- /dev/null +++ b/libxsde/xsde/cxx/parser/error.cxx @@ -0,0 +1,20 @@ +// file : xsde/cxx/parser/error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + void error:: + true_ () + { + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/error.hxx b/libxsde/xsde/cxx/parser/error.hxx new file mode 100644 index 0000000..47ca489 --- /dev/null +++ b/libxsde/xsde/cxx/parser/error.hxx @@ -0,0 +1,135 @@ +// file : xsde/cxx/parser/error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_ERROR_HXX +#define XSDE_CXX_PARSER_ERROR_HXX + +#include +#include + +#include + +#ifdef XSDE_PARSER_VALIDATION +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace parser + { + using expat::xml_error; + + // This type is only used when C++ exceptions are not used. + // + struct error + { + enum error_type + { + none, + sys, + xml, + schema, + app + }; + + public: + error_type + type () const; + + + // Line and column are only available for xml, schema, and + // app errors. + // + unsigned long + line () const; + + unsigned long + column () const; + + + // Returns true if there is an error so that you can write + // if (p.error ()) or if (error e = p.error ()). + // + typedef void (error::*bool_convertible) (); + operator bool_convertible () const; + + + // sys + // + public: + error (sys_error); + + sys_error + sys_code () const; + + const char* + sys_text () const; + + + // xml + // + public: + error (xml_error, unsigned long line, unsigned long column); + + xml_error + xml_code () const; + + const char* + xml_text () const; + + + // schema + // +#ifdef XSDE_PARSER_VALIDATION + public: + error (schema_error::value, unsigned long line, unsigned long column); + + schema_error + schema_code () const; + + const char* + schema_text () const; +#endif + + // app + // + public: + error (int app_code, unsigned long line, unsigned long column); + + int + app_code () const; + + + public: + error (); + + private: + void + true_ (); + + private: + error_type type_; + unsigned long line_; + unsigned long column_; + + union + { + sys_error::value sys; + xml_error xml; +#ifdef XSDE_PARSER_VALIDATION + schema_error::value schema; +#endif + int app; + } code_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_ERROR_HXX diff --git a/libxsde/xsde/cxx/parser/error.ixx b/libxsde/xsde/cxx/parser/error.ixx new file mode 100644 index 0000000..dbb57bb --- /dev/null +++ b/libxsde/xsde/cxx/parser/error.ixx @@ -0,0 +1,143 @@ +// file : xsde/cxx/parser/error.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + inline + error::error_type error:: + type () const + { + return type_; + } + + inline + unsigned long error:: + line () const + { + return line_; + } + + inline + unsigned long error:: + column () const + { + return column_; + } + + inline + error:: + operator error::bool_convertible () const + { + return type_ != none ? &error::true_ : 0; + } + + // sys + // + + inline + error:: + error (sys_error e) + : type_ (sys), line_ (0), column_ (0) + { + code_.sys = e; + } + + inline + sys_error error:: + sys_code () const + { + return code_.sys; + } + + inline + const char* error:: + sys_text () const + { + return sys_error::text (code_.sys); + } + + // xml + // + + inline + error:: + error (xml_error e, unsigned long l, unsigned long c) + : type_ (xml), line_ (l), column_ (c) + { + code_.xml = e; + } + + inline + xml_error error:: + xml_code () const + { + return code_.xml; + } + + inline + const char* error:: + xml_text () const + { + return expat::xml_error_text (code_.xml); + } + + // schema + // + +#ifdef XSDE_PARSER_VALIDATION + inline + error:: + error (schema_error::value e, unsigned long l, unsigned long c) + : type_ (schema), line_ (l), column_ (c) + { + code_.schema = e; + } + + inline + schema_error error:: + schema_code () const + { + return code_.schema; + } + + inline + const char* error:: + schema_text () const + { + return schema_error::text (code_.schema); + } +#endif + + // app + // + + inline + error:: + error (int e, unsigned long l, unsigned long c) + : type_ (app), line_ (l), column_ (c) + { + code_.app = e; + } + + inline + int error:: + app_code () const + { + return code_.app; + } + + inline + error:: + error () + : type_ (none) + { + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/exceptions.cxx b/libxsde/xsde/cxx/parser/exceptions.cxx new file mode 100644 index 0000000..0046266 --- /dev/null +++ b/libxsde/xsde/cxx/parser/exceptions.cxx @@ -0,0 +1,64 @@ +// file : xsde/cxx/parser/exceptions.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // exception + // + +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream& os, const exception& e) + { + return os << e.text (); + } +#endif + + + // xml + // + const char* xml:: + text () const + { + return expat::xml_error_text (code_); + } + + const char* xml:: + what () const throw () + { + return "xml error"; + } + + + // schema + // +#ifdef XSDE_PARSER_VALIDATION + const char* schema:: + text () const + { + return schema_error::text (code_); + } + + const char* schema:: + what () const throw () + { + return "schema error"; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/parser/exceptions.hxx b/libxsde/xsde/cxx/parser/exceptions.hxx new file mode 100644 index 0000000..d02eeb3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/exceptions.hxx @@ -0,0 +1,103 @@ +// file : xsde/cxx/parser/exceptions.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_EXCEPTIONS_HXX +#define XSDE_CXX_PARSER_EXCEPTIONS_HXX + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include // xsde::cxx::exception + +#ifdef XSDE_PARSER_VALIDATION +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // exception + // + struct exception: xsde::cxx::exception + { + exception (unsigned long line, unsigned long column); + + unsigned long + line () const; + + unsigned long + column () const; + + virtual const char* + text () const = 0; + + private: + unsigned long line_; + unsigned long column_; + }; + +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream&, const exception&); +#endif + + + // xml + // + using expat::xml_error; + + struct xml: exception + { + xml (xml_error, unsigned long line, unsigned long column); + + xml_error + code () const; + + virtual const char* + text () const; + + virtual const char* + what () const throw (); + + private: + xml_error code_; + }; + + + // schema + // +#ifdef XSDE_PARSER_VALIDATION + struct schema: exception + { + schema (schema_error, unsigned long line, unsigned long column); + + schema_error + code () const; + + virtual const char* + text () const; + + virtual const char* + what () const throw (); + + private: + schema_error code_; + }; +#endif + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_EXCEPTIONS_HXX diff --git a/libxsde/xsde/cxx/parser/exceptions.ixx b/libxsde/xsde/cxx/parser/exceptions.ixx new file mode 100644 index 0000000..77ca9e5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/exceptions.ixx @@ -0,0 +1,66 @@ +// file : xsde/cxx/parser/exceptions.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // exception + // + inline exception:: + exception (unsigned long line, unsigned long column) + : line_ (line), column_ (column) + { + } + + inline unsigned long exception:: + line () const + { + return line_; + } + + inline unsigned long exception:: + column () const + { + return column_; + } + + + // xml + // + inline xml:: + xml (xml_error code, unsigned long line, unsigned long column) + : exception (line, column), code_ (code) + { + } + + inline xml_error xml:: + code () const + { + return code_; + } + + + // schema + // +#ifdef XSDE_PARSER_VALIDATION + inline schema:: + schema (schema_error code, unsigned long line, unsigned long column) + : exception (line, column), code_ (code) + { + } + + inline schema_error schema:: + code () const + { + return code_; + } +#endif + } + } +} + diff --git a/libxsde/xsde/cxx/parser/expat/document.cxx b/libxsde/xsde/cxx/parser/expat/document.cxx new file mode 100644 index 0000000..0e30a2a --- /dev/null +++ b/libxsde/xsde/cxx/parser/expat/document.cxx @@ -0,0 +1,1044 @@ +// file : xsde/cxx/parser/expat/document.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include // strchr, strlen + +#ifdef XSDE_EXCEPTIONS +# include // std::bad_alloc +#endif + +#ifdef XSDE_IOSTREAM +# include +# include +#endif + +#ifdef XSDE_EXCEPTIONS +# include +#endif + +#ifdef XSDE_POLYMORPHIC +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace expat + { +#ifdef XSDE_POLYMORPHIC + static substitution_map_init substitution_map_init_; +#endif + + // document_pimpl + // + + document_pimpl:: + ~document_pimpl () + { + // Prevents auto-generation of this dtor. + } + +#ifdef XSDE_STL + + document_pimpl:: +#ifdef XSDE_POLYMORPHIC + document_pimpl (parser_base& p, const std::string& n, bool poly) +#else + document_pimpl (parser_base& p, const std::string& n) +#endif + : first_ (true), xml_parser_ (0), context_ (0), parser_ (&p) + { +#ifdef XSDE_POLYMORPHIC + polymorphic_ = poly; +#endif + init_root_name (0, n.c_str ()); + } + + document_pimpl:: +#ifdef XSDE_POLYMORPHIC + document_pimpl (parser_base& p, + const std::string& ns, + const std::string& n, + bool poly) +#else + document_pimpl (parser_base& p, + const std::string& ns, + const std::string& n) +#endif + : first_ (true), xml_parser_ (0), context_ (0), parser_ (&p) + { +#ifdef XSDE_POLYMORPHIC + polymorphic_ = poly; +#endif + init_root_name (ns.c_str (), n.c_str ()); + } + +#endif // XSDE_STL + + document_pimpl:: +#ifdef XSDE_POLYMORPHIC + document_pimpl (parser_base& p, const char* n, bool poly) +#else + document_pimpl (parser_base& p, const char* n) +#endif + : first_ (true), xml_parser_ (0), context_ (0), parser_ (&p) + { +#ifdef XSDE_POLYMORPHIC + polymorphic_ = poly; +#endif + init_root_name (0, n); + } + + document_pimpl:: +#ifdef XSDE_POLYMORPHIC + document_pimpl (parser_base& p, + const char* ns, + const char* n, + bool poly) +#else + document_pimpl (parser_base& p, const char* ns, const char* n) +#endif + : first_ (true), xml_parser_ (0), context_ (0), parser_ (&p) + { +#ifdef XSDE_POLYMORPHIC + polymorphic_ = poly; +#endif + init_root_name (ns, n); + } + + document_pimpl:: + document_pimpl () + : first_ (true), xml_parser_ (0), context_ (0), parser_ (0) + { +#ifdef XSDE_POLYMORPHIC + polymorphic_ = false; +#endif + } + +#ifdef XSDE_POLYMORPHIC + document_pimpl:: + document_pimpl (const char* n) + : first_ (true), xml_parser_ (0), context_ (0), parser_ (0), + polymorphic_ (true) + { + init_root_name (0, n); + } + + document_pimpl:: + document_pimpl (const char* ns, const char* n) + : first_ (true), xml_parser_ (0), context_ (0), parser_ (0), + polymorphic_ (true) + { + init_root_name (ns, n); + } + +#ifdef XSDE_STL + document_pimpl:: + document_pimpl (const std::string& n) + : first_ (true), xml_parser_ (0), context_ (0), parser_ (0), + polymorphic_ (true) + { + init_root_name (0, n.c_str ()); + } + + document_pimpl:: + document_pimpl (const std::string& ns, const std::string& n) + : first_ (true), xml_parser_ (0), context_ (0), parser_ (0), + polymorphic_ (true) + { + init_root_name (ns.c_str (), n.c_str ()); + } +#endif // XSDE_STL +#endif // XSDE_POLYMORPHIC + + void document_pimpl:: + init_root_name (const char* ns, const char* name) + { +#ifdef XSDE_EXCEPTIONS + root_ns_.assign (ns ? ns : ""); + root_name_.assign (name); +#else + if (root_ns_.assign (ns ? ns : "") || root_name_.assign (name)) + error_ = error (sys_error::no_memory); +#endif + } + + // + // + parser_base* document_pimpl:: +#ifdef XSDE_POLYMORPHIC + start_root_element (const ro_string& ns, + const ro_string& name, + const char*) +#else + start_root_element (const ro_string& ns, const ro_string& name) +#endif + { + if (root_name_ == name && root_ns_ == ns) + { + return parser_; + } + else + { +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error (schema_error::unexpected_element); +#endif + return 0; + } + } + + void document_pimpl:: + end_root_element (const ro_string&, const ro_string&, parser_base*) + { + } + + void document_pimpl:: + reset () + { +#ifndef XSDE_EXCEPTIONS + error_ = error (); +#endif + first_ = true; + + if (parser_) + parser_->_reset (); + } + + // file + // + +#ifdef XSDE_IOSTREAM + void document_pimpl:: + parse (const char* file) + { + std::ifstream ifs; + +#ifdef XSDE_EXCEPTIONS + ifs.exceptions (std::ifstream::badbit | std::ifstream::failbit); +#endif + + ifs.open (file, std::ifstream::in | std::ifstream::binary); + +#ifndef XSDE_EXCEPTIONS + if (ifs.fail ()) + { + error_ = error (sys_error::open_failed); + return; + } +#endif + parse (ifs); + } + +#ifdef XSDE_STL + void document_pimpl:: + parse (const std::string& file) + { + parse (file.c_str ()); + } +#endif + + // istream + // + +#ifdef XSDE_EXCEPTIONS + namespace bits + { + struct stream_exception_controller + { + ~stream_exception_controller () + { + std::istream::iostate s = is_.rdstate (); + s &= ~std::istream::failbit; + + // If our error state (sans failbit) intersects with the + // exception state then that means we have an active + // exception and changing error/exception state will + // cause another to be thrown. + // + if (!(old_state_ & s)) + { + // Clear failbit if it was caused by eof. + // + if (is_.fail () && is_.eof ()) + is_.clear (s); + + is_.exceptions (old_state_); + } + } + + stream_exception_controller (std::istream& is) + : is_ (is), old_state_ (is_.exceptions ()) + { + is_.exceptions (old_state_ & ~std::istream::failbit); + } + + private: + stream_exception_controller (const stream_exception_controller&); + + stream_exception_controller& + operator= (const stream_exception_controller&); + + private: + std::istream& is_; + std::istream::iostate old_state_; + }; + } +#endif + + void document_pimpl:: + parse (std::istream& is) + { +#ifdef XSDE_EXCEPTIONS + // Temporarily unset the exception failbit. Also clear the + // fail bit when we reset the old state if it was caused + // by eof. + // + bits::stream_exception_controller sec (is); +#endif + + char buf[4096]; // Page size. + + do + { + is.read (buf, sizeof (buf)); + +#ifndef XSDE_EXCEPTIONS + if (is.bad () || (is.fail () && !is.eof ())) + { + error_ = error (sys_error::read_failed); + break; + } +#endif + parse (buf, is.gcount (), is.eof ()); + +#ifndef XSDE_EXCEPTIONS + if (error_) + break; +#endif + } while (!is.eof ()); + } +#endif // XSDE_IOSTREAM + + + void document_pimpl:: + parse (const void* data, size_t size, bool last) + { + // First call. + // + if (first_) + { + if (auto_xml_parser_ == 0) + { + auto_xml_parser_ = XML_ParserCreateNS (0, XML_Char (' ')); + + if (auto_xml_parser_ == 0) + { +#ifdef XSDE_EXCEPTIONS + throw std::bad_alloc (); +#else + error_ = error (sys_error::no_memory); + return; +#endif + } + } + else + XML_ParserReset (auto_xml_parser_, 0); + + parse_begin (auto_xml_parser_); + first_ = false; + } + + + if (XML_Parse (xml_parser_, + static_cast (data), + static_cast (size), + last) == XML_STATUS_ERROR || + last) + { + first_ = true; + parse_end (); + } + } + + + // XML_Parser + // + + void document_pimpl:: + parse_begin (XML_Parser parser) + { + context_ = context (parser); + + xml_parser_ = parser; + set (); + } + + void document_pimpl:: + parse_end () + { + XML_Error e (XML_GetErrorCode (xml_parser_)); + + if (e == XML_ERROR_NONE) + { + clear (); + xml_parser_ = 0; + } + else + { + unsigned long l = XML_GetCurrentLineNumber (xml_parser_); + unsigned long c = XML_GetCurrentColumnNumber (xml_parser_); + + clear (); + xml_parser_ = 0; + + // See if the parser was aborted. + // + if (e == XML_ERROR_ABORTED) + { + // Got to be either a system, schema, or application + // level error. + // +#if defined(XSDE_PARSER_VALIDATION) || !defined (XSDE_EXCEPTIONS) + switch (context_.error_type ()) + { +#ifndef XSDE_EXCEPTIONS + case context::error_sys: + { + error_ = error (context_.sys_error ()); + break; + } +#endif +#ifdef XSDE_PARSER_VALIDATION + case context::error_schema: + { +#ifdef XSDE_EXCEPTIONS + throw schema (context_.schema_error (), l, c); +#else + error_ = error (context_.schema_error (), l, c); + break; +#endif + } +#endif +#ifndef XSDE_EXCEPTIONS + case context::error_app: + { + error_ = error (context_.app_error (), l, c); + break; + } +#endif + default: + { + // Someone aborted the parser without setting an + // error. Oh well, let them sort this one out. + // + break; + } + } +#endif // XSDE_PARSER_VALIDATION || !XSDE_EXCEPTIONS + } + else if (e == XML_ERROR_NO_MEMORY) + { +#ifdef XSDE_EXCEPTIONS + throw std::bad_alloc (); +#else + error_ = error (sys_error::no_memory); +#endif + } + else + { +#ifdef XSDE_EXCEPTIONS + throw xml (e, l, c); +#else + error_ = error (e, l, c); +#endif + } + } + } + + + // + // + void document_pimpl:: + set () + { + assert (xml_parser_ != 0); + + XML_SetUserData(xml_parser_, this); + XML_SetStartElementHandler (xml_parser_, &start_element); + XML_SetEndElementHandler (xml_parser_, &end_element); + XML_SetCharacterDataHandler (xml_parser_, &characters); + +#ifdef XSDE_POLYMORPHIC + if (polymorphic_) + XML_SetNamespaceDeclHandler ( + xml_parser_, &start_namespace_decl, &end_namespace_decl); +#endif + } + + void document_pimpl:: + clear () + { + assert (xml_parser_ != 0); + + XML_SetUserData (xml_parser_, 0); + XML_SetStartElementHandler (xml_parser_, 0); + XML_SetEndElementHandler (xml_parser_, 0); + XML_SetCharacterDataHandler (xml_parser_, 0); + +#ifdef XSDE_POLYMORPHIC + if (polymorphic_) + XML_SetNamespaceDeclHandler (xml_parser_, 0, 0); +#endif + } + + + // Expat thunks. + // + + void XMLCALL document_pimpl:: + start_element (void* p, const XML_Char* name, const XML_Char** ats) + { + document_pimpl& doc = *reinterpret_cast (p); + doc.start_element_ (name, ats); + } + + void XMLCALL document_pimpl:: + end_element (void* p, const XML_Char* name) + { + document_pimpl& doc = *reinterpret_cast (p); + doc.end_element_ (name); + } + + void XMLCALL document_pimpl:: + characters (void* p, const XML_Char* s, int n) + { + document_pimpl& doc = *reinterpret_cast (p); + doc.characters_ (s, static_cast (n)); + } + +#ifdef XSDE_POLYMORPHIC + void XMLCALL document_pimpl:: + start_namespace_decl (void* p, + const XML_Char* prefix, + const XML_Char* ns) + { + document_pimpl& doc = *reinterpret_cast (p); + doc.start_namespace_decl_ (prefix, ns); + } + + void XMLCALL document_pimpl:: + end_namespace_decl (void* p, const XML_Char* prefix) + { + document_pimpl& doc = *reinterpret_cast (p); + doc.end_namespace_decl_ (prefix); + } +#endif // XSDE_POLYMORPHIC + + namespace bits + { + inline void + split_name (const XML_Char* s, + const char*& ns, size_t& ns_s, + const char*& name, size_t& name_s) + { + const char* p = strchr (s, ' '); + + if (p) + { + ns = s; + ns_s = p - s; + name = p + 1; + } + else + { + ns = s; + ns_s = 0; + name = s; + } + + name_s = strlen (name); + } + } + + void document_pimpl:: + start_element_ (const XML_Char* ns_name, const XML_Char** atts) + { + // Current Expat (2.0.0) has a (mis)-feature of a possibility of + // calling callbacks even after the non-resumable XML_StopParser + // call. The following code accounts for this. + // + { + XML_ParsingStatus s; + XML_GetParsingStatus (xml_parser_, &s); + if (s.parsing == XML_FINISHED) + return; + } + + const char* ns_p; + const char* name_p; + size_t ns_s, name_s; + + bits::split_name (ns_name, ns_p, ns_s, name_p, name_s); + + parser_state& cur = context_.current_; + + { + const ro_string ns (ns_p, ns_s); + const ro_string name (name_p, name_s); + +#ifdef XSDE_POLYMORPHIC + const char* type = 0; + string type_holder; + + if (polymorphic_) + { + // Search for the xsi:type attribute. + // + const XML_Char** p = atts; // VC8 can't handle p (atts) + for (; *p != 0; p += 2) + { + bits::split_name (*p, ns_p, ns_s, name_p, name_s); + const ro_string ns (ns_p, ns_s), name (name_p, name_s); + + if (name.compare ("type", 4) == 0 && + ns.compare ( + "http://www.w3.org/2001/XMLSchema-instance", 41) == 0) + break; + } + + if (*p != 0) + { + bool valid = true; + + // @@ Need proper QName validation. + // + // Get the qualified type name and try to resolve it. + // + ro_string qn (*(p + 1)); + + ro_string tp, tn; + size_t pos = qn.find (':'); + + if (pos != ro_string::npos) + { + tp.assign (qn.data (), pos); + tn.assign (qn.data () + pos + 1); + + if (tp.empty ()) + { +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error (schema_error::invalid_xsi_type); +#endif + valid = false; + } + } + else + tn.assign (qn.data (), qn.size ()); + + if (valid && tn.empty ()) + { +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error (schema_error::invalid_xsi_type); +#endif + valid = false; + } + + if (valid) + { + // Search our namespace declaration stack. Note that + // we need to do this even if prefix is empty. + // + const char* tns = 0; + + for (size_t i = 0; i < prefixes_.size (); ++i) + { + if (tp == prefixes_[i]) + { +#ifdef XSDE_STL + tns = prefix_namespaces_[i].c_str (); +#else + tns = prefix_namespaces_[i]; +#endif + break; + } + } + + if (!tp.empty () && tns == 0) + { + // The 'xml' prefix requires special handling. + // + if (tp.compare ("xml", 3) == 0) + tns = "http://www.w3.org/XML/1998/namespace"; + else + { +#ifdef XSDE_PARSER_VALIDATION + context_.schema_error (schema_error::invalid_xsi_type); +#endif + valid = false; + } + } + + // Construct the compound name. + // + if (valid) + { + if (tns) + { +#ifdef XSDE_EXCEPTIONS + type_holder.assign (tn.data (), tn.size ()); + type_holder.append (" ", 1); + type_holder.append (tns); +#else + if (type_holder.assign (tn.data (), tn.size ()) || + type_holder.append (" ", 1) || + type_holder.append (tns)) + { + context_.sys_error (sys_error::no_memory); + XML_StopParser (xml_parser_, false); + } +#endif + type = type_holder.data (); + } + else + { + // We know that tn is '\0'-terminated. + // + type = tn.data (); + } + } + } + +#ifdef XSDE_PARSER_VALIDATION + if (!valid) + { + XML_StopParser (xml_parser_, false); + return; + } +#endif + } + } +#endif // XSDE_POLYMORPHIC + + // Dispatch. + // + if (cur.depth_ > 0) + { + if (cur.any_) + { + // Handling content matched by a wildcard. + // + cur.depth_++; + +#ifdef XSDE_POLYMORPHIC + cur.parser_->_start_any_element (ns, name, type); +#else + cur.parser_->_start_any_element (ns, name); +#endif + } + else + { + // Ignoring content for which there is no parser. + // + cur.depth_++; + } + } + else if (cur.parser_) + { + // The "normal" case: call _start_element which will + // call pre() and _pre_impl() (which will push the + // new parser). + // +#ifdef XSDE_POLYMORPHIC + cur.parser_->_start_element (ns, name, type); +#else + cur.parser_->_start_element (ns, name); +#endif + } + else + { + // Root element. Assume the user will report errors via + // context. + // +#ifdef XSDE_POLYMORPHIC + parser_base* p = 0; + + if (polymorphic_ && (root_name_ != name || root_ns_ != ns)) + { + // See if we can translate this element into type using + // substitution map. + // + if (substitution_map_instance ().check ( + ns, + name, + root_ns_.size () ? root_ns_.data () : 0, + root_name_.data (), + type)) + { + ro_string ro_ns (root_ns_); + ro_string ro_name (root_name_); + p = start_root_element (ro_ns, ro_name, type); + } + else + p = start_root_element (ns, name, type); + } + else + p = start_root_element (ns, name, type); +#else + parser_base* p = start_root_element (ns, name); +#endif + +#ifndef XSDE_EXCEPTIONS + if (!context_.error_type ()) + { +#endif + if (p) + { + // pre() is called by the user. + // + p->_pre_impl (context_); + } + else + { + // Ignoring. + // + cur.depth_++; + } + +#ifndef XSDE_EXCEPTIONS + } +#endif + } + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (context_.error_type ()) + { + XML_StopParser (xml_parser_, false); + return; + } +#endif + } + + // Dispatch attributes if we are not ignoring. + // + if (cur.depth_ == 0 || cur.any_) + { + for (; *atts != 0; atts += 2) + { + bits::split_name (*atts, ns_p, ns_s, name_p, name_s); + + const ro_string ns (ns_p, ns_s), name (name_p, name_s); + const ro_string value (*(atts + 1)); + + if (!cur.any_) + cur.parser_->_attribute (ns, name, value); + else + cur.parser_->_any_attribute (ns, name, value); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (context_.error_type ()) + { + XML_StopParser (xml_parser_, false); + break; + } +#endif + } + } + } + + void document_pimpl:: + end_element_ (const XML_Char* ns_name) + { + // See the comment in start_element_ for what's going on here. + // + { + XML_ParsingStatus s; + XML_GetParsingStatus (xml_parser_, &s); + if (s.parsing == XML_FINISHED) + return; + } + + const char* ns_p; + const char* name_p; + size_t ns_s, name_s; + + bits::split_name (ns_name, ns_p, ns_s, name_p, name_s); + + const ro_string ns (ns_p, ns_s); + const ro_string name (name_p, name_s); + + parser_state& cur = context_.current_; + + // @@ Error propagation. + // + if (cur.depth_ == 0) + { + // The "normal" case: call _post to pop the parser and then + // call _end_element on the "outer" parser which calls post(). + // + parser_base* p = cur.parser_; + cur.parser_->_post_impl (); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (!context_.error_type ()) + { +#endif + // This case is a bit complicated by the fact that we can be + // popped up into a wildcard. + // + if (cur.depth_ == 0) + { + if (cur.parser_) + cur.parser_->_end_element (ns, name); + else + { + // End of the root element. post() is called by the user. + // + end_root_element (ns, name, p); + } + } + else + { + // Handling content matched by a wildcard. + // + if (--cur.depth_ > 0) + cur.parser_->_end_any_element (ns, name); + else + { + cur.parser_->_end_element (ns, name); + cur.any_ = false; + } + } + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + } +#endif + } + else + { + if (cur.any_) + { + // Handling content matched by a wildcard. + // + if (--cur.depth_ > 0) + cur.parser_->_end_any_element (ns, name); + else + { + cur.parser_->_end_element (ns, name); + cur.any_ = false; + } + } + else + { + // Ignoring content for which there is no parser. + // + if (--cur.depth_ == 0) + { + if (cur.parser_) + cur.parser_->_end_element (ns, name); + else + { + // End of the root element for which there was + // no parser. + // + end_root_element (ns, name, 0); + } + } + } + } + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (context_.error_type ()) + XML_StopParser (xml_parser_, false); +#endif + } + + void document_pimpl:: + characters_ (const XML_Char* s, size_t n) + { + // See the comment in start_element_ for what's going on here. + // + { + XML_ParsingStatus s; + XML_GetParsingStatus (xml_parser_, &s); + if (s.parsing == XML_FINISHED) + return; + } + + // Dispatch characters if we are not ignoring. + // + parser_state& cur = context_.current_; + + if (n != 0 && (cur.depth_ == 0 || cur.any_)) + { + const ro_string str (s, n); + + if (!cur.any_) + cur.parser_->_characters (str); + else + cur.parser_->_any_characters (str); + +#if defined(XSDE_PARSER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (context_.error_type ()) + XML_StopParser (xml_parser_, false); +#endif + } + } + +#ifdef XSDE_POLYMORPHIC + void document_pimpl:: + start_namespace_decl_ (const XML_Char* p, const XML_Char* ns) + { + // prefix is 0 for default namespace + // namespace is 0 when unsetting default namespace + // + if (polymorphic_) + { +#if defined (XSDE_STL) + prefixes_.push_back (p ? p : ""); + prefix_namespaces_.push_back (ns ? ns : ""); +#else +#if defined (XSDE_EXCEPTIONS) + prefixes_.push_back_copy (p ? p : ""); + prefix_namespaces_.push_back_copy (ns ? ns : ""); +#else + if (prefixes_.push_back_copy (p ? p : "" ) || + prefix_namespaces_.push_back_copy (ns ? ns : "")) + { + context_.sys_error (sys_error::no_memory); + XML_StopParser (xml_parser_, false); + } +#endif +#endif + } + } + + void document_pimpl:: + end_namespace_decl_ (const XML_Char*) + { + // prefix is 0 for default namespace + // + if (polymorphic_) + { + // Here we assume the prefixes are removed in the reverse + // order of them being added. This appears to how every + // sensible implementation works. + // + prefixes_.pop_back (); + prefix_namespaces_.pop_back (); + } + } +#endif // XSDE_POLYMORPHIC + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/expat/document.hxx b/libxsde/xsde/cxx/parser/expat/document.hxx new file mode 100644 index 0000000..2f87686 --- /dev/null +++ b/libxsde/xsde/cxx/parser/expat/document.hxx @@ -0,0 +1,337 @@ +// file : xsde/cxx/parser/expat/document.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_EXPAT_DOCUMENT_HXX +#define XSDE_CXX_PARSER_EXPAT_DOCUMENT_HXX + +#include + +#include // size_t + +#ifdef XSDE_STL +# include +#endif + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include + +// We only support UTF-8 expat for now. +// +#ifdef XML_UNICODE +#error UTF-16 expat (XML_UNICODE defined) is not supported +#endif + +#include + +#ifdef XSDE_STL +# include +#else +# include +#endif + +#include +#include + +#ifndef XSDE_EXCEPTIONS +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace expat + { + // Simple auto pointer for Expat's XML_Parser object. + // + struct parser_auto_ptr + { + ~parser_auto_ptr (); + + explicit + parser_auto_ptr (XML_Parser = 0); + + parser_auto_ptr& + operator= (XML_Parser); + + public: + operator XML_Parser () + { + return parser_; + } + + private: + parser_auto_ptr (const parser_auto_ptr&); + + parser_auto_ptr& + operator= (const parser_auto_ptr&); + + private: + XML_Parser parser_; + }; + + // + // + class document_pimpl + { + public: + virtual + ~document_pimpl (); + +#ifdef XSDE_POLYMORPHIC + document_pimpl (parser_base&, + const char* root_element_name, + bool polymorphic = false); + + document_pimpl (parser_base&, + const char* root_element_namespace, + const char* root_element_name, + bool polymorphic = false); + +#ifdef XSDE_STL + document_pimpl (parser_base&, + const std::string& root_element_name, + bool polymorphic = false); + + document_pimpl (parser_base&, + const std::string& root_element_namespace, + const std::string& root_element_name, + bool polymorphic = false); + +#endif // XSDE_STL + protected: + document_pimpl (); // Non-polymorphic parsing. + + document_pimpl (const char* root_element_name); + + document_pimpl (const char* root_element_namespace, + const char* root_element_name); + +#ifdef XSDE_STL + document_pimpl (const std::string& root_element_name); + + document_pimpl (const std::string& root_element_namespace, + const std::string& root_element_name); +#endif + + +#else // XSDE_POLYMORPHIC + + document_pimpl (parser_base&, + const char* root_element_name); + + document_pimpl (parser_base&, + const char* root_element_namespace, + const char* root_element_name); + +#ifdef XSDE_STL + document_pimpl (parser_base&, + const std::string& root_element_name); + + document_pimpl (parser_base&, + const std::string& root_element_namespace, + const std::string& root_element_name); +#endif + protected: + document_pimpl (); + +#endif // XSDE_POLYMORPHIC + + // This function is called to obtain the root element type parser. + // If the returned pointed is 0 then the whole document content + // is ignored. + // + // The type argument contains the type name and namespace if + // xsi:type attribute or an element that substitutes the root + // was specified and 0 otherwise. The type argument is in the + // form " " with the space and namespace part + // absent if the type does not have a namespace. + // + // +#ifdef XSDE_POLYMORPHIC + virtual parser_base* + start_root_element (const ro_string& ns, + const ro_string& name, + const char* type); +#else + virtual parser_base* + start_root_element (const ro_string& ns, const ro_string& name); +#endif + + + // 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, + parser_base* parser); + + public: + // If you override start_root_element() then you will most + // likely also want to override reset() in order to reset + // root element parser(s). + // + virtual void + reset (); + +#ifdef XSDE_IOSTREAM + public: + // Parse a local file. The file is accessed with std::ifstream + // in binary mode. The std::ios_base::failure exception is used + // to report io errors (badbit and failbit) if XSDE_EXCEPTIONS + // is defined. Otherwise error codes are used. + // + void + parse (const char* file); + +#ifdef XSDE_STL + void + parse (const std::string& file); +#endif + + // Parse std::istream. std::ios_base::failure exception is used + // to report io errors (badbit and failbit) if XSDE_EXCEPTIONS + // is defined. Otherwise error codes are used. + // + void + parse (std::istream&); +#endif + + public: + // Parse a chunk of input. You can call this function multiple + // times with the last call having the last argument true. + // + void + parse (const void* data, size_t size, bool last); + + public: + // Low-level Expat-specific parsing API. A typical use case + // would look like this (pseudo-code): + // + // XML_Parser xml_parser (XML_ParserCreateNS (0, ' ')); + // + // xxx_pimpl root; + // document_pimpl doc (root, "root"); + // + // root.pre (); + // doc.parse_begin (xml_parser); + // + // while (more_stuff_to_parse) + // { + // // Call XML_Parse or XML_ParseBuffer: + // // + // if (XML_Parse (...) != XML_STATUS_ERROR) + // break; + // } + // + // doc.parse_end (); + // result_type result (root.post_xxx ()); + // + // Notes: + // + // 1. If your XML instances use XML namespaces, XML_ParserCreateNS + // functions should be used to create the XML parser. Space + // (XML_Char (' ')) should be used as a separator (the second + // argument to XML_ParserCreateNS). + // + // 2. If XML_Parse or XML_ParseBuffer fail, call parse_end to + // determine the error which is indicated either via exception + // or set as an error code. + // + void + parse_begin (XML_Parser); + + void + parse_end (); + +#ifndef XSDE_EXCEPTIONS + public: + const error& + _error () const; +#endif + + protected: + void + set (); + + void + clear (); + + protected: + static void XMLCALL + start_element (void*, const XML_Char*, const XML_Char**); + + static void XMLCALL + end_element (void*, const XML_Char*); + + static void XMLCALL + characters (void*, const XML_Char*, int); + +#ifdef XSDE_POLYMORPHIC + static void XMLCALL + start_namespace_decl (void*, const XML_Char*, const XML_Char*); + + static void XMLCALL + end_namespace_decl (void*, const XML_Char*); +#endif + + protected: + void + start_element_ (const XML_Char* ns_name, const XML_Char** atts); + + void + end_element_ (const XML_Char* ns_name); + + void + characters_ (const XML_Char* s, size_t n); + +#ifdef XSDE_POLYMORPHIC + void + start_namespace_decl_ (const XML_Char* prefix, const XML_Char* ns); + + void + end_namespace_decl_ (const XML_Char* prefix); +#endif + + protected: + bool first_; + XML_Parser xml_parser_; + parser_auto_ptr auto_xml_parser_; + + context context_; + + parser_base* parser_; + string root_name_; + string root_ns_; + +#ifdef XSDE_POLYMORPHIC + bool polymorphic_; + string_sequence prefixes_; + string_sequence prefix_namespaces_; +#endif + +#ifndef XSDE_EXCEPTIONS + error error_; +#endif + + private: + void + init_root_name (const char* ns, const char* name); + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_EXPAT_DOCUMENT_HXX diff --git a/libxsde/xsde/cxx/parser/expat/document.ixx b/libxsde/xsde/cxx/parser/expat/document.ixx new file mode 100644 index 0000000..0c3d34d --- /dev/null +++ b/libxsde/xsde/cxx/parser/expat/document.ixx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/expat/document.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace expat + { + // parser_auto_ptr + // + inline parser_auto_ptr:: + ~parser_auto_ptr () + { + if (parser_ != 0) + XML_ParserFree (parser_); + } + + inline parser_auto_ptr:: + parser_auto_ptr (XML_Parser parser) + : parser_ (parser) + { + } + + inline parser_auto_ptr& parser_auto_ptr:: + operator= (XML_Parser parser) + { + if (parser_ != 0) + XML_ParserFree (parser_); + + parser_ = parser; + return *this; + } + + + // document_pimpl + // +#ifndef XSDE_EXCEPTIONS + inline const error& document_pimpl:: + _error () const + { + return error_; + } +#endif + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/expat/xml-error.cxx b/libxsde/xsde/cxx/parser/expat/xml-error.cxx new file mode 100644 index 0000000..a24059c --- /dev/null +++ b/libxsde/xsde/cxx/parser/expat/xml-error.cxx @@ -0,0 +1,25 @@ +// file : xsde/cxx/parser/expat/xml-error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace expat + { + const char* + xml_error_text (xml_error e) + { + return XML_ErrorString (e); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/expat/xml-error.hxx b/libxsde/xsde/cxx/parser/expat/xml-error.hxx new file mode 100644 index 0000000..4028590 --- /dev/null +++ b/libxsde/xsde/cxx/parser/expat/xml-error.hxx @@ -0,0 +1,28 @@ +// file : xsde/cxx/parser/expat/xml-error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_EXPAT_XML_ERROR_HXX +#define XSDE_CXX_PARSER_EXPAT_XML_ERROR_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace expat + { + typedef XML_Error xml_error; + + const char* + xml_error_text (xml_error); + } + } + } +} + +#endif // XSDE_CXX_PARSER_EXPAT_XML_ERROR_HXX diff --git a/libxsde/xsde/cxx/parser/map.cxx b/libxsde/xsde/cxx/parser/map.cxx new file mode 100644 index 0000000..b21c41e --- /dev/null +++ b/libxsde/xsde/cxx/parser/map.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/parser/map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // parser_map + // + parser_map:: + ~parser_map () + { + } + + // parser_map_impl + // + void parser_map_impl:: + reset () const + { + for (hashmap::const_iterator i (map_.begin ()), e (map_.end ()); + i != e; ++i) + { + parser_base* p = *static_cast (*i); + p->_reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/map.hxx b/libxsde/xsde/cxx/parser/map.hxx new file mode 100644 index 0000000..400de27 --- /dev/null +++ b/libxsde/xsde/cxx/parser/map.hxx @@ -0,0 +1,87 @@ +// file : xsde/cxx/parser/map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_MAP_HXX +#define XSDE_CXX_PARSER_MAP_HXX + +#include // size_t + +#include +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // Parser map. Used in the polymorphic document parsing. + // + class parser_map + { + public: + // The type argument is the type name and namespace from the + // xsi:type attribute or substitution group map in the form + // " " with the space and namespace part + // absent if the type does not have a namespace. + // + virtual parser_base* + find (const char* type) const = 0; + + // Reset the parsers this map contains. + // + virtual void + reset () const = 0; + + virtual + ~parser_map (); + }; + + // Default parser map implementation. + // + class parser_map_impl: public parser_map + { + public: +#ifndef XSDE_EXCEPTIONS + enum error + { + error_none, + error_no_memory + }; + + error + _error () const; +#endif + + public: + parser_map_impl (size_t buckets); + + void + insert (parser_base&); + + virtual parser_base* + find (const char* type) const; + + virtual void + reset () const; + + private: + parser_map_impl (const parser_map_impl&); + + parser_map_impl& + operator= (const parser_map_impl&); + + private: + hashmap map_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_MAP_HXX diff --git a/libxsde/xsde/cxx/parser/map.ixx b/libxsde/xsde/cxx/parser/map.ixx new file mode 100644 index 0000000..3a1f931 --- /dev/null +++ b/libxsde/xsde/cxx/parser/map.ixx @@ -0,0 +1,41 @@ +// file : xsde/cxx/parser/map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { +#ifndef XSDE_EXCEPTIONS + inline parser_map_impl::error parser_map_impl:: + _error () const + { + return map_._error () ? error_no_memory : error_none; + } +#endif + + inline parser_map_impl:: + parser_map_impl (size_t buckets) + : map_ (buckets, sizeof (parser_base*)) + { + } + + inline void parser_map_impl:: + insert (parser_base& p) + { + parser_base* tmp = &p; + map_.insert (p._dynamic_type (), &tmp); + } + + inline parser_base* parser_map_impl:: + find (const char* type) const + { + const void* p = map_.find (type); + return p ? *static_cast (p) : 0; + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/any-type.hxx b/libxsde/xsde/cxx/parser/non-validating/any-type.hxx new file mode 100644 index 0000000..37e1d6f --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/any-type.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/parser/non-validating/any-type.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_ANY_TYPE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_ANY_TYPE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // any_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_type_pimpl: virtual any_type_pskel +#else + struct any_type_pimpl: any_type_pskel +#endif + { + }; + + // any_simple_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_simple_type_pimpl: virtual any_simple_type_pskel +#else + struct any_simple_type_pimpl: any_simple_type_pskel +#endif + { + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_ANY_TYPE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx new file mode 100644 index 0000000..95588a2 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx @@ -0,0 +1,241 @@ +// file : xsde/cxx/parser/non-validating/base64-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +static unsigned char +base64_decode (char c) +{ + unsigned char r = 0xFF; + + if (c >= 'A' && c <= 'Z') + r = static_cast (c - 'A'); + else if (c >= 'a' && c <= 'z') + r = static_cast (c - 'a' + 26); + else if (c >= '0' && c <= '9') + r = static_cast (c - '0' + 52); + else if (c == '+') + r = 62; + else if (c == '/') + r = 63; + + return r; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + base64_binary_pimpl:: + ~base64_binary_pimpl () + { + if (!base_) + delete buf_; + } + + void base64_binary_pimpl:: + _reset () + { + base64_binary_pskel::_reset (); + + if (!base_) + { + delete buf_; + buf_ = 0; + } + } + + base64_binary_pimpl:: + base64_binary_pimpl (bool base) + : base_ (base), buf_ (0) + { + } + + void base64_binary_pimpl:: + pre_impl (buffer* b) + { + buf_ = b; + } + + void base64_binary_pimpl:: + _pre () + { + if (buf_ == 0) + { + buf_ = new buffer (); + +#ifndef XSDE_EXCEPTIONS + if (buf_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void base64_binary_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + buffer* base64_binary_pimpl:: + post_base64_binary () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + const char* src = str_.data (); + + // Remove all whitespaces. + // + { + size_type j = 0; + bool subs = false; + + for (size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + subs = false; + + str_[j++] = c; + } + } + + size = j; + str_.truncate (size); + } + + // Our length should be a multiple of four. + // + size_type quad_count = size / 4; + size_type capacity = quad_count * 3 + 1; + +#ifdef XSDE_EXCEPTIONS + buf_->size (capacity); +#else + if (buf_->size (capacity)) + { + _sys_error (sys_error::no_memory); + return 0; + } +#endif + char* dst = buf_->data (); + + // Source and destination indexes. + // + size_type si = 0; + size_type di = 0; + + // Process all quads except the last one. + // + unsigned char b1, b2, b3, b4; + + for (size_type q = 0; q < quad_count - 1; ++q) + { + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + b3 = base64_decode (src[si++]); + b4 = base64_decode (src[si++]); + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } + + // Process the last quad. The first two octets are always there. + // + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + + char e3 = src[si++]; + char e4 = src[si++]; + + if (e4 == '=') + { + if (e3 == '=') + { + // Two pads. Last 4 bits in b2 should be zero. + // + dst[di++] = (b1 << 2) | (b2 >> 4); + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + } + } + else + { + // No pads. + // + b3 = base64_decode (e3); + b4 = base64_decode (e4); + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } + + // Set the real size. + // + buf_->size (di); + + buffer* r = buf_; + buf_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/base64-binary.hxx b/libxsde/xsde/cxx/parser/non-validating/base64-binary.hxx new file mode 100644 index 0000000..fef946b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/base64-binary.hxx @@ -0,0 +1,55 @@ +// file : xsde/cxx/parser/non-validating/base64-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_BASE64_BINARY_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_BASE64_BINARY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct base64_binary_pimpl: virtual base64_binary_pskel +#else + struct base64_binary_pimpl: base64_binary_pskel +#endif + { + ~base64_binary_pimpl (); + base64_binary_pimpl (bool base = false); + + void + pre_impl (buffer*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual buffer* + post_base64_binary (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + buffer* buf_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_BASE64_BINARY_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/boolean.cxx b/libxsde/xsde/cxx/parser/non-validating/boolean.cxx new file mode 100644 index 0000000..af5ee41 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/boolean.cxx @@ -0,0 +1,80 @@ +// file : xsde/cxx/parser/non-validating/boolean.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void boolean_pimpl:: + _pre () + { + size_ = 0; + state_ = leading_ws; + } + + void boolean_pimpl:: + _characters (const ro_string& s) + { + ro_string tmp (s.data (), s.size ()); + + size_t size = tmp.size (); + + switch (state_) + { + case leading_ws: + { + size = trim_left (tmp); + + if (size != 0) + state_ = literal; + else + break; + // Fall through. + } + case literal: + { + // If this chunk is too long then it has to be the last so trim + // trailing ws. + // + if ((5 - size_) < size) + { + size = trim_right (tmp); + state_ = trailing_ws; // It either had ws or is too large. + } + + if ((5 - size_) >= size) + { + memcpy (str_ + size_, tmp.data (), size); + size_ += size; + } + + break; + } + case trailing_ws: + { + // We don't really care if it is not. + break; + } + } + } + + bool boolean_pimpl:: + post_boolean () + { + ro_string tmp (str_, size_); + trim_right (tmp); + + return (tmp == "1" || tmp == "true"); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/boolean.hxx b/libxsde/xsde/cxx/parser/non-validating/boolean.hxx new file mode 100644 index 0000000..eeb9068 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/boolean.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/boolean.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_BOOLEAN_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_BOOLEAN_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct boolean_pimpl: virtual boolean_pskel +#else + struct boolean_pimpl: boolean_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual bool + post_boolean (); + + protected: + // We only need strlen("false") + 1 characters to hold all valid + // and trimmed string representations of boolean. + // + char str_[6]; + size_t size_; + enum { leading_ws, literal, trailing_ws } state_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_BOOLEAN_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/byte.cxx b/libxsde/xsde/cxx/parser/non-validating/byte.cxx new file mode 100644 index 0000000..47fa839 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/byte.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void byte_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void byte_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 4); + } + + signed char byte_pimpl:: + post_byte () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + str_[size] = '\0'; + unsigned long ul = strtoul (str_, 0, 10); + + return (sign_ == minus) + ? static_cast (-static_cast (ul)) + : static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/byte.hxx b/libxsde/xsde/cxx/parser/non-validating/byte.hxx new file mode 100644 index 0000000..a6bbffc --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/byte.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_BYTE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_BYTE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 8-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct byte_pimpl: virtual byte_pskel, number +#else + struct byte_pimpl: byte_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual signed char + post_byte (); + + protected: + // We only need strlen("0128") + 1 characters to hold all valid + // and trimmed string representations of signed byte. + // + char str_[5]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_BYTE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/date-time.cxx b/libxsde/xsde/cxx/parser/non-validating/date-time.cxx new file mode 100644 index 0000000..59d8c11 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/date-time.cxx @@ -0,0 +1,154 @@ +// file : xsde/cxx/parser/non-validating/date-time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul, strtod + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void date_time_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void date_time_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + date_time date_time_pimpl:: + post_date_time () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] + // + + int year = 0; + unsigned short month = 0; + unsigned short day = 0; + unsigned short hours = 0; + unsigned short minutes = 0; + double seconds = 0.0; + bool zone = false; + short zh, zm; + + if (n >= 19) + { + // Find the end of the year token. + // + ro_string::size_type yp = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (yp != ro_string::npos && (n - yp - 1) >= 14) + { + // Find the end of the seconds fragment. + // + ro_string::size_type sp = yp + 15; + for (; sp < n; ++sp) + { + char c = s[sp]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // Parse it backwards so that we can truncate and reuse + // the string. + // + + // zone + // + if (sp < n) + { + bits::parse_time_zone (s + sp, n - sp, zh, zm); + zone = true; + } + + // seconds + // + str_.truncate (sp); + + seconds = strtod (s + yp + 13, 0); + + // minutes + // + minutes = 10 * (s[yp + 10] - '0') + (s[yp + 11] - '0'); + + // hours + // + hours = 10 * (s[yp + 7] - '0') + (s[yp + 8] - '0'); + + // day + // + day = 10 * (s[yp + 4] - '0') + (s[yp + 5] - '0'); + + // month + // + month = 10 * (s[yp + 1] - '0') + (s[yp + 2] - '0'); + + // year + // + str_.truncate (yp); + + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, 0, 10); + + year = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + } + + return zone + ? date_time (year, month, day, hours, minutes, seconds, zh, zm) + : date_time (year, month, day, hours, minutes, seconds); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/date-time.hxx b/libxsde/xsde/cxx/parser/non-validating/date-time.hxx new file mode 100644 index 0000000..bb329af --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/date-time.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/date-time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_DATE_TIME_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_DATE_TIME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_time_pimpl: virtual date_time_pskel +#else + struct date_time_pimpl: date_time_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual date_time + post_date_time (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_DATE_TIME_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/date.cxx b/libxsde/xsde/cxx/parser/non-validating/date.cxx new file mode 100644 index 0000000..0364ac1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/date.cxx @@ -0,0 +1,126 @@ +// file : xsde/cxx/parser/non-validating/date.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void date_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void date_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + date date_pimpl:: + post_date () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] + // + + int year = 0; + unsigned short month = 0; + unsigned short day = 0; + bool zone = false; + short zh, zm; + + if (n >= 10) + { + // Find the end of the year token. + // + ro_string::size_type pos = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (pos != ro_string::npos && (n - pos - 1) >= 5) + { + // Parse the month, day values and time zone first so that we + // can truncate and reuse the string. + // + + // month + // + month = 10 * (s[pos + 1] - '0') + (s[pos + 2] - '0'); + + // day + // + day = 10 * (s[pos + 4] - '0') + (s[pos + 5] - '0'); + + // zone + // + if ((pos + 6) < n) + { + bits::parse_time_zone (s + pos + 6, n - pos - 6, zh, zm); + zone = true; + } + + // year + // + str_.truncate (pos); + + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, 0, 10); + + year = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + } + + return zone + ? date (year, month, day, zh, zm) + : date (year, month, day); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/date.hxx b/libxsde/xsde/cxx/parser/non-validating/date.hxx new file mode 100644 index 0000000..174de7d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/date.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/date.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_DATE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_DATE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_pimpl: virtual date_pskel +#else + struct date_pimpl: date_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual date + post_date (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_DATE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/decimal.cxx b/libxsde/xsde/cxx/parser/non-validating/decimal.cxx new file mode 100644 index 0000000..401800b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/decimal.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/decimal.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void decimal_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void decimal_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 127); + } + + double decimal_pimpl:: + post_decimal () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + double r = strtod (str_, 0); + + if (sign_ == minus) + r = -r; + + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/decimal.hxx b/libxsde/xsde/cxx/parser/non-validating/decimal.hxx new file mode 100644 index 0000000..fd1cf4e --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/decimal.hxx @@ -0,0 +1,46 @@ +// file : xsde/cxx/parser/non-validating/decimal.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_DECIMAL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_DECIMAL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct decimal_pimpl: virtual decimal_pskel, number +#else + struct decimal_pimpl: decimal_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual double + post_decimal (); + + protected: + // Assume decimal values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_DECIMAL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/double.cxx b/libxsde/xsde/cxx/parser/non-validating/double.cxx new file mode 100644 index 0000000..8c7ab9a --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/double.cxx @@ -0,0 +1,62 @@ +// file : xsde/cxx/parser/non-validating/double.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void double_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void double_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 127); + } + + double double_pimpl:: + post_double () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + double r; + + if (tmp == "INF") + { + r = strtod (sign_ == minus ? "-INF" : "INF", 0); + } + else if (tmp == "NaN") + { + r = strtod ("NAN", 0); + } + else + { + r = strtod (str_, 0); + + if (sign_ == minus) + r = -r; + } + + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/double.hxx b/libxsde/xsde/cxx/parser/non-validating/double.hxx new file mode 100644 index 0000000..1e5f299 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/double.hxx @@ -0,0 +1,46 @@ +// file : xsde/cxx/parser/non-validating/double.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_DOUBLE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_DOUBLE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct double_pimpl: virtual double_pskel, number +#else + struct double_pimpl: double_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual double + post_double (); + + protected: + // Assume double values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_DOUBLE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/duration.cxx b/libxsde/xsde/cxx/parser/non-validating/duration.cxx new file mode 100644 index 0000000..d7cbb3b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/duration.cxx @@ -0,0 +1,166 @@ +// file : xsde/cxx/parser/non-validating/duration.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul, strtod + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void duration_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void duration_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + static ro_string::size_type + rfind_delim (const char* s, ro_string::size_type pos) + { + const char* p = s + pos; + for (; p >= s; --p) + { + if (*p == 'Y' || *p == 'D' || *p == 'M' || + *p == 'H' || *p == 'M' || *p == 'S' || + *p == 'T' || *p == 'P') + break; + } + + return p >= s ? p - s : ro_string::npos; + } + + duration duration_pimpl:: + post_duration () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + bool negative = false; + unsigned int years = 0; + unsigned int months = 0; + unsigned int days = 0; + unsigned int hours = 0; + unsigned int minutes = 0; + double seconds = 0.0; + + // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] + // + + if (n >= 3 && s[s[0] == '-' ? 1 : 0] == 'P') + { + if (s[0] == '-') + negative = true; + + // Parse it backwards so that we can truncate and reuse + // the string. + // + ro_string::size_type pos = n - 1; + ro_string::size_type t_pos = tmp.find ('T'); + + if (s[pos] == 'S') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + seconds = strtod (s + pos + 1, 0); + } + + if (s[pos] == 'M' && t_pos != ro_string::npos && t_pos < pos) + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + minutes = + static_cast (strtoul (s + pos + 1, 0, 10)); + } + + if (s[pos] == 'H') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + hours = + static_cast (strtoul (s + pos + 1, 0, 10)); + } + + if (s[pos] == 'T') + pos = rfind_delim (s, pos - 1); + + if (s[pos] == 'D') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + days = + static_cast (strtoul (s + pos + 1, 0, 10)); + } + + if (s[pos] == 'M') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + months = + static_cast (strtoul (s + pos + 1, 0, 10)); + } + + if (s[pos] == 'Y') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + years = + static_cast (strtoul (s + pos + 1, 0, 10)); + } + } + + return duration ( + negative, years, months, days, hours, minutes, seconds); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/duration.hxx b/libxsde/xsde/cxx/parser/non-validating/duration.hxx new file mode 100644 index 0000000..ebbd210 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/duration.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/duration.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_DURATION_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_DURATION_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct duration_pimpl: virtual duration_pskel +#else + struct duration_pimpl: duration_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual duration + post_duration (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_DURATION_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/float.cxx b/libxsde/xsde/cxx/parser/non-validating/float.cxx new file mode 100644 index 0000000..9c90b32 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/float.cxx @@ -0,0 +1,76 @@ +// file : xsde/cxx/parser/non-validating/float.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtof, strtod + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void float_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void float_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 127); + } + + float float_pimpl:: + post_float () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + float r; + + if (tmp == "INF") + { +#ifdef XSDE_STRTOF + r = strtof (sign_ == minus ? "-INF" : "INF", 0); +#else + r = static_cast (strtod (sign_ == minus ? "-INF" : "INF", 0)); +#endif + } + else if (tmp == "NaN") + { +#ifdef XSDE_STRTOF + r = strtof ("NAN", 0); +#else + r = static_cast (strtod ("NAN", 0)); +#endif + } + else + { +#ifdef XSDE_STRTOF + r = strtof (str_, 0); +#else + r = static_cast (strtod (str_, 0)); +#endif + + if (sign_ == minus) + r = -r; + } + + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/float.hxx b/libxsde/xsde/cxx/parser/non-validating/float.hxx new file mode 100644 index 0000000..cae4fa7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/float.hxx @@ -0,0 +1,46 @@ +// file : xsde/cxx/parser/non-validating/float.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_FLOAT_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_FLOAT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct float_pimpl: virtual float_pskel, number +#else + struct float_pimpl: float_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual float + post_float (); + + protected: + // Assume float values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_FLOAT_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/gday.cxx b/libxsde/xsde/cxx/parser/non-validating/gday.cxx new file mode 100644 index 0000000..64c9cd9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gday.cxx @@ -0,0 +1,88 @@ +// file : xsde/cxx/parser/non-validating/gday.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void gday_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gday_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + gday gday_pimpl:: + post_gday () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gday := ---DD[Z|(+|-)HH:MM] + // + + unsigned short day = 0; + bool zone = false; + short zh, zm; + + if (n >= 5) + { + day = 10 * (s[3] - '0') + (s[4] - '0'); + + if (n > 5) + { + bits::parse_time_zone (s + 5, n - 5, zh, zm); + zone = true; + } + } + + return zone ? gday (day, zh, zm) : gday (day); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/gday.hxx b/libxsde/xsde/cxx/parser/non-validating/gday.hxx new file mode 100644 index 0000000..7af0c19 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gday.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/gday.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_GDAY_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_GDAY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gday_pimpl: virtual gday_pskel +#else + struct gday_pimpl: gday_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual gday + post_gday (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_GDAY_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/gmonth-day.cxx b/libxsde/xsde/cxx/parser/non-validating/gmonth-day.cxx new file mode 100644 index 0000000..223b73f --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gmonth-day.cxx @@ -0,0 +1,100 @@ +// file : xsde/cxx/parser/non-validating/gmonth-day.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void gmonth_day_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gmonth_day_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + gmonth_day gmonth_day_pimpl:: + post_gmonth_day () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gmonth_day := --MM-DD[Z|(+|-)HH:MM] + // + + unsigned short month = 0; + unsigned short day = 0; + bool zone = false; + short zh, zm; + + if (n >= 7) + { + // month + // + month = 10 * (s[2] - '0') + (s[3] - '0'); + + // day + // + day = 10 * (s[5] - '0') + (s[6] - '0'); + + // zone + // + if (n > 7) + { + bits::parse_time_zone (s + 7, n - 7, zh, zm); + zone = true; + + } + } + + return zone + ? gmonth_day (month, day, zh, zm) + : gmonth_day (month, day); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/gmonth-day.hxx b/libxsde/xsde/cxx/parser/non-validating/gmonth-day.hxx new file mode 100644 index 0000000..75fb3fb --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gmonth-day.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/gmonth-day.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_DAY_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_DAY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_day_pimpl: virtual gmonth_day_pskel +#else + struct gmonth_day_pimpl: gmonth_day_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual gmonth_day + post_gmonth_day (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_DAY_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/gmonth.cxx b/libxsde/xsde/cxx/parser/non-validating/gmonth.cxx new file mode 100644 index 0000000..f203c70 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gmonth.cxx @@ -0,0 +1,88 @@ +// file : xsde/cxx/parser/non-validating/gmonth.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void gmonth_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gmonth_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + gmonth gmonth_pimpl:: + post_gmonth () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gmonth := --MM[Z|(+|-)HH:MM] + // + + unsigned short month = 0; + bool zone = false; + short zh, zm; + + if (n >= 4) + { + month = 10 * (s[2] - '0') + (s[3] - '0'); + + if (n > 4) + { + bits::parse_time_zone (s + 4, n - 4, zh, zm); + zone = true; + } + } + + return zone ? gmonth (month, zh, zm) : gmonth (month); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/gmonth.hxx b/libxsde/xsde/cxx/parser/non-validating/gmonth.hxx new file mode 100644 index 0000000..dfa9b33 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gmonth.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/gmonth.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_pimpl: virtual gmonth_pskel +#else + struct gmonth_pimpl: gmonth_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual gmonth + post_gmonth (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_GMONTH_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/gyear-month.cxx b/libxsde/xsde/cxx/parser/non-validating/gyear-month.cxx new file mode 100644 index 0000000..4492246 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gyear-month.cxx @@ -0,0 +1,121 @@ +// file : xsde/cxx/parser/non-validating/gyear-month.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void gyear_month_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gyear_month_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + gyear_month gyear_month_pimpl:: + post_gyear_month () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] + // + + int year = 0; + unsigned short month = 0; + bool zone = false; + short zh, zm; + + if (n >= 7) + { + // Find the end of the year token. + // + ro_string::size_type pos = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (pos != ro_string::npos && (n - pos - 1) >= 2) + { + // Parse the month value and time zone first so that we can + // truncate and reuse the string. + // + + // month + // + month = 10 * (s[pos + 1] - '0') + (s[pos + 2] - '0'); + + // zone + // + if ((pos + 3) < n) + { + bits::parse_time_zone (s + pos + 3, n - pos - 3, zh, zm); + zone = true; + } + + // year + // + str_.truncate (pos); + + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, 0, 10); + + year = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + } + + return zone + ? gyear_month (year, month, zh, zm) + : gyear_month (year, month); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/gyear-month.hxx b/libxsde/xsde/cxx/parser/non-validating/gyear-month.hxx new file mode 100644 index 0000000..23b7378 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gyear-month.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/gyear-month.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_MONTH_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_MONTH_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_month_pimpl: virtual gyear_month_pskel +#else + struct gyear_month_pimpl: gyear_month_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual gyear_month + post_gyear_month (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_MONTH_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/gyear.cxx b/libxsde/xsde/cxx/parser/non-validating/gyear.cxx new file mode 100644 index 0000000..351ac4c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gyear.cxx @@ -0,0 +1,115 @@ +// file : xsde/cxx/parser/non-validating/gyear.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void gyear_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gyear_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + gyear gyear_pimpl:: + post_gyear () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] + // + + int year = 0; + bool zone = false; + short zh, zm; + + if (n >= 4) + { + // Find the end of the year token. + // + ro_string::size_type pos = (s[0] == '-' ? 5 : 4); + for (; pos < n; ++pos) + { + char c = s[pos]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // Parse the time zone first so that we can truncate and + // reuse the string. + // + if (pos < n) + { + bits::parse_time_zone (s + pos, n - pos, zh, zm); + zone = true; + } + + // Parse the year value. + // + str_.truncate (pos); + + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, 0, 10); + + year = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + + return zone ? gyear (year, zh, zm) : gyear (year); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/gyear.hxx b/libxsde/xsde/cxx/parser/non-validating/gyear.hxx new file mode 100644 index 0000000..528b368 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/gyear.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/gyear.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_pimpl: virtual gyear_pskel +#else + struct gyear_pimpl: gyear_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual gyear + post_gyear (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_GYEAR_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/hex-binary.cxx b/libxsde/xsde/cxx/parser/non-validating/hex-binary.cxx new file mode 100644 index 0000000..a7cc8b4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/hex-binary.cxx @@ -0,0 +1,159 @@ +// file : xsde/cxx/parser/non-validating/hex-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +static unsigned char +hex_decode (char c) +{ + unsigned char r = 0xFF; + + if (c >= '0' && c <= '9') + r = static_cast (c - '0'); + else if (c >= 'A' && c <= 'F') + r = static_cast (10 + (c - 'A')); + else if (c >= 'a' && c <= 'f') + r = static_cast (10 + (c - 'a')); + + return r; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + hex_binary_pimpl:: + ~hex_binary_pimpl () + { + if (!base_) + delete buf_; + } + + void hex_binary_pimpl:: + _reset () + { + hex_binary_pskel::_reset (); + + if (!base_) + { + delete buf_; + buf_ = 0; + } + } + + hex_binary_pimpl:: + hex_binary_pimpl (bool base) + : base_ (base), buf_ (0) + { + } + + void hex_binary_pimpl:: + pre_impl (buffer* b) + { + buf_ = b; + } + + void hex_binary_pimpl:: + _pre () + { + if (buf_ == 0) + { + buf_ = new buffer (); + +#ifndef XSDE_EXCEPTIONS + if (buf_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void hex_binary_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + buffer* hex_binary_pimpl:: + post_hex_binary () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + size_t n = size / 2; + +#ifdef XSDE_EXCEPTIONS + buf_->size (n); +#else + if (buf_->size (n)) + { + _sys_error (sys_error::no_memory); + return 0; + } +#endif + + if (n != 0) + { + const char* src = tmp.data (); + char* dst = buf_->data (); + size_t i = 0; + + for (; i < n; ++i) + { + unsigned char h = hex_decode (src[2 * i]); + unsigned char l = hex_decode (src[2 * i + 1]); + + if (h == 0xFF || l == 0xFF) + break; + + dst[i] = (h << 4) | l; + } + } + + buffer* r = buf_; + buf_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/hex-binary.hxx b/libxsde/xsde/cxx/parser/non-validating/hex-binary.hxx new file mode 100644 index 0000000..3b7a4b3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/hex-binary.hxx @@ -0,0 +1,55 @@ +// file : xsde/cxx/parser/non-validating/hex-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_HEX_BINARY_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_HEX_BINARY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct hex_binary_pimpl: virtual hex_binary_pskel +#else + struct hex_binary_pimpl: hex_binary_pskel +#endif + { + ~hex_binary_pimpl (); + hex_binary_pimpl (bool base = false); + + void + pre_impl (buffer*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual buffer* + post_hex_binary (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + buffer* buf_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_HEX_BINARY_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/id-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/id-stl.cxx new file mode 100644 index 0000000..15a611b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/id-stl.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/id-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void id_pimpl:: + _pre () + { + str_.erase (); + } + + void id_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string id_pimpl:: + post_id () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/non-validating/id-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/id-stl.hxx new file mode 100644 index 0000000..5109ba1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/id-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/id-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_ID_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_ID_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_pimpl: virtual id_pskel +#else + struct id_pimpl: id_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_id (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_ID_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/id.cxx b/libxsde/xsde/cxx/parser/non-validating/id.cxx new file mode 100644 index 0000000..5230305 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/id.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/id.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void id_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void id_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* id_pimpl:: + post_id () + { + ro_string tmp (str_.data (), str_.size ()); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/id.hxx b/libxsde/xsde/cxx/parser/non-validating/id.hxx new file mode 100644 index 0000000..d762271 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/id.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/id.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_ID_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_ID_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_pimpl: virtual id_pskel +#else + struct id_pimpl: id_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_id (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_ID_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/idref-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/idref-stl.cxx new file mode 100644 index 0000000..e3be5af --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idref-stl.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/idref-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void idref_pimpl:: + _pre () + { + str_.erase (); + } + + void idref_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string idref_pimpl:: + post_idref () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/idref-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/idref-stl.hxx new file mode 100644 index 0000000..e65375c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idref-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/idref-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_IDREF_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_IDREF_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_pimpl: virtual idref_pskel +#else + struct idref_pimpl: idref_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_idref (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_IDREF_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/idref.cxx b/libxsde/xsde/cxx/parser/non-validating/idref.cxx new file mode 100644 index 0000000..f6ac060 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idref.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/idref.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void idref_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void idref_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* idref_pimpl:: + post_idref () + { + ro_string tmp (str_.data (), str_.size ()); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/idref.hxx b/libxsde/xsde/cxx/parser/non-validating/idref.hxx new file mode 100644 index 0000000..b76318c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idref.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/idref.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_IDREF_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_IDREF_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_pimpl: virtual idref_pskel +#else + struct idref_pimpl: idref_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_idref (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_IDREF_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.cxx new file mode 100644 index 0000000..a62ea47 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.cxx @@ -0,0 +1,94 @@ +// file : xsde/cxx/parser/non-validating/idrefs-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + idrefs_pimpl:: + ~idrefs_pimpl () + { + if (!base_) + delete seq_; + } + + void idrefs_pimpl:: + _reset () + { + idrefs_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + idrefs_pimpl:: + idrefs_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void idrefs_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void idrefs_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + idrefs_pskel::_pre (); + } + + string_sequence* idrefs_pimpl:: + post_idrefs () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void idrefs_pimpl:: + _xsde_parse_item (const ro_string& s) + { + parser_.pre (); + parser_._pre_impl (_context ()); + parser_._characters (s); + parser_._post_impl (); + seq_->push_back (parser_.post_idref ()); + } + } + } + } +} + +#include diff --git a/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.hxx new file mode 100644 index 0000000..193b764 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idrefs-stl.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/non-validating/idrefs-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_pimpl: virtual idrefs_pskel +#else + struct idrefs_pimpl: idrefs_pskel +#endif + { + ~idrefs_pimpl (); + idrefs_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual string_sequence* + post_idrefs (); + + virtual void + _reset (); + + protected: + bool base_; + idref_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/idrefs.cxx b/libxsde/xsde/cxx/parser/non-validating/idrefs.cxx new file mode 100644 index 0000000..15a6947 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idrefs.cxx @@ -0,0 +1,133 @@ +// file : xsde/cxx/parser/non-validating/idrefs.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + idrefs_pimpl:: + ~idrefs_pimpl () + { + if (!base_) + delete seq_; + } + + void idrefs_pimpl:: + _reset () + { + idrefs_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + idrefs_pimpl:: + idrefs_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void idrefs_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void idrefs_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + idrefs_pskel::_pre (); + } + + string_sequence* idrefs_pimpl:: + post_idrefs () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + +#ifdef XSDE_EXCEPTIONS + void idrefs_pimpl:: + _xsde_parse_item (const ro_string& s) + { + parser_.pre (); + parser_._pre_impl (_context ()); + parser_._characters (s); + parser_._post_impl (); + + // push_back() frees the string if it throws. + // + seq_->push_back (parser_.post_idref ()); + } +#else + void idrefs_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + parser_.pre (); + + if (!parser_._error_type ()) + parser_._pre_impl (ctx); + else + parser_._copy_error (ctx); + + if (!ctx.error_type ()) + parser_._characters (s); + + if (!ctx.error_type ()) + parser_._post_impl (); + + if (!ctx.error_type ()) + { + char* x = parser_.post_idref (); + + if (!parser_._error_type ()) + { + // push_back() frees the string if it fails. + // + if (seq_->push_back (x)) + _sys_error (sys_error::no_memory); + } + else + parser_._copy_error (ctx); + } + } +#endif + } + } + } +} + +#include diff --git a/libxsde/xsde/cxx/parser/non-validating/idrefs.hxx b/libxsde/xsde/cxx/parser/non-validating/idrefs.hxx new file mode 100644 index 0000000..f3d9b99 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/idrefs.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/non-validating/idrefs.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_pimpl: virtual idrefs_pskel +#else + struct idrefs_pimpl: idrefs_pskel +#endif + { + ~idrefs_pimpl (); + idrefs_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual string_sequence* + post_idrefs (); + + virtual void + _reset (); + + protected: + bool base_; + idref_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_IDREFS_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/int.cxx b/libxsde/xsde/cxx/parser/non-validating/int.cxx new file mode 100644 index 0000000..86a9a8b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/int.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void int_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void int_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 11); + } + + int int_pimpl:: + post_int () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + str_[size] = '\0'; + unsigned long ul = strtoul (str_, 0, 10); + + return (sign_ == minus) + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/int.hxx b/libxsde/xsde/cxx/parser/non-validating/int.hxx new file mode 100644 index 0000000..8543909 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/int.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_INT_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_INT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 32-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct int_pimpl: virtual int_pskel, number +#else + struct int_pimpl: int_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual int + post_int (); + + protected: + // We only need strlen("02147483648") + 1 characters to hold all + // valid and trimmed string representations of int. + // + char str_[12]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_INT_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/integer.cxx b/libxsde/xsde/cxx/parser/non-validating/integer.cxx new file mode 100644 index 0000000..dbad0e6 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/integer.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN, LONG_MAX + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void integer_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 20); + } + + long integer_pimpl:: + post_integer () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + unsigned long ul = strtoul (str_, 0, 10); + + return (sign_ == minus) + ? (ul == static_cast (LONG_MIN) + ? LONG_MIN : -static_cast (ul)) + : static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/integer.hxx b/libxsde/xsde/cxx/parser/non-validating/integer.hxx new file mode 100644 index 0000000..94e1754 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/integer.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_INTEGER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Arbitrary-length integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct integer_pimpl: virtual integer_pskel, number +#else + struct integer_pimpl: integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual long + post_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/language-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/language-stl.cxx new file mode 100644 index 0000000..80128ea --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/language-stl.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/language-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void language_pimpl:: + _pre () + { + str_.erase (); + } + + void language_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string language_pimpl:: + post_language () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/language-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/language-stl.hxx new file mode 100644 index 0000000..01dda2d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/language-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/language-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_pimpl: virtual language_pskel +#else + struct language_pimpl: language_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_language (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/language.cxx b/libxsde/xsde/cxx/parser/non-validating/language.cxx new file mode 100644 index 0000000..bcf41b0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/language.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/language.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void language_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void language_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* language_pimpl:: + post_language () + { + ro_string tmp (str_); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/language.hxx b/libxsde/xsde/cxx/parser/non-validating/language.hxx new file mode 100644 index 0000000..cfefe25 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/language.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/language.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_pimpl: virtual language_pskel +#else + struct language_pimpl: language_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_language (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_LANGUAGE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/long-long.cxx b/libxsde/xsde/cxx/parser/non-validating/long-long.cxx new file mode 100644 index 0000000..5501925 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/long-long.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoull + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void long_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 20); + } + + long long long_pimpl:: + post_long () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + unsigned long long ull = strtoull (str_, 0, 10); + + return (sign_ == minus) + ? (ull == 9223372036854775808ULL + ? (-9223372036854775807LL - 1) + : -static_cast (ull)) + : static_cast (ull); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/long-long.hxx b/libxsde/xsde/cxx/parser/non-validating/long-long.hxx new file mode 100644 index 0000000..44669d0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/long-long.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_LONG_LONG_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_LONG_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 64-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_pimpl: virtual long_pskel, number +#else + struct long_pimpl: long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual long long + post_long (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long long. + // + char str_[21]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/long.cxx b/libxsde/xsde/cxx/parser/non-validating/long.cxx new file mode 100644 index 0000000..e1a3beb --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/long.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void long_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 20); + } + + long long_pimpl:: + post_long () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + unsigned long ul = strtoul (str_, 0, 10); + + return (sign_ == minus) + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/long.hxx b/libxsde/xsde/cxx/parser/non-validating/long.hxx new file mode 100644 index 0000000..b51ecd0f --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/long.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_LONG_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_pimpl: virtual long_pskel, number +#else + struct long_pimpl: long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual long + post_long (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long long. + // + char str_[21]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/name-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/name-stl.cxx new file mode 100644 index 0000000..65c3e0a --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/name-stl.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/name-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void name_pimpl:: + _pre () + { + str_.erase (); + } + + void name_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string name_pimpl:: + post_name () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/name-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/name-stl.hxx new file mode 100644 index 0000000..75bbf03 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/name-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/name-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NAME_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_pimpl: virtual name_pskel +#else + struct name_pimpl: name_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_name (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/name.cxx b/libxsde/xsde/cxx/parser/non-validating/name.cxx new file mode 100644 index 0000000..bbc7a2e --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/name.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/name.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void name_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void name_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* name_pimpl:: + post_name () + { + ro_string tmp (str_.data (), str_.size ()); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/name.hxx b/libxsde/xsde/cxx/parser/non-validating/name.hxx new file mode 100644 index 0000000..d10d34d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/name.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/name.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NAME_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_pimpl: virtual name_pskel +#else + struct name_pimpl: name_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_name (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NAME_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/ncname-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/ncname-stl.cxx new file mode 100644 index 0000000..50f2df8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/ncname-stl.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/ncname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void ncname_pimpl:: + _pre () + { + str_.erase (); + } + + void ncname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string ncname_pimpl:: + post_ncname () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/non-validating/ncname-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/ncname-stl.hxx new file mode 100644 index 0000000..a1a1c69 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/ncname-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/ncname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_pimpl: virtual ncname_pskel +#else + struct ncname_pimpl: ncname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_ncname (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/ncname.cxx b/libxsde/xsde/cxx/parser/non-validating/ncname.cxx new file mode 100644 index 0000000..0fffa19 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/ncname.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/ncname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void ncname_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void ncname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* ncname_pimpl:: + post_ncname () + { + ro_string tmp (str_.data (), str_.size ()); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/ncname.hxx b/libxsde/xsde/cxx/parser/non-validating/ncname.hxx new file mode 100644 index 0000000..61a6a65 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/ncname.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/ncname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_pimpl: virtual ncname_pskel +#else + struct ncname_pimpl: ncname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_ncname (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NCNAME_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/negative-integer.cxx b/libxsde/xsde/cxx/parser/non-validating/negative-integer.cxx new file mode 100644 index 0000000..7121020 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/negative-integer.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void negative_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void negative_integer_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 20); + } + + long negative_integer_pimpl:: + post_negative_integer () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + unsigned long ul = strtoul (str_, 0, 10); + + return (ul == static_cast (LONG_MIN)) + ? LONG_MIN : -static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/negative-integer.hxx b/libxsde/xsde/cxx/parser/non-validating/negative-integer.hxx new file mode 100644 index 0000000..b7ee9e0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/negative-integer.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NEGATIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Arbitrary-length negative integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct negative_integer_pimpl: virtual negative_integer_pskel, number +#else + struct negative_integer_pimpl: negative_integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual long + post_negative_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.cxx new file mode 100644 index 0000000..ce9df4b --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/nmtoken-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void nmtoken_pimpl:: + _pre () + { + str_.erase (); + } + + void nmtoken_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string nmtoken_pimpl:: + post_nmtoken () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.hxx new file mode 100644 index 0000000..770bfba --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/nmtoken-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_pimpl: virtual nmtoken_pskel +#else + struct nmtoken_pimpl: nmtoken_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_nmtoken (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx b/libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx new file mode 100644 index 0000000..63888c7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/nmtoken.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void nmtoken_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void nmtoken_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* nmtoken_pimpl:: + post_nmtoken () + { + ro_string tmp (str_.data (), str_.size ()); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx b/libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx new file mode 100644 index 0000000..a76eead --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/nmtoken.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_pimpl: virtual nmtoken_pskel +#else + struct nmtoken_pimpl: nmtoken_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_nmtoken (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NMTOKEN_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.cxx new file mode 100644 index 0000000..5b8186d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.cxx @@ -0,0 +1,90 @@ +// file : xsde/cxx/parser/non-validating/nmtokens-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + nmtokens_pimpl:: + ~nmtokens_pimpl () + { + if (!base_) + delete seq_; + } + + void nmtokens_pimpl:: + _reset () + { + nmtokens_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + nmtokens_pimpl:: + nmtokens_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void nmtokens_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void nmtokens_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + nmtokens_pskel::_pre (); + } + + string_sequence* nmtokens_pimpl:: + post_nmtokens () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void nmtokens_pimpl:: + _xsde_parse_item (const ro_string& s) + { + parser_.pre (); + parser_._pre_impl (_context ()); + parser_._characters (s); + parser_._post_impl (); + seq_->push_back (parser_.post_nmtoken ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.hxx new file mode 100644 index 0000000..8c90877 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/non-validating/nmtokens-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_pimpl: virtual nmtokens_pskel +#else + struct nmtokens_pimpl: nmtokens_pskel +#endif + { + ~nmtokens_pimpl (); + nmtokens_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual string_sequence* + post_nmtokens (); + + virtual void + _reset (); + + protected: + bool base_; + nmtoken_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtokens.cxx b/libxsde/xsde/cxx/parser/non-validating/nmtokens.cxx new file mode 100644 index 0000000..4cf41be --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtokens.cxx @@ -0,0 +1,129 @@ +// file : xsde/cxx/parser/non-validating/nmtokens.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + nmtokens_pimpl:: + ~nmtokens_pimpl () + { + if (!base_) + delete seq_; + } + + void nmtokens_pimpl:: + _reset () + { + nmtokens_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + nmtokens_pimpl:: + nmtokens_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void nmtokens_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void nmtokens_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + nmtokens_pskel::_pre (); + } + + string_sequence* nmtokens_pimpl:: + post_nmtokens () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + +#ifdef XSDE_EXCEPTIONS + void nmtokens_pimpl:: + _xsde_parse_item (const ro_string& s) + { + parser_.pre (); + parser_._pre_impl (_context ()); + parser_._characters (s); + parser_._post_impl (); + + // push_back() frees the string if it throws. + // + seq_->push_back (parser_.post_nmtoken ()); + } +#else + void nmtokens_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + parser_.pre (); + + if (!parser_._error_type ()) + parser_._pre_impl (ctx); + else + parser_._copy_error (ctx); + + if (!ctx.error_type ()) + parser_._characters (s); + + if (!ctx.error_type ()) + parser_._post_impl (); + + if (!ctx.error_type ()) + { + char* x = parser_.post_nmtoken (); + + if (!parser_._error_type ()) + { + // push_back() frees the string if it fails. + // + if (seq_->push_back (x)) + _sys_error (sys_error::no_memory); + } + else + parser_._copy_error (ctx); + } + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/nmtokens.hxx b/libxsde/xsde/cxx/parser/non-validating/nmtokens.hxx new file mode 100644 index 0000000..f8b3a19 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/nmtokens.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/non-validating/nmtokens.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_pimpl: virtual nmtokens_pskel +#else + struct nmtokens_pimpl: nmtokens_pskel +#endif + { + ~nmtokens_pimpl (); + nmtokens_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual string_sequence* + post_nmtokens (); + + virtual void + _reset (); + + protected: + bool base_; + nmtoken_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NMTOKENS_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.cxx b/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.cxx new file mode 100644 index 0000000..463c6c6 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/non-negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void non_negative_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void non_negative_integer_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 21); + } + + unsigned long non_negative_integer_pimpl:: + post_non_negative_integer () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + return strtoul (str_, 0, 10); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.hxx b/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.hxx new file mode 100644 index 0000000..b7cf3f7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/non-negative-integer.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/non-negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Arbitrary-length non-negative integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_negative_integer_pimpl: virtual non_negative_integer_pskel, +#else + struct non_negative_integer_pimpl: non_negative_integer_pskel, +#endif + number + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned long + post_non_negative_integer (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long, assuming we are on a 64 bit machine. + // + char str_[22]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.cxx b/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.cxx new file mode 100644 index 0000000..c218a77 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/non-positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void non_positive_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void non_positive_integer_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 20); + } + + long non_positive_integer_pimpl:: + post_non_positive_integer () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + unsigned long ul = strtoul (str_, 0, 10); + + return (ul == static_cast (LONG_MIN)) + ? LONG_MIN : -static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.hxx b/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.hxx new file mode 100644 index 0000000..a6cefab --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/non-positive-integer.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/non-validating/non-positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Arbitrary-length non-positive integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_positive_integer_pimpl: virtual non_positive_integer_pskel, +#else + struct non_positive_integer_pimpl: non_positive_integer_pskel, +#endif + number + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual long + post_non_positive_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.cxx new file mode 100644 index 0000000..2b1ff1a --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/normalized-string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void normalized_string_pimpl:: + _pre () + { + str_.erase (); + } + + void normalized_string_pimpl:: + _characters (const ro_string& s) + { + str_ += s; + } + + std::string normalized_string_pimpl:: + post_normalized_string () + { + std::string::size_type size = str_.size (); + + for (std::string::size_type i = 0; i < size; ++i) + { + char& c = str_[i]; + + if (c == 0x0A || c == 0x0D || c == 0x09) + c = 0x20; + } + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.hxx new file mode 100644 index 0000000..8544ac3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/normalized-string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_pimpl: virtual normalized_string_pskel +#else + struct normalized_string_pimpl: normalized_string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_normalized_string (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/normalized-string.cxx b/libxsde/xsde/cxx/parser/non-validating/normalized-string.cxx new file mode 100644 index 0000000..b00b6c7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/normalized-string.cxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/parser/non-validating/normalized-string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void normalized_string_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void normalized_string_pimpl:: + _characters (const ro_string& s) + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + + char* normalized_string_pimpl:: + post_normalized_string () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + + for (size_type i = 0; i < size; ++i) + { + char& c = str_[i]; + + if (c == 0x0A || c == 0x0D || c == 0x09) + c = 0x20; + } + + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/normalized-string.hxx b/libxsde/xsde/cxx/parser/non-validating/normalized-string.hxx new file mode 100644 index 0000000..8953729 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/normalized-string.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/normalized-string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_pimpl: virtual normalized_string_pskel +#else + struct normalized_string_pimpl: normalized_string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_normalized_string (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NORMALIZED_STRING_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/number.cxx b/libxsde/xsde/cxx/parser/non-validating/number.cxx new file mode 100644 index 0000000..c271ab5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/number.cxx @@ -0,0 +1,127 @@ +// file : xsde/cxx/parser/non-validating/number.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy + +#include + +using xsde::cxx::ro_string; + +static bool +trim_leading_zeros (ro_string& s) +{ + ro_string::size_type size = s.size (); + + if (size != 0) + { + const char* f = s.data (); + const char* l = f + size; + const char* of = f; + + while (f < l && *f == '0') + ++f; + + if (f != of) + { + s.assign ((f <= l ? f : 0), (f <= l ? l - f : 0)); + return true; + } + } + + return false; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void number:: + parse (const ro_string& s, char* str, size_t max) + { + ro_string tmp (s.data (), s.size ()); + size_t size = tmp.size (); + + switch (state_) + { + case leading_ws: + { + size = trim_left (tmp); + + if (size != 0) + state_ = sign; + else + break; + // Fall through. + } + case sign: + { + if (tmp[0] == '-') + sign_ = minus; + else if (tmp[0] == '+') + sign_ = plus; + + if (sign_ != none) + tmp.assign (tmp.data () + 1, --size); + + if (size != 0) + state_ = leading_zeros; + else + break; + + // Fall through. + } + case leading_zeros: + { + if (trim_leading_zeros (tmp)) + { + if (size_ == 0) + { + str[0] = '0'; + size_ = 1; + } + + size = tmp.size (); + } + + if (size != 0) + state_ = literal; + else + break; + // Fall through. + } + case literal: + { + // If this chunk is too long then it has to be the last so trim + // trailing ws. + // + if ((max - size_) < size) + { + size = trim_right (tmp); + state_ = trailing_ws; // It either had ws or is too large. + } + + if ((max - size_) >= size) + { + memcpy (str + size_, tmp.data (), size); + size_ += size; + } + + break; + } + case trailing_ws: + { + // We don't really care if it is not. + break; + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/number.hxx b/libxsde/xsde/cxx/parser/non-validating/number.hxx new file mode 100644 index 0000000..793f9b9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/number.hxx @@ -0,0 +1,37 @@ +// file : xsde/cxx/parser/non-validating/number.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_NUMBER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_NUMBER_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + class number + { + protected: + void + parse (const ro_string&, char* str, size_t max); + + protected: + size_t size_; + enum {leading_ws, sign, leading_zeros, literal, trailing_ws} state_; + enum {none, plus, minus} sign_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_NUMBER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/parser.cxx b/libxsde/xsde/cxx/parser/non-validating/parser.cxx new file mode 100644 index 0000000..21a15e7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/parser.cxx @@ -0,0 +1,473 @@ +// file : xsde/cxx/parser/non-validating/parser.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // empty_content + // + +#ifdef XSDE_POLYMORPHIC + bool empty_content:: + _start_element_impl (const ro_string&, + const ro_string&, + const char*) + { + return false; + } +#else + bool empty_content:: + _start_element_impl (const ro_string&, + const ro_string&) + { + return false; + } +#endif + + bool empty_content:: + _end_element_impl (const ro_string&, + const ro_string&) + { + return false; + } + + bool empty_content:: + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + bool empty_content:: + _characters_impl (const ro_string&) + { + return false; + } + + // + // +#ifdef XSDE_POLYMORPHIC + void empty_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (!_start_element_impl (ns, name, type)) + _start_any_element (ns, name, type); + } +#else + void empty_content:: + _start_element (const ro_string& ns, + const ro_string& name) + { + if (!_start_element_impl (ns, name)) + _start_any_element (ns, name); + } +#endif + + void empty_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + if (!_end_element_impl (ns, name)) + _end_any_element (ns, name); + } + + static const char + xmlns_namespace_[] = "http://www.w3.org/2000/xmlns/"; + + static const char + xsi_namespace_[] = "http://www.w3.org/2001/XMLSchema-instance"; + + static const char + type_[] = "type"; + + static const char + nil_[] = "nil"; + + static const char + schema_location_[] = "schemaLocation"; + + static const char + no_namespace_schema_location_[] = "noNamespaceSchemaLocation"; + + void empty_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + + void empty_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + _any_characters (s); + } + + + // simple_content + // + + void simple_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + + void simple_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + _any_characters (s); + } + + + // complex_content + // + +#ifdef XSDE_POLYMORPHIC + void complex_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (!_start_element_impl (ns, name, type)) + { + context& c = _context (); + + c.current_.any_ = true; + c.current_.depth_++; + + _start_any_element (ns, name, type); + } + } +#else + void complex_content:: + _start_element (const ro_string& ns, + const ro_string& name) + { + if (!_start_element_impl (ns, name)) + { + context& c = _context (); + + c.current_.any_ = true; + c.current_.depth_++; + + _start_any_element (ns, name); + } + } +#endif + + void complex_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + if (!_end_element_impl (ns, name)) + _end_any_element (ns, name); + } + + void complex_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _any_attribute (ns, name, value); + } + + void complex_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + _any_characters (s); + } + + void complex_content:: + _pre_impl (context& c) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + assert (parent_ == 0); + + // Set the parent_ pointers in the tied-in implementations. + // + _set_parent_chain (); +#endif + if (depth_++ == 0) + context_ = &c; + +#ifdef XSDE_EXCEPTIONS + parser_stack_.push (c.current_); +#else + if (parser_stack_.push (c.current_)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + c.current_.parser_ = this; + c.current_.depth_ = 0; + c.current_.any_ = false; + + _pre (); + } + + void complex_content:: + _post_impl () + { +#ifndef XSDE_EXCEPTIONS + if (!context_->error_type ()) +#endif + _post (); + + context_->current_ = parser_stack_.top (); + parser_stack_.pop (); + + if (--depth_ == 0) + context_ = 0; + } + + void complex_content:: + _reset () + { + empty_content::_reset (); + + depth_ = 0; + parser_stack_.clear (); + } + + // list_base + // + + // Find first non-space character. + // + static ro_string::size_type + find_ns (const char* s, + ro_string::size_type size, + ro_string::size_type pos) + { + while (pos < size && + (s[pos] == 0x20 || s[pos] == 0x0A || + s[pos] == 0x0D || s[pos] == 0x09)) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + + // Find first space character. + // + static ro_string::size_type + find_s (const char* s, + ro_string::size_type size, + ro_string::size_type pos) + { + while (pos < size && + s[pos] != 0x20 && s[pos] != 0x0A && + s[pos] != 0x0D && s[pos] != 0x09) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + + // Relevant XML Schema Part 2: Datatypes sections: 4.2.1.2, 4.3.6. + // + + void list_base:: + _pre_impl (context& c) + { + simple_content::_pre_impl (c); + +#ifdef XSDE_EXCEPTIONS + buf_.assign ("", 0); +#else + if (!c.error_type ()) + { + if (buf_.assign ("", 0)) + _sys_error (sys_error::no_memory); + } +#endif + } + + void list_base:: + _characters (const ro_string& s) + { + typedef ro_string::size_type size_type; + + const char* data = s.data (); + size_type size = s.size (); + + // Handle the previous chunk if we start with a ws. + // + if (!buf_.empty () && + (data[0] == 0x20 || data[0] == 0x0A || + data[0] == 0x0D || data[0] == 0x09)) + { + ro_string tmp (buf_); // Private copy ctor. + _xsde_parse_item (tmp); + buf_.assign ("", 0); // Can't fail. + } + +#ifndef XSDE_EXCEPTIONS + context& ctx = _context (); +#endif + + // Traverse the data while logically collapsing spaces. + // + for (size_type i = find_ns (data, size, 0); i != ro_string::npos;) + { + size_type j = find_s (data, size, i); + + if (j != ro_string::npos) + { + if (buf_.empty ()) + { + ro_string tmp (data + i, j - i); // Private copy ctor. + _xsde_parse_item (tmp); + } + else + { + // Assemble the first item in str from buf_ and s. + // + string str; + str.swap (buf_); + +#ifdef XSDE_EXCEPTIONS + str.append (data + i, j - i); +#else + if (str.append (data + i, j - i)) + { + _sys_error (sys_error::no_memory); + break; + } +#endif + ro_string tmp (str); // Private copy ctor. + _xsde_parse_item (tmp); + } + +#ifndef XSDE_EXCEPTIONS + if (ctx.error_type ()) + break; +#endif + + i = find_ns (data, size, j); + } + else + { + // Last fragment, append it to buf_. + // +#ifdef XSDE_EXCEPTIONS + buf_.append (data + i, size - i); +#else + if (buf_.append (data + i, size - i)) + _sys_error (sys_error::no_memory); +#endif + break; + } + } + } + + void list_base:: + _xsde_parse_item (const ro_string&) + { + } + + void list_base:: + _post_impl () + { + // Handle the last item. + // + if (!buf_.empty ()) + { + ro_string tmp (buf_); // Private copy ctor. + _xsde_parse_item (tmp); + } + + simple_content::_post_impl (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/parser.hxx b/libxsde/xsde/cxx/parser/non-validating/parser.hxx new file mode 100644 index 0000000..6b9889a --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/parser.hxx @@ -0,0 +1,196 @@ +// file : xsde/cxx/parser/non-validating/parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_PARSER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_PARSER_HXX + +#include + +#include // size_t + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + struct empty_content: parser_base + { + // + // +#ifdef XSDE_POLYMORPHIC + virtual bool + _start_element_impl (const ro_string&, + const ro_string&, + const char*); +#else + virtual bool + _start_element_impl (const ro_string&, + const ro_string&); +#endif + + virtual bool + _end_element_impl (const ro_string&, + const ro_string&); + + virtual bool + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&); + + virtual bool + _characters_impl (const ro_string&); + + + // + // +#ifdef XSDE_POLYMORPHIC + virtual void + _start_element (const ro_string&, + const ro_string&, + const char*); +#else + virtual void + _start_element (const ro_string&, + const ro_string&); +#endif + + virtual void + _end_element (const ro_string&, + const ro_string&); + + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + empty_content (); + empty_content (empty_content* impl, void*); +#endif + }; + + + // + // + struct simple_content: empty_content + { + // + // + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + simple_content (); + simple_content (simple_content* impl, void*); +#endif + }; + + + // + // + struct complex_content: empty_content + { +#ifdef XSDE_POLYMORPHIC + virtual void + _start_element (const ro_string&, + const ro_string&, + const char*); +#else + virtual void + _start_element (const ro_string&, + const ro_string&); +#endif + virtual void + _end_element (const ro_string&, + const ro_string&); + + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + + // + // + virtual void + _pre_impl (context&); + + virtual void + _post_impl (); + + // + // + virtual void + _reset (); + + // + // + complex_content (); + +#ifdef XSDE_REUSE_STYLE_TIEIN + complex_content (complex_content* impl, void*); +#endif + protected: + size_t depth_; + parser_stack parser_stack_; + }; + + // Base for xsd:list. + // + struct list_base: simple_content + { + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _pre_impl (context&); + + virtual void + _characters (const ro_string&); + + virtual void + _post_impl (); + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + list_base (); + list_base (list_base* impl, void*); +#endif + protected: + string buf_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_PARSER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/parser.ixx b/libxsde/xsde/cxx/parser/non-validating/parser.ixx new file mode 100644 index 0000000..95f085d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/parser.ixx @@ -0,0 +1,77 @@ +// file : xsde/cxx/parser/non-validating/parser.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // empty_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline empty_content:: + empty_content () + { + } + + inline empty_content:: + empty_content (empty_content* impl, void*) + : parser_base (impl, 0) + { + } +#endif + + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline simple_content:: + simple_content () + { + } + + inline simple_content:: + simple_content (simple_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + + // complex_content + // + inline complex_content:: + complex_content () + : depth_ (0), parser_stack_ (previous_) + { + } + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline complex_content:: + complex_content (complex_content* impl, void*) + : empty_content (impl, 0), depth_ (0), parser_stack_ (previous_) + { + } +#endif + + // list_base + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline list_base:: + list_base () + { + } + + inline list_base:: + list_base (list_base* impl, void*) + : simple_content (impl, 0) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/positive-integer.cxx b/libxsde/xsde/cxx/parser/non-validating/positive-integer.cxx new file mode 100644 index 0000000..47f9852 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/positive-integer.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void positive_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void positive_integer_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 21); + } + + unsigned long positive_integer_pimpl:: + post_positive_integer () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + return strtoul (str_, 0, 10); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/positive-integer.hxx b/libxsde/xsde/cxx/parser/non-validating/positive-integer.hxx new file mode 100644 index 0000000..fc326e4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/positive-integer.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_POSITIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_POSITIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Arbitrary-length positive integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct positive_integer_pimpl: virtual positive_integer_pskel, number +#else + struct positive_integer_pimpl: positive_integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned long + post_positive_integer (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long, assuming we are on a 64 bit machine. + // + char str_[22]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/qname-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/qname-stl.cxx new file mode 100644 index 0000000..746959a --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/qname-stl.cxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/parser/non-validating/qname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void qname_pimpl:: + _pre () + { + str_.erase (); + } + + void qname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + qname qname_pimpl:: + post_qname () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + ro_string::size_type pos = tmp.find (':'); + + if (pos != ro_string::npos) + { + std::string prefix (tmp.data (), pos); + std::string name (tmp.data () + pos + 1, size - pos - 1); + return qname (prefix, name); + } + else + { + str_.resize (size); + return qname (str_); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/qname-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/qname-stl.hxx new file mode 100644 index 0000000..7671400 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/qname-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/qname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_QNAME_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_QNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_pimpl: virtual qname_pskel +#else + struct qname_pimpl: qname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual qname + post_qname (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_QNAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/qname.cxx b/libxsde/xsde/cxx/parser/non-validating/qname.cxx new file mode 100644 index 0000000..87f03e8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/qname.cxx @@ -0,0 +1,153 @@ +// file : xsde/cxx/parser/non-validating/qname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + qname_pimpl:: + ~qname_pimpl () + { + if (!base_) + delete qn_; + } + + void qname_pimpl:: + _reset () + { + qname_pskel::_reset (); + + if (!base_) + { + delete qn_; + qn_ = 0; + } + } + + qname_pimpl:: + qname_pimpl (bool base) + : base_ (base), qn_ (0) + { + } + + void qname_pimpl:: + pre_impl (qname* qn) + { + qn_ = qn; + } + + void qname_pimpl:: + _pre () + { + if (qn_ == 0) + { + qn_ = new qname (); + +#ifndef XSDE_EXCEPTIONS + if (qn_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void qname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + qname* qname_pimpl:: + post_qname () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + ro_string::size_type pos = tmp.find (':'); + + const char* s = tmp.data (); + + string prefix; + string name; + + if (pos != ro_string::npos) + { +#ifdef XSDE_EXCEPTIONS + prefix.assign (s, pos); + name.assign (s + pos + 1, size - pos - 1); +#else + if (prefix.assign (s, pos) || + name.assign (s + pos + 1, size - pos - 1)) + { + _sys_error (sys_error::no_memory); + return 0; + } +#endif + } + else + { +#ifdef XSDE_EXCEPTIONS + prefix.assign ("", 0); +#else + if (prefix.assign ("", 0)) + { + _sys_error (sys_error::no_memory); + return 0; + } +#endif + str_.truncate (size); + name.swap (str_); + } + + qn_->prefix (prefix.detach ()); + qn_->name (name.detach ()); + + qname* r = qn_; + qn_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/qname.hxx b/libxsde/xsde/cxx/parser/non-validating/qname.hxx new file mode 100644 index 0000000..257eaf4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/qname.hxx @@ -0,0 +1,55 @@ +// file : xsde/cxx/parser/non-validating/qname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_QNAME_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_QNAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_pimpl: virtual qname_pskel +#else + struct qname_pimpl: qname_pskel +#endif + { + ~qname_pimpl (); + qname_pimpl (bool base = false); + + void + pre_impl (qname*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual qname* + post_qname (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + qname* qn_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_QNAME_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/short.cxx b/libxsde/xsde/cxx/parser/non-validating/short.cxx new file mode 100644 index 0000000..70f401d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/short.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void short_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void short_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 6); + } + + short short_pimpl:: + post_short () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + str_[size] = '\0'; + unsigned long ul = strtoul (str_, 0, 10); + + return (sign_ == minus) + ? static_cast (-static_cast (ul)) + : static_cast (ul); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/short.hxx b/libxsde/xsde/cxx/parser/non-validating/short.hxx new file mode 100644 index 0000000..8417a94 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/short.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_SHORT_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_SHORT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 16-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct short_pimpl: virtual short_pskel, number +#else + struct short_pimpl: short_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual short + post_short (); + + protected: + // We only need strlen("032768") + 1 characters to hold all valid + // and trimmed string representations of short. + // + char str_[7]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_SHORT_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/string-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/string-stl.cxx new file mode 100644 index 0000000..7864648 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/string-stl.cxx @@ -0,0 +1,38 @@ +// file : xsde/cxx/parser/non-validating/string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void string_pimpl:: + _pre () + { + str_.erase (); + } + + void string_pimpl:: + _characters (const ro_string& s) + { + str_ += s; + } + + std::string string_pimpl:: + post_string () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/string-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/string-stl.hxx new file mode 100644 index 0000000..aaab4ba --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/string-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_STRING_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_pimpl: virtual string_pskel +#else + struct string_pimpl: string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_string (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/string.cxx b/libxsde/xsde/cxx/parser/non-validating/string.cxx new file mode 100644 index 0000000..9d5f083 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/string.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void string_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void string_pimpl:: + _characters (const ro_string& s) + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + + char* string_pimpl:: + post_string () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/string.hxx b/libxsde/xsde/cxx/parser/non-validating/string.hxx new file mode 100644 index 0000000..de48551 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/string.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_STRING_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_STRING_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_pimpl: virtual string_pskel +#else + struct string_pimpl: string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_string (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_STRING_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/time-zone.cxx b/libxsde/xsde/cxx/parser/non-validating/time-zone.cxx new file mode 100644 index 0000000..3465045 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/time-zone.cxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/non-validating/time-zone.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + namespace bits + { + void + parse_time_zone (const char* s, size_t n, short& h, short& m) + { + // time_zone := Z|(+|-)HH:MM + // + if (n == 0) + { + return; + } + else if (s[0] == 'Z') + { + h = 0; + m = 0; + } + else if (n == 6) + { + // Parse hours. + // + h = 10 * (s[1] - '0') + (s[2] - '0'); + + // Parse minutes. + // + m = 10 * (s[4] - '0') + (s[5] - '0'); + + if (s[0] == '-') + { + h = -h; + m = -m; + } + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/time-zone.hxx b/libxsde/xsde/cxx/parser/non-validating/time-zone.hxx new file mode 100644 index 0000000..9a3363c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/time-zone.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/parser/non-validating/time-zone.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_TIME_ZONE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_TIME_ZONE_HXX + +#include // size_t + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + namespace bits + { + void + parse_time_zone (const char* s, + size_t size, + short& hours, + short& minutes); + } + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_TIME_ZONE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/time.cxx b/libxsde/xsde/cxx/parser/non-validating/time.cxx new file mode 100644 index 0000000..a2ad5d3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/time.cxx @@ -0,0 +1,118 @@ +// file : xsde/cxx/parser/non-validating/time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void time_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void time_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + time time_pimpl:: + post_time () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] + // + unsigned short hours = 0; + unsigned short minutes = 0; + double seconds = 0.0; + bool zone = false; + short zh, zm; + + if (n >= 8) + { + // hours + // + hours = 10 * (s[0] - '0') + (s[1] - '0'); + + // minutes + // + minutes = 10 * (s[3] - '0') + (s[4] - '0'); + + // Find the end of the seconds fragment. + // + ro_string::size_type pos = 8; + for (; pos < n; ++pos) + { + char c = s[pos]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // Parse the time zone first so that we can truncate and + // reuse the string. + // + if (pos < n) + { + bits::parse_time_zone (s + pos, n - pos, zh, zm); + zone = true; + } + + // seconds + // + str_.truncate (pos); + seconds = strtod (s + 6, 0); + } + + return zone + ? time (hours, minutes, seconds, zh, zm) + : time (hours, minutes, seconds); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/time.hxx b/libxsde/xsde/cxx/parser/non-validating/time.hxx new file mode 100644 index 0000000..7526414 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/time.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_TIME_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_TIME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct time_pimpl: virtual time_pskel +#else + struct time_pimpl: time_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual time + post_time (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_TIME_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/token-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/token-stl.cxx new file mode 100644 index 0000000..e975ae3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/token-stl.cxx @@ -0,0 +1,73 @@ +// file : xsde/cxx/parser/non-validating/token-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void token_pimpl:: + _pre () + { + str_.erase (); + } + + void token_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string token_pimpl:: + post_token () + { + std::string::size_type size = str_.size (); + std::string::size_type j = 0; + + bool subs = false; + + for (std::string::size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + { + subs = false; + str_[j++] = 0x20; + } + + str_[j++] = c; + } + } + + str_.resize (j); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/token-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/token-stl.hxx new file mode 100644 index 0000000..0f3a288 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/token-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/token-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_pimpl: virtual token_pskel +#else + struct token_pimpl: token_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_token (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/token.cxx b/libxsde/xsde/cxx/parser/non-validating/token.cxx new file mode 100644 index 0000000..ffc1b4d --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/token.cxx @@ -0,0 +1,94 @@ +// file : xsde/cxx/parser/non-validating/token.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void token_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void token_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* token_pimpl:: + post_token () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + size_type j = 0; + + bool subs = false; + + for (size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + { + subs = false; + str_[j++] = 0x20; + } + + str_[j++] = c; + } + } + + str_.truncate (j); + + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/token.hxx b/libxsde/xsde/cxx/parser/non-validating/token.hxx new file mode 100644 index 0000000..22d9f59 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/token.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/token.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_pimpl: virtual token_pskel +#else + struct token_pimpl: token_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_token (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_TOKEN_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.cxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.cxx new file mode 100644 index 0000000..11e6dd5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/unsigned-byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void unsigned_byte_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_byte_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 4); + } + + unsigned char unsigned_byte_pimpl:: + post_unsigned_byte () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + str_[size] = '\0'; + return static_cast (strtoul (str_, 0, 10)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.hxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.hxx new file mode 100644 index 0000000..ed54cd0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-byte.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/unsigned-byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_BYTE_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_BYTE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 8-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_byte_pimpl: virtual unsigned_byte_pskel, number +#else + struct unsigned_byte_pimpl: unsigned_byte_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned char + post_unsigned_byte (); + + protected: + // We only need strlen("0256") + 1 characters to hold all valid + // and trimmed string representations of unsigned byte. + // + char str_[5]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_BYTE_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-int.cxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-int.cxx new file mode 100644 index 0000000..e14e091 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-int.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/unsigned-int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void unsigned_int_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_int_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 11); + } + + unsigned int unsigned_int_pimpl:: + post_unsigned_int () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + return static_cast (strtoul (str_, 0, 10)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-int.hxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-int.hxx new file mode 100644 index 0000000..4cce2b0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-int.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/unsigned-int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_INT_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_INT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 32-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_int_pimpl: virtual unsigned_int_pskel, number +#else + struct unsigned_int_pimpl: unsigned_int_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned int + post_unsigned_int (); + + protected: + // We only need strlen("04294967295") + 1 characters to hold all + // valid and trimmed string representations of unsigned int. + // + char str_[12]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_INT_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.cxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.cxx new file mode 100644 index 0000000..908066c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/unsigned-long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoull + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void unsigned_long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_long_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 21); + } + + unsigned long long unsigned_long_pimpl:: + post_unsigned_long () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + return strtoull (str_, 0, 10); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.hxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.hxx new file mode 100644 index 0000000..8957135 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/unsigned-long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 64-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_pimpl: virtual unsigned_long_pskel, number +#else + struct unsigned_long_pimpl: unsigned_long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned long long + post_unsigned_long (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long long. + // + char str_[22]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-long.cxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-long.cxx new file mode 100644 index 0000000..8f70812 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-long.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/unsigned-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void unsigned_long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_long_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 21); + } + + unsigned long unsigned_long_pimpl:: + post_unsigned_long () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + str_[size] = '\0'; + + return strtoul (str_, 0, 10); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-long.hxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-long.hxx new file mode 100644 index 0000000..45c976f --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-long.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/unsigned-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_pimpl: virtual unsigned_long_pskel, number +#else + struct unsigned_long_pimpl: unsigned_long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned long + post_unsigned_long (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long long. + // + char str_[22]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-short.cxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-short.cxx new file mode 100644 index 0000000..2044611 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-short.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/unsigned-short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void unsigned_short_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_short_pimpl:: + _characters (const ro_string& s) + { + parse (s, str_, 6); + } + + unsigned short unsigned_short_pimpl:: + post_unsigned_short () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + str_[size] = '\0'; + return static_cast (strtoul (str_, 0, 10)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/unsigned-short.hxx b/libxsde/xsde/cxx/parser/non-validating/unsigned-short.hxx new file mode 100644 index 0000000..26b97ce --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/unsigned-short.hxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/non-validating/unsigned-short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_SHORT_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_SHORT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // 16-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_short_pimpl: virtual unsigned_short_pskel, number +#else + struct unsigned_short_pimpl: unsigned_short_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual unsigned short + post_unsigned_short (); + + protected: + // We only need strlen("065535") + 1 characters to hold all valid + // and trimmed string representations of unsigned short. + // + char str_[7]; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_UNSIGNED_SHORT_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx b/libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx new file mode 100644 index 0000000..369f448 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/non-validating/uri-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void uri_pimpl:: + _pre () + { + str_.erase (); + } + + void uri_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string uri_pimpl:: + post_uri () + { + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx b/libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx new file mode 100644 index 0000000..351c513 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/uri-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_URI_STL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_URI_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_pimpl: virtual uri_pskel +#else + struct uri_pimpl: uri_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_uri (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_URI_STL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/uri.cxx b/libxsde/xsde/cxx/parser/non-validating/uri.cxx new file mode 100644 index 0000000..2edb794 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/uri.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/parser/non-validating/uri.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + void uri_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void uri_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* uri_pimpl:: + post_uri () + { + ro_string tmp (str_); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/non-validating/uri.hxx b/libxsde/xsde/cxx/parser/non-validating/uri.hxx new file mode 100644 index 0000000..245c493 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/uri.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/non-validating/uri.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_URI_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_URI_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_pimpl: virtual uri_pskel +#else + struct uri_pimpl: uri_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_uri (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_URI_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx new file mode 100644 index 0000000..e51cff0 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx @@ -0,0 +1,82 @@ +// file : xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PIMPL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PIMPL_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_LONGLONG +# include +# include +#else +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_STL +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PIMPL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.cxx b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.cxx new file mode 100644 index 0000000..39138a1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.cxx @@ -0,0 +1,612 @@ +// file : xsde/cxx/parser/non-validating/xml-schema-pskel.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // any_type and any_simple_type + // + // In non-validating case we can simply return false from *_impl + // functions which will result in calls to the corresponding + // _any_* callbacks. + // + // + +#ifdef XSDE_POLYMORPHIC + bool any_type_pskel:: + _start_element_impl (const ro_string&, + const ro_string&, + const char*) + { + return false; + } +#else + bool any_type_pskel:: + _start_element_impl (const ro_string&, const ro_string&) + { + return false; + } +#endif + + + bool any_type_pskel:: + _end_element_impl (const ro_string&, const ro_string&) + { + return false; + } + + bool any_type_pskel:: + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + bool any_type_pskel:: + _characters_impl (const ro_string&) + { + return false; + } + + void any_type_pskel:: + post_any_type () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_type_impl_) + any_type_impl_->post_any_type (); +#endif + } + + // any_simple_type + // + + bool any_simple_type_pskel:: + _characters_impl (const ro_string&) + { + return false; + } + + void any_simple_type_pskel:: + post_any_simple_type () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_simple_type_impl_) + any_simple_type_impl_->post_any_simple_type (); +#endif + } + + // static/dynamic_type function implementations. + // + +#ifdef XSDE_POLYMORPHIC + const char* any_type_pskel:: + _static_type () + { + return "anyType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_type_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* any_simple_type_pskel:: + _static_type () + { + return "anySimpleType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_simple_type_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* boolean_pskel:: + _static_type () + { + return "boolean http://www.w3.org/2001/XMLSchema"; + } + + const char* boolean_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* byte_pskel:: + _static_type () + { + return "byte http://www.w3.org/2001/XMLSchema"; + } + + const char* byte_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_byte_pskel:: + _static_type () + { + return "unsignedByte http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_byte_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* short_pskel:: + _static_type () + { + return "short http://www.w3.org/2001/XMLSchema"; + } + + const char* short_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_short_pskel:: + _static_type () + { + return "unsignedShort http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_short_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* int_pskel:: + _static_type () + { + return "int http://www.w3.org/2001/XMLSchema"; + } + + const char* int_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_int_pskel:: + _static_type () + { + return "unsignedInt http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_int_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* long_pskel:: + _static_type () + { + return "long http://www.w3.org/2001/XMLSchema"; + } + + const char* long_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_long_pskel:: + _static_type () + { + return "unsignedLong http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_long_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* integer_pskel:: + _static_type () + { + return "integer http://www.w3.org/2001/XMLSchema"; + } + + const char* integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* negative_integer_pskel:: + _static_type () + { + return "negativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* negative_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_positive_integer_pskel:: + _static_type () + { + return "nonPositiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_positive_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* positive_integer_pskel:: + _static_type () + { + return "positiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* positive_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_negative_integer_pskel:: + _static_type () + { + return "nonNegativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_negative_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* float_pskel:: + _static_type () + { + return "float http://www.w3.org/2001/XMLSchema"; + } + + const char* float_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* double_pskel:: + _static_type () + { + return "double http://www.w3.org/2001/XMLSchema"; + } + + const char* double_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* decimal_pskel:: + _static_type () + { + return "decimal http://www.w3.org/2001/XMLSchema"; + } + + const char* decimal_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* string_pskel:: + _static_type () + { + return "string http://www.w3.org/2001/XMLSchema"; + } + + const char* string_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* normalized_string_pskel:: + _static_type () + { + return "normalizedString http://www.w3.org/2001/XMLSchema"; + } + + const char* normalized_string_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* token_pskel:: + _static_type () + { + return "token http://www.w3.org/2001/XMLSchema"; + } + + const char* token_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* name_pskel:: + _static_type () + { + return "Name http://www.w3.org/2001/XMLSchema"; + } + + const char* name_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtoken_pskel:: + _static_type () + { + return "NMTOKEN http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtoken_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtokens_pskel:: + _static_type () + { + return "NMTOKENS http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtokens_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* ncname_pskel:: + _static_type () + { + return "NCName http://www.w3.org/2001/XMLSchema"; + } + + const char* ncname_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* id_pskel:: + _static_type () + { + return "ID http://www.w3.org/2001/XMLSchema"; + } + + const char* id_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idref_pskel:: + _static_type () + { + return "IDREF http://www.w3.org/2001/XMLSchema"; + } + + const char* idref_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idrefs_pskel:: + _static_type () + { + return "IDREFS http://www.w3.org/2001/XMLSchema"; + } + + const char* idrefs_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* language_pskel:: + _static_type () + { + return "language http://www.w3.org/2001/XMLSchema"; + } + + const char* language_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* uri_pskel:: + _static_type () + { + return "anyURI http://www.w3.org/2001/XMLSchema"; + } + + const char* uri_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* qname_pskel:: + _static_type () + { + return "QName http://www.w3.org/2001/XMLSchema"; + } + + const char* qname_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* base64_binary_pskel:: + _static_type () + { + return "base64Binary http://www.w3.org/2001/XMLSchema"; + } + + const char* base64_binary_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* hex_binary_pskel:: + _static_type () + { + return "hexBinary http://www.w3.org/2001/XMLSchema"; + } + + const char* hex_binary_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gday_pskel:: + _static_type () + { + return "gDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gday_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_pskel:: + _static_type () + { + return "gMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_pskel:: + _static_type () + { + return "gYear http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_day_pskel:: + _static_type () + { + return "gMonthDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_day_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_month_pskel:: + _static_type () + { + return "gYearMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_month_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_pskel:: + _static_type () + { + return "date http://www.w3.org/2001/XMLSchema"; + } + + const char* date_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* time_pskel:: + _static_type () + { + return "time http://www.w3.org/2001/XMLSchema"; + } + + const char* time_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_time_pskel:: + _static_type () + { + return "dateTime http://www.w3.org/2001/XMLSchema"; + } + + const char* date_time_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* duration_pskel:: + _static_type () + { + return "duration http://www.w3.org/2001/XMLSchema"; + } + + const char* duration_pskel:: + _dynamic_type () const + { + return _static_type (); + } +#endif // XSDE_POLYMORPHIC + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.hxx b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.hxx new file mode 100644 index 0000000..0792936 --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.hxx @@ -0,0 +1,1388 @@ +// file : xsde/cxx/parser/non-validating/xml-schema-pskel.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PSKEL_HXX +#define XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PSKEL_HXX + +#include + +#ifdef XSDE_STL +# include +#endif + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // anyType and anySimpleType. All events are routed to the + // _any_* callbacks. + // + + struct any_type_pskel: complex_content + { +#ifdef XSDE_POLYMORPHIC + virtual bool + _start_element_impl (const ro_string&, + const ro_string&, + const char*); +#else + virtual bool + _start_element_impl (const ro_string&, + const ro_string&); +#endif + virtual bool + _end_element_impl (const ro_string&, + const ro_string&); + + virtual bool + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&); + + virtual bool + _characters_impl (const ro_string&); + + virtual void + post_any_type (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_type_pskel (); + any_type_pskel (any_type_pskel* impl, void*); + + protected: + any_type_pskel* any_type_impl_; +#endif + }; + + struct any_simple_type_pskel: simple_content + { + virtual bool + _characters_impl (const ro_string&); + + virtual void + post_any_simple_type (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_simple_type_pskel (); + any_simple_type_pskel (any_simple_type_pskel* impl, void*); + + protected: + any_simple_type_pskel* any_simple_type_impl_; +#endif + }; + + + // Boolean. + // + + struct boolean_pskel: simple_content + { + virtual bool + post_boolean () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + boolean_pskel (); + boolean_pskel (boolean_pskel* impl, void*); + + protected: + boolean_pskel* boolean_impl_; +#endif + }; + + + // 8-bit + // + struct byte_pskel: simple_content + { + virtual signed char + post_byte () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + byte_pskel (); + byte_pskel (byte_pskel* impl, void*); + + protected: + byte_pskel* byte_impl_; +#endif + }; + + struct unsigned_byte_pskel: simple_content + { + virtual unsigned char + post_unsigned_byte () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_byte_pskel (); + unsigned_byte_pskel (unsigned_byte_pskel* impl, void*); + + protected: + unsigned_byte_pskel* unsigned_byte_impl_; +#endif + }; + + + // 16-bit + // + + struct short_pskel: simple_content + { + virtual short + post_short () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + short_pskel (); + short_pskel (short_pskel* impl, void*); + + protected: + short_pskel* short_impl_; +#endif + }; + + struct unsigned_short_pskel: simple_content + { + virtual unsigned short + post_unsigned_short () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_short_pskel (); + unsigned_short_pskel (unsigned_short_pskel* impl, void*); + + protected: + unsigned_short_pskel* unsigned_short_impl_; +#endif + }; + + + // 32-bit + // + + struct int_pskel: simple_content + { + virtual int + post_int () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + int_pskel (); + int_pskel (int_pskel* impl, void*); + + protected: + int_pskel* int_impl_; +#endif + }; + + struct unsigned_int_pskel: simple_content + { + virtual unsigned int + post_unsigned_int () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_int_pskel (); + unsigned_int_pskel (unsigned_int_pskel* impl, void*); + + protected: + unsigned_int_pskel* unsigned_int_impl_; +#endif + }; + + + // 64-bit + // +#ifdef XSDE_LONGLONG + + struct long_pskel: simple_content + { + virtual long long + post_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_pskel (); + long_pskel (long_pskel* impl, void*); + + protected: + long_pskel* long_impl_; +#endif + }; + + struct unsigned_long_pskel: simple_content + { + virtual unsigned long long + post_unsigned_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_pskel (); + unsigned_long_pskel (unsigned_long_pskel* impl, void*); + + protected: + unsigned_long_pskel* unsigned_long_impl_; +#endif + }; + +#else + + struct long_pskel: simple_content + { + virtual long + post_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_pskel (); + long_pskel (long_pskel* impl, void*); + + protected: + long_pskel* long_impl_; +#endif + }; + + struct unsigned_long_pskel: simple_content + { + virtual unsigned long + post_unsigned_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_pskel (); + unsigned_long_pskel (unsigned_long_pskel* impl, void*); + + protected: + unsigned_long_pskel* unsigned_long_impl_; +#endif + }; +#endif + + + // Arbitrary-length integers. + // + + struct integer_pskel: simple_content + { + virtual long + post_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + integer_pskel (); + integer_pskel (integer_pskel* impl, void*); + + protected: + integer_pskel* integer_impl_; +#endif + }; + + struct negative_integer_pskel: simple_content + { + virtual long + post_negative_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + negative_integer_pskel (); + negative_integer_pskel (negative_integer_pskel* impl, void*); + + protected: + negative_integer_pskel* negative_integer_impl_; +#endif + }; + + struct non_positive_integer_pskel: simple_content + { + virtual long + post_non_positive_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_positive_integer_pskel (); + non_positive_integer_pskel (non_positive_integer_pskel* impl, void*); + + protected: + non_positive_integer_pskel* non_positive_integer_impl_; +#endif + }; + + struct positive_integer_pskel: simple_content + { + virtual unsigned long + post_positive_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + positive_integer_pskel (); + positive_integer_pskel (positive_integer_pskel* impl, void*); + + protected: + positive_integer_pskel* positive_integer_impl_; +#endif + }; + + struct non_negative_integer_pskel: simple_content + { + virtual unsigned long + post_non_negative_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_negative_integer_pskel (); + non_negative_integer_pskel (non_negative_integer_pskel* impl, void*); + + protected: + non_negative_integer_pskel* non_negative_integer_impl_; +#endif + }; + + + // Floats. + // + + struct float_pskel: simple_content + { + virtual float + post_float () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + float_pskel (); + float_pskel (float_pskel* impl, void*); + + protected: + float_pskel* float_impl_; +#endif + }; + + struct double_pskel: simple_content + { + virtual double + post_double () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + double_pskel (); + double_pskel (double_pskel* impl, void*); + + protected: + double_pskel* double_impl_; +#endif + }; + + struct decimal_pskel: simple_content + { + virtual double + post_decimal () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + decimal_pskel (); + decimal_pskel (decimal_pskel* impl, void*); + + protected: + decimal_pskel* decimal_impl_; +#endif + }; + + + // String-based types. + // +#ifdef XSDE_STL + + struct string_pskel: simple_content + { + virtual std::string + post_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_pskel (); + string_pskel (string_pskel* impl, void*); + + protected: + string_pskel* string_impl_; +#endif + }; + + struct normalized_string_pskel: simple_content + { + virtual std::string + post_normalized_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_pskel (); + normalized_string_pskel (normalized_string_pskel* impl, void*); + + protected: + normalized_string_pskel* normalized_string_impl_; +#endif + }; + + struct token_pskel: simple_content + { + virtual std::string + post_token () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_pskel (); + token_pskel (token_pskel* impl, void*); + + protected: + token_pskel* token_impl_; +#endif + }; + + struct name_pskel: simple_content + { + virtual std::string + post_name () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_pskel (); + name_pskel (name_pskel* impl, void*); + + protected: + name_pskel* name_impl_; +#endif + }; + + struct nmtoken_pskel: simple_content + { + virtual std::string + post_nmtoken () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_pskel (); + nmtoken_pskel (nmtoken_pskel* impl, void*); + + protected: + nmtoken_pskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_pskel: list_base + { + virtual string_sequence* + post_nmtokens () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_pskel (); + nmtokens_pskel (nmtokens_pskel* impl, void*); + + protected: + nmtokens_pskel* nmtokens_impl_; +#endif + }; + + struct ncname_pskel: simple_content + { + virtual std::string + post_ncname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_pskel (); + ncname_pskel (ncname_pskel* impl, void*); + + protected: + ncname_pskel* ncname_impl_; +#endif + }; + + struct id_pskel: simple_content + { + virtual std::string + post_id () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_pskel (); + id_pskel (id_pskel* impl, void*); + + protected: + id_pskel* id_impl_; +#endif + }; + + struct idref_pskel: simple_content + { + virtual std::string + post_idref () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_pskel (); + idref_pskel (idref_pskel* impl, void*); + + protected: + idref_pskel* idref_impl_; +#endif + }; + + struct idrefs_pskel: list_base + { + virtual string_sequence* + post_idrefs () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_pskel (); + idrefs_pskel (idrefs_pskel* impl, void*); + + protected: + idrefs_pskel* idrefs_impl_; +#endif + }; + + struct language_pskel: simple_content + { + virtual std::string + post_language () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_pskel (); + language_pskel (language_pskel* impl, void*); + + protected: + language_pskel* language_impl_; +#endif + }; + + struct uri_pskel: simple_content + { + virtual std::string + post_uri () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_pskel (); + uri_pskel (uri_pskel* impl, void*); + + protected: + uri_pskel* uri_impl_; +#endif + }; + + struct qname_pskel: simple_content + { + virtual qname + post_qname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_pskel (); + qname_pskel (qname_pskel* impl, void*); + + protected: + qname_pskel* qname_impl_; +#endif + }; + +#else // XSDE_STL + + // Note that in this case you are getting a C string that you + // have to delete with delete[]. + // + + struct string_pskel: simple_content + { + virtual char* + post_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_pskel (); + string_pskel (string_pskel* impl, void*); + + protected: + string_pskel* string_impl_; +#endif + }; + + struct normalized_string_pskel: simple_content + { + virtual char* + post_normalized_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_pskel (); + normalized_string_pskel (normalized_string_pskel* impl, void*); + + protected: + normalized_string_pskel* normalized_string_impl_; +#endif + }; + + struct token_pskel: simple_content + { + virtual char* + post_token () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_pskel (); + token_pskel (token_pskel* impl, void*); + + protected: + token_pskel* token_impl_; +#endif + }; + + struct name_pskel: simple_content + { + virtual char* + post_name () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_pskel (); + name_pskel (name_pskel* impl, void*); + + protected: + name_pskel* name_impl_; +#endif + }; + + struct nmtoken_pskel: simple_content + { + virtual char* + post_nmtoken () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_pskel (); + nmtoken_pskel (nmtoken_pskel* impl, void*); + + protected: + nmtoken_pskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_pskel: list_base + { + virtual string_sequence* + post_nmtokens () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_pskel (); + nmtokens_pskel (nmtokens_pskel* impl, void*); + + protected: + nmtokens_pskel* nmtokens_impl_; +#endif + }; + + struct ncname_pskel: simple_content + { + virtual char* + post_ncname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_pskel (); + ncname_pskel (ncname_pskel* impl, void*); + + protected: + ncname_pskel* ncname_impl_; +#endif + }; + + struct id_pskel: simple_content + { + virtual char* + post_id () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_pskel (); + id_pskel (id_pskel* impl, void*); + + protected: + id_pskel* id_impl_; +#endif + }; + + struct idref_pskel: simple_content + { + virtual char* + post_idref () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_pskel (); + idref_pskel (idref_pskel* impl, void*); + + protected: + idref_pskel* idref_impl_; +#endif + }; + + struct idrefs_pskel: list_base + { + virtual string_sequence* + post_idrefs () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_pskel (); + idrefs_pskel (idrefs_pskel* impl, void*); + + protected: + idrefs_pskel* idrefs_impl_; +#endif + }; + + struct language_pskel: simple_content + { + virtual char* + post_language () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_pskel (); + language_pskel (language_pskel* impl, void*); + + protected: + language_pskel* language_impl_; +#endif + }; + + struct uri_pskel: simple_content + { + virtual char* + post_uri () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_pskel (); + uri_pskel (uri_pskel* impl, void*); + + protected: + uri_pskel* uri_impl_; +#endif + }; + + struct qname_pskel: simple_content + { + virtual qname* + post_qname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_pskel (); + qname_pskel (qname_pskel* impl, void*); + + protected: + qname_pskel* qname_impl_; +#endif + }; +#endif // XSDE_STL + + + // base64Binary + // + struct base64_binary_pskel: simple_content + { + virtual buffer* + post_base64_binary () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + base64_binary_pskel (); + base64_binary_pskel (base64_binary_pskel* impl, void*); + + protected: + base64_binary_pskel* base64_binary_impl_; +#endif + }; + + // hexBinary + // + struct hex_binary_pskel: simple_content + { + virtual buffer* + post_hex_binary () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + hex_binary_pskel (); + hex_binary_pskel (hex_binary_pskel* impl, void*); + + protected: + hex_binary_pskel* hex_binary_impl_; +#endif + }; + + // Time and date types. + // + struct gday_pskel: simple_content + { + virtual gday + post_gday () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gday_pskel (); + gday_pskel (gday_pskel* impl, void*); + + protected: + gday_pskel* gday_impl_; +#endif + }; + + struct gmonth_pskel: simple_content + { + virtual gmonth + post_gmonth () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_pskel (); + gmonth_pskel (gmonth_pskel* impl, void*); + + protected: + gmonth_pskel* gmonth_impl_; +#endif + }; + + struct gyear_pskel: simple_content + { + virtual gyear + post_gyear () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_pskel (); + gyear_pskel (gyear_pskel* impl, void*); + + protected: + gyear_pskel* gyear_impl_; +#endif + }; + + struct gmonth_day_pskel: simple_content + { + virtual gmonth_day + post_gmonth_day () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_day_pskel (); + gmonth_day_pskel (gmonth_day_pskel* impl, void*); + + protected: + gmonth_day_pskel* gmonth_day_impl_; +#endif + }; + + struct gyear_month_pskel: simple_content + { + virtual gyear_month + post_gyear_month () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_month_pskel (); + gyear_month_pskel (gyear_month_pskel* impl, void*); + + protected: + gyear_month_pskel* gyear_month_impl_; +#endif + }; + + struct date_pskel: simple_content + { + virtual date + post_date () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_pskel (); + date_pskel (date_pskel* impl, void*); + + protected: + date_pskel* date_impl_; +#endif + }; + + struct time_pskel: simple_content + { + virtual time + post_time () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + time_pskel (); + time_pskel (time_pskel* impl, void*); + + protected: + time_pskel* time_impl_; +#endif + }; + + struct date_time_pskel: simple_content + { + virtual date_time + post_date_time () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_time_pskel (); + date_time_pskel (date_time_pskel* impl, void*); + + protected: + date_time_pskel* date_time_impl_; +#endif + }; + + struct duration_pskel: simple_content + { + virtual duration + post_duration () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + duration_pskel (); + duration_pskel (duration_pskel* impl, void*); + + protected: + duration_pskel* duration_impl_; +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_NON_VALIDATING_XML_SCHEMA_PSKEL_HXX diff --git a/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.ixx b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.ixx new file mode 100644 index 0000000..220464c --- /dev/null +++ b/libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.ixx @@ -0,0 +1,704 @@ +// file : xsde/cxx/parser/non-validating/xml-schema-pskel.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace non_validating + { + // any_type_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_type_pskel:: + any_type_pskel () + : any_type_impl_ (0) + { + } + + inline any_type_pskel:: + any_type_pskel (any_type_pskel* impl, void*) + : complex_content (impl, 0), any_type_impl_ (impl) + { + } +#endif + + // any_simple_type_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_simple_type_pskel:: + any_simple_type_pskel () + : any_simple_type_impl_ (0) + { + } + + inline any_simple_type_pskel:: + any_simple_type_pskel (any_simple_type_pskel* impl, void*) + : simple_content (impl, 0), any_simple_type_impl_ (impl) + { + } +#endif + + // boolean_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline boolean_pskel:: + boolean_pskel () + : boolean_impl_ (0) + { + } + + inline boolean_pskel:: + boolean_pskel (boolean_pskel* impl, void*) + : simple_content (impl, 0), boolean_impl_ (impl) + { + } +#endif + + // byte_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline byte_pskel:: + byte_pskel () + : byte_impl_ (0) + { + } + + inline byte_pskel:: + byte_pskel (byte_pskel* impl, void*) + : simple_content (impl, 0), byte_impl_ (impl) + { + } +#endif + + // unsigned_byte_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_byte_pskel:: + unsigned_byte_pskel () + : unsigned_byte_impl_ (0) + { + } + + inline unsigned_byte_pskel:: + unsigned_byte_pskel (unsigned_byte_pskel* impl, void*) + : simple_content (impl, 0), unsigned_byte_impl_ (impl) + { + } +#endif + + // short_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline short_pskel:: + short_pskel () + : short_impl_ (0) + { + } + + inline short_pskel:: + short_pskel (short_pskel* impl, void*) + : simple_content (impl, 0), short_impl_ (impl) + { + } +#endif + + // unsigned_short_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_short_pskel:: + unsigned_short_pskel () + : unsigned_short_impl_ (0) + { + } + + inline unsigned_short_pskel:: + unsigned_short_pskel (unsigned_short_pskel* impl, void*) + : simple_content (impl, 0), unsigned_short_impl_ (impl) + { + } +#endif + + // int_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline int_pskel:: + int_pskel () + : int_impl_ (0) + { + } + + inline int_pskel:: + int_pskel (int_pskel* impl, void*) + : simple_content (impl, 0), int_impl_ (impl) + { + } +#endif + + // unsigned_int_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_int_pskel:: + unsigned_int_pskel () + : unsigned_int_impl_ (0) + { + } + + inline unsigned_int_pskel:: + unsigned_int_pskel (unsigned_int_pskel* impl, void*) + : simple_content (impl, 0), unsigned_int_impl_ (impl) + { + } +#endif + + // long_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline long_pskel:: + long_pskel () + : long_impl_ (0) + { + } + + inline long_pskel:: + long_pskel (long_pskel* impl, void*) + : simple_content (impl, 0), long_impl_ (impl) + { + } +#endif + + // unsigned_long_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_long_pskel:: + unsigned_long_pskel () + : unsigned_long_impl_ (0) + { + } + + inline unsigned_long_pskel:: + unsigned_long_pskel (unsigned_long_pskel* impl, void*) + : simple_content (impl, 0), unsigned_long_impl_ (impl) + { + } +#endif + + // integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline integer_pskel:: + integer_pskel () + : integer_impl_ (0) + { + } + + inline integer_pskel:: + integer_pskel (integer_pskel* impl, void*) + : simple_content (impl, 0), integer_impl_ (impl) + { + } +#endif + + // negative_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline negative_integer_pskel:: + negative_integer_pskel () + : negative_integer_impl_ (0) + { + } + + inline negative_integer_pskel:: + negative_integer_pskel (negative_integer_pskel* impl, void*) + : simple_content (impl, 0), negative_integer_impl_ (impl) + { + } +#endif + + // non_positive_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_positive_integer_pskel:: + non_positive_integer_pskel () + : non_positive_integer_impl_ (0) + { + } + + inline non_positive_integer_pskel:: + non_positive_integer_pskel (non_positive_integer_pskel* impl, void*) + : simple_content (impl, 0), non_positive_integer_impl_ (impl) + { + } +#endif + + // positive_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline positive_integer_pskel:: + positive_integer_pskel () + : positive_integer_impl_ (0) + { + } + + inline positive_integer_pskel:: + positive_integer_pskel (positive_integer_pskel* impl, void*) + : simple_content (impl, 0), positive_integer_impl_ (impl) + { + } +#endif + + // non_negative_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_negative_integer_pskel:: + non_negative_integer_pskel () + : non_negative_integer_impl_ (0) + { + } + + inline non_negative_integer_pskel:: + non_negative_integer_pskel (non_negative_integer_pskel* impl, void*) + : simple_content (impl, 0), non_negative_integer_impl_ (impl) + { + } +#endif + + // float_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline float_pskel:: + float_pskel () + : float_impl_ (0) + { + } + + inline float_pskel:: + float_pskel (float_pskel* impl, void*) + : simple_content (impl, 0), float_impl_ (impl) + { + } +#endif + + // double_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline double_pskel:: + double_pskel () + : double_impl_ (0) + { + } + + inline double_pskel:: + double_pskel (double_pskel* impl, void*) + : simple_content (impl, 0), double_impl_ (impl) + { + } +#endif + + // decimal_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline decimal_pskel:: + decimal_pskel () + : decimal_impl_ (0) + { + } + + inline decimal_pskel:: + decimal_pskel (decimal_pskel* impl, void*) + : simple_content (impl, 0), decimal_impl_ (impl) + { + } +#endif + + // string_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline string_pskel:: + string_pskel () + : string_impl_ (0) + { + } + + inline string_pskel:: + string_pskel (string_pskel* impl, void*) + : simple_content (impl, 0), string_impl_ (impl) + { + } +#endif + + // normalized_string_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline normalized_string_pskel:: + normalized_string_pskel () + : normalized_string_impl_ (0) + { + } + + inline normalized_string_pskel:: + normalized_string_pskel (normalized_string_pskel* impl, void*) + : simple_content (impl, 0), normalized_string_impl_ (impl) + { + } +#endif + + // token_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline token_pskel:: + token_pskel () + : token_impl_ (0) + { + } + + inline token_pskel:: + token_pskel (token_pskel* impl, void*) + : simple_content (impl, 0), token_impl_ (impl) + { + } +#endif + + // name_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline name_pskel:: + name_pskel () + : name_impl_ (0) + { + } + + inline name_pskel:: + name_pskel (name_pskel* impl, void*) + : simple_content (impl, 0), name_impl_ (impl) + { + } +#endif + + // nmtoken_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtoken_pskel:: + nmtoken_pskel () + : nmtoken_impl_ (0) + { + } + + inline nmtoken_pskel:: + nmtoken_pskel (nmtoken_pskel* impl, void*) + : simple_content (impl, 0), nmtoken_impl_ (impl) + { + } +#endif + + // nmtokens_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtokens_pskel:: + nmtokens_pskel () + : nmtokens_impl_ (0) + { + } + + inline nmtokens_pskel:: + nmtokens_pskel (nmtokens_pskel* impl, void*) + : list_base (impl, 0), nmtokens_impl_ (impl) + { + } +#endif + + // ncname_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline ncname_pskel:: + ncname_pskel () + : ncname_impl_ (0) + { + } + + inline ncname_pskel:: + ncname_pskel (ncname_pskel* impl, void*) + : simple_content (impl, 0), ncname_impl_ (impl) + { + } +#endif + + // id_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline id_pskel:: + id_pskel () + : id_impl_ (0) + { + } + + inline id_pskel:: + id_pskel (id_pskel* impl, void*) + : simple_content (impl, 0), id_impl_ (impl) + { + } +#endif + + // idref_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idref_pskel:: + idref_pskel () + : idref_impl_ (0) + { + } + + inline idref_pskel:: + idref_pskel (idref_pskel* impl, void*) + : simple_content (impl, 0), idref_impl_ (impl) + { + } +#endif + + // idrefs_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idrefs_pskel:: + idrefs_pskel () + : idrefs_impl_ (0) + { + } + + inline idrefs_pskel:: + idrefs_pskel (idrefs_pskel* impl, void*) + : list_base (impl, 0), idrefs_impl_ (impl) + { + } +#endif + + // language_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline language_pskel:: + language_pskel () + : language_impl_ (0) + { + } + + inline language_pskel:: + language_pskel (language_pskel* impl, void*) + : simple_content (impl, 0), language_impl_ (impl) + { + } +#endif + + // uri_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline uri_pskel:: + uri_pskel () + : uri_impl_ (0) + { + } + + inline uri_pskel:: + uri_pskel (uri_pskel* impl, void*) + : simple_content (impl, 0), uri_impl_ (impl) + { + } +#endif + + // qname_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline qname_pskel:: + qname_pskel () + : qname_impl_ (0) + { + } + + inline qname_pskel:: + qname_pskel (qname_pskel* impl, void*) + : simple_content (impl, 0), qname_impl_ (impl) + { + } +#endif + + // base64_binary_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline base64_binary_pskel:: + base64_binary_pskel () + : base64_binary_impl_ (0) + { + } + + inline base64_binary_pskel:: + base64_binary_pskel (base64_binary_pskel* impl, void*) + : simple_content (impl, 0), base64_binary_impl_ (impl) + { + } +#endif + + // hex_binary_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline hex_binary_pskel:: + hex_binary_pskel () + : hex_binary_impl_ (0) + { + } + + inline hex_binary_pskel:: + hex_binary_pskel (hex_binary_pskel* impl, void*) + : simple_content (impl, 0), hex_binary_impl_ (impl) + { + } +#endif + + // gday_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gday_pskel:: + gday_pskel () + : gday_impl_ (0) + { + } + + inline gday_pskel:: + gday_pskel (gday_pskel* impl, void*) + : simple_content (impl, 0), gday_impl_ (impl) + { + } +#endif + + // gmonth_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_pskel:: + gmonth_pskel () + : gmonth_impl_ (0) + { + } + + inline gmonth_pskel:: + gmonth_pskel (gmonth_pskel* impl, void*) + : simple_content (impl, 0), gmonth_impl_ (impl) + { + } +#endif + + // gyear_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_pskel:: + gyear_pskel () + : gyear_impl_ (0) + { + } + + inline gyear_pskel:: + gyear_pskel (gyear_pskel* impl, void*) + : simple_content (impl, 0), gyear_impl_ (impl) + { + } +#endif + + // gmonth_day_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_day_pskel:: + gmonth_day_pskel () + : gmonth_day_impl_ (0) + { + } + + inline gmonth_day_pskel:: + gmonth_day_pskel (gmonth_day_pskel* impl, void*) + : simple_content (impl, 0), gmonth_day_impl_ (impl) + { + } +#endif + + // gyear_month_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_month_pskel:: + gyear_month_pskel () + : gyear_month_impl_ (0) + { + } + + inline gyear_month_pskel:: + gyear_month_pskel (gyear_month_pskel* impl, void*) + : simple_content (impl, 0), gyear_month_impl_ (impl) + { + } +#endif + + // date_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_pskel:: + date_pskel () + : date_impl_ (0) + { + } + + inline date_pskel:: + date_pskel (date_pskel* impl, void*) + : simple_content (impl, 0), date_impl_ (impl) + { + } +#endif + + // time_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline time_pskel:: + time_pskel () + : time_impl_ (0) + { + } + + inline time_pskel:: + time_pskel (time_pskel* impl, void*) + : simple_content (impl, 0), time_impl_ (impl) + { + } +#endif + + // date_time_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_time_pskel:: + date_time_pskel () + : date_time_impl_ (0) + { + } + + inline date_time_pskel:: + date_time_pskel (date_time_pskel* impl, void*) + : simple_content (impl, 0), date_time_impl_ (impl) + { + } +#endif + + // duration_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline duration_pskel:: + duration_pskel () + : duration_impl_ (0) + { + } + + inline duration_pskel:: + duration_pskel (duration_pskel* impl, void*) + : simple_content (impl, 0), duration_impl_ (impl) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/state.cxx b/libxsde/xsde/cxx/parser/state.cxx new file mode 100644 index 0000000..756190e --- /dev/null +++ b/libxsde/xsde/cxx/parser/state.cxx @@ -0,0 +1,37 @@ +// file : xsde/cxx/parser/state.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + stack::error stack:: + grow () + { + size_t c = capacity_ ? capacity_ * 2 : 8; + char* d = new char[c * el_size_]; + + if (d == 0) + return error_no_memory; + + if (size_ > 1) + memcpy (d, data_, (size_ - 1) * el_size_); + + delete[] data_; + + data_ = d; + capacity_ = c; + + return error_none; + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/state.hxx b/libxsde/xsde/cxx/parser/state.hxx new file mode 100644 index 0000000..11ace8d --- /dev/null +++ b/libxsde/xsde/cxx/parser/state.hxx @@ -0,0 +1,89 @@ +// file : xsde/cxx/parser/state.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_STATE_HXX +#define XSDE_CXX_PARSER_STATE_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // POD stack with pre-allocated first element. You may + // need to pad your elements to get the proper alignment. + // + struct stack + { + enum error + { + error_none, + error_no_memory + }; + + ~stack (); + stack (size_t element_size, void* first_element); + + public: + void + pop (); + + error + push (); + + void* + top (); + + size_t + element_size () const; + + void + clear (); + + private: + error + grow (); + + private: + size_t el_size_; + void* first_; + char* data_; + size_t size_; + size_t capacity_; + }; + + // Optimized state stack for non-recursive case (one element). + // + struct parser_stack + { + parser_stack (parser_state& first); + + stack::error + push (parser_state&); + + void + pop (); + + parser_state& + top (); + + void + clear (); + + private: + stack stack_; + }; + } + } +} + + +#include + +#endif // XSDE_CXX_PARSER_STATE_HXX diff --git a/libxsde/xsde/cxx/parser/state.ixx b/libxsde/xsde/cxx/parser/state.ixx new file mode 100644 index 0000000..6f9c4b7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/state.ixx @@ -0,0 +1,102 @@ +// file : xsde/cxx/parser/state.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + // stack + // + + inline stack:: + ~stack () + { + delete[] data_; + } + + inline stack:: + stack (size_t el_size, void* first_el) + : el_size_ (el_size), first_ (first_el), + data_ (0), size_ (0), capacity_ (0) + { + } + + inline void stack:: + pop () + { + --size_; + } + + inline stack::error stack:: + push () + { + if (size_ > capacity_) + if (error e = grow ()) + return e; + + ++size_; + + return error_none; + } + + inline void* stack:: + top () + { + return size_ == 1 ? first_ : data_ + (size_ - 1) * el_size_; + } + + inline size_t stack:: + element_size () const + { + return el_size_; + } + + inline void stack:: + clear () + { + size_ = 0; + } + + // parser_stack + // + inline parser_stack:: + parser_stack (parser_state& first) + : stack_ (sizeof (parser_state), &first) + { + } + + inline stack::error parser_stack:: + push (parser_state& s) + { + if (stack::error e = stack_.push ()) + return e; + + *static_cast (stack_.top ()) = s; + return stack::error_none; + } + + inline void parser_stack:: + pop () + { + stack_.pop (); + } + + inline parser_state& parser_stack:: + top () + { + return *static_cast (stack_.top ()); + } + + inline void parser_stack:: + clear () + { + stack_.clear (); + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/substitution-map-load.hxx b/libxsde/xsde/cxx/parser/substitution-map-load.hxx new file mode 100644 index 0000000..4efa2ad --- /dev/null +++ b/libxsde/xsde/cxx/parser/substitution-map-load.hxx @@ -0,0 +1,31 @@ +// file : xsde/cxx/parser/substitution-map-load.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_SUBSTITUTION_MAP_LOAD_HXX +#define XSDE_CXX_PARSER_SUBSTITUTION_MAP_LOAD_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + size_t + parser_smap_elements (); + + inline size_t + parser_smap_buckets () + { + return XSDE_PARSER_SMAP_BUCKETS; + } + } + } +} + +#endif // XSDE_CXX_PARSER_SUBSTITUTION_MAP_LOAD_HXX diff --git a/libxsde/xsde/cxx/parser/substitution-map.cxx b/libxsde/xsde/cxx/parser/substitution-map.cxx new file mode 100644 index 0000000..950d07d --- /dev/null +++ b/libxsde/xsde/cxx/parser/substitution-map.cxx @@ -0,0 +1,236 @@ +// file : xsde/cxx/parser/substitution-map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // strlen, strcmp, strncmp + +#ifndef XSDE_EXCEPTIONS +# include // assert +# include // exit +#endif + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + substitution_map* substitution_map_init::map = 0; + size_t substitution_map_init::count = 0; + + bool substitution_map:: + check_ (const ro_string& ns, + const ro_string& name, + const char* root, + const char** type) const + { + bool r = false; + + if (const value* v = find_ (ns, name)) + { + if (strcmp (root, v->root_) == 0) + r = true; + else + r = check_ (v->root_, root); + + if (r && type != 0 && *type == 0) + *type = v->type_; + } + + return r; + } + + bool substitution_map:: + check_ (const ro_string& ns, + const ro_string& name, + const char* root_ns, + const char* root_name, + const char** type) const + { + bool r = false; + + if (const value* v = find_ (ns, name)) + { + if (root_ns == 0) + r = strcmp (v->root_, root_name) == 0; + else + { + size_t n = strlen (root_name); + + r = strncmp (v->root_, root_name, n) == 0 && v->root_[n] == ' ' && + strcmp (v->root_ + n + 1, root_ns) == 0; + } + + if (!r) + r = check_ (v->root_, root_ns, root_name); + + if (r && type != 0 && *type == 0) + *type = v->type_; + } + + return r; + } + + bool substitution_map:: + check_ (const char* member, const char* root) const + { + const value* v = static_cast (find (member)); + + if (v == 0) + return false; + + return strcmp (root, v->root_) == 0 ? true : check_ (v->root_, root); + } + + bool substitution_map:: + check_ (const char* member, + const char* root_ns, + const char* root_name) const + { + const value* v = static_cast (find (member)); + + if (v == 0) + return false; + + bool r; + + if (root_ns == 0) + r = strcmp (v->root_, root_name) == 0; + else + { + size_t n = strlen (root_name); + + r = strncmp (v->root_, root_name, n) == 0 && v->root_[n] == ' ' && + strcmp (v->root_ + n + 1, root_ns) == 0; + } + + return r ? true : check_ (v->root_, root_ns, root_name); + } + + const substitution_map::value* substitution_map:: + find_ (const ro_string& ns, const ro_string& name) const + { + bool q = !ns.empty (); + size_t h = hash (name.data (), name.size ()); + + if (q) + { + h = hash (h, " ", 1); + h = hash (h, ns.data (), ns.size ()); + } + + const bucket* p = find (h); + + if (p == 0) + return 0; + + // Search for the entry in the bucket. + // + const size_t el_size = sizeof (element) + sizeof (value); + const char* b = reinterpret_cast (p) + sizeof (bucket); + const char* e = b + p->size_ * el_size; + + for (; b < e; b += el_size) + { + const element* e = reinterpret_cast (b); + + if (e->hash_ == h) + { + if (!q) + { + if (strlen (e->key_) == name.size () && + strncmp (e->key_, name.data (), name.size ()) == 0) + break; + } + else + { + size_t n = name.size (); + + if (strncmp (e->key_, name.data (), n) == 0 && + e->key_[n] == ' ' && + strlen (e->key_ + n + 1) == ns.size () && + strncmp (e->key_ + n + 1, ns.data (), ns.size ()) == 0) + break; + } + } + } + + if (b == e) + return 0; + + return reinterpret_cast (b + sizeof (element)); + } + + // substitution_map_init + // + substitution_map_init:: + substitution_map_init () + { + if (count == 0) + { + map = new substitution_map (XSDE_PARSER_SMAP_BUCKETS); + +#ifndef XSDE_EXCEPTIONS + if (map == 0 || map->_error () != substitution_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + ++count; + } + + substitution_map_init:: + ~substitution_map_init () + { + if (--count == 0) + delete map; + } + + // substitution_map_entry + // + substitution_map_entry:: + substitution_map_entry (const char* member, + const char* root, + const char* type) + { + substitution_map& m = substitution_map_instance (); + m.insert (member, root, type); + +#ifndef XSDE_EXCEPTIONS + if (m._error () != substitution_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + // + // + size_t + parser_smap_elements () + { + return substitution_map_instance ().size (); + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/substitution-map.hxx b/libxsde/xsde/cxx/parser/substitution-map.hxx new file mode 100644 index 0000000..14586c1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/substitution-map.hxx @@ -0,0 +1,115 @@ +// file : xsde/cxx/parser/substitution-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_SUBSTITUTION_MAP_HXX +#define XSDE_CXX_PARSER_SUBSTITUTION_MAP_HXX + +#include // size_t + +#include +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + struct substitution_map: hashmap + { + substitution_map (size_t buckets); + + void + insert (const char* member, + const char* root, + const char* type); + + // Check and have the type set if found. + // + bool + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root, + const char*& type) const; + + bool + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root_ns, // 0 if no namespace + const char* root_name, + const char*& type) const; + + // Check but don't care about the type. + // + bool + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root) const; + + private: + struct value + { + const char* root_; + const char* type_; + }; + + private: + bool + check_ (const ro_string& member_ns, + const ro_string& member_name, + const char* root, + const char** type) const; + + bool + check_ (const ro_string& member_ns, + const ro_string& member_name, + const char* root_ns, + const char* root_name, + const char** type) const; + + bool + check_ (const char* member, const char* root) const; + + bool + check_ (const char* member, + const char* root_ns, + const char* root_name) const; + + const value* + find_ (const ro_string& member_ns, + const ro_string& member_name) const; + }; + + + // Translation unit initializer. + // + struct substitution_map_init + { + static substitution_map* map; + static size_t count; + + substitution_map_init (); + ~substitution_map_init (); + }; + + substitution_map& + substitution_map_instance (); + + // Map entry initializer. + // + struct substitution_map_entry + { + substitution_map_entry (const char* member, + const char* root, + const char* type); + }; + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_SUBSTITUTION_MAP_HXX diff --git a/libxsde/xsde/cxx/parser/substitution-map.ixx b/libxsde/xsde/cxx/parser/substitution-map.ixx new file mode 100644 index 0000000..a45b5d4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/substitution-map.ixx @@ -0,0 +1,71 @@ +// file : xsde/cxx/parser/substitution-map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + inline substitution_map:: + substitution_map (size_t buckets) + : hashmap (buckets, sizeof (value)) + { + } + + inline void substitution_map:: + insert (const char* member, + const char* root, + const char* type) + { + value v; + v.root_ = root; + v.type_ = type; + hashmap::insert (member, &v); + } + + inline bool substitution_map:: + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root, + const char*& type) const + { + + return empty () + ? false + : check_ (member_ns, member_name, root, &type); + } + + inline bool substitution_map:: + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root_ns, + const char* root_name, + const char*& type) const + { + return empty () + ? false + : check_ (member_ns, member_name, root_ns, root_name, &type); + } + + inline bool substitution_map:: + check (const ro_string& member_ns, + const ro_string& member_name, + const char* root) const + { + + return empty () + ? false + : check_ (member_ns, member_name, root, 0); + } + + inline substitution_map& + substitution_map_instance () + { + return *substitution_map_init::map; + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/any-type.hxx b/libxsde/xsde/cxx/parser/validating/any-type.hxx new file mode 100644 index 0000000..6f183d4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/any-type.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/parser/validating/any-type.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_ANY_TYPE_HXX +#define XSDE_CXX_PARSER_VALIDATING_ANY_TYPE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // any_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_type_pimpl: virtual any_type_pskel +#else + struct any_type_pimpl: any_type_pskel +#endif + { + }; + + // any_simple_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_simple_type_pimpl: virtual any_simple_type_pskel +#else + struct any_simple_type_pimpl: any_simple_type_pskel +#endif + { + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_ANY_TYPE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/base64-binary.cxx b/libxsde/xsde/cxx/parser/validating/base64-binary.cxx new file mode 100644 index 0000000..994c14b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/base64-binary.cxx @@ -0,0 +1,281 @@ +// file : xsde/cxx/parser/validating/base64-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +static unsigned char +base64_decode (char c) +{ + unsigned char r = 0xFF; + + if (c >= 'A' && c <= 'Z') + r = static_cast (c - 'A'); + else if (c >= 'a' && c <= 'z') + r = static_cast (c - 'a' + 26); + else if (c >= '0' && c <= '9') + r = static_cast (c - '0' + 52); + else if (c == '+') + r = 62; + else if (c == '/') + r = 63; + + return r; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + base64_binary_pimpl:: + ~base64_binary_pimpl () + { + if (!base_) + delete buf_; + } + + void base64_binary_pimpl:: + _reset () + { + base64_binary_pskel::_reset (); + + if (!base_) + { + delete buf_; + buf_ = 0; + } + } + + base64_binary_pimpl:: + base64_binary_pimpl (bool base) + : base_ (base), buf_ (0) + { + } + + void base64_binary_pimpl:: + pre_impl (buffer* b) + { + buf_ = b; + } + + void base64_binary_pimpl:: + _pre () + { + if (buf_ == 0) + { + buf_ = new buffer (); + +#ifndef XSDE_EXCEPTIONS + if (buf_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void base64_binary_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void base64_binary_pimpl:: + _post () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + const char* src = str_.data (); + + // Remove all whitespaces. + // + { + size_type j = 0; + bool subs = false; + + for (size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + subs = false; + + str_[j++] = c; + } + } + + size = j; + str_.truncate (size); + } + + // Our length should be a multiple of four. + // + if (size == 0 || size % 4 != 0) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + size_type quad_count = size / 4; + size_type capacity = quad_count * 3 + 1; + +#ifdef XSDE_EXCEPTIONS + buf_->size (capacity); +#else + if (buf_->size (capacity)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + char* dst = buf_->data (); + + // Source and destination indexes. + // + size_type si = 0; + size_type di = 0; + + // Process all quads except the last one. + // + unsigned char b1, b2, b3, b4; + + for (size_type q = 0; q < quad_count - 1; ++q) + { + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + b3 = base64_decode (src[si++]); + b4 = base64_decode (src[si++]); + + if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } + + // Process the last quad. The first two octets are always there. + // + b1 = base64_decode (src[si++]); + b2 = base64_decode (src[si++]); + + if (b1 == 0xFF || b2 == 0xFF) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + char e3 = src[si++]; + char e4 = src[si++]; + + if (e4 == '=') + { + if (e3 == '=') + { + // Two pads. Last 4 bits in b2 should be zero. + // + if ((b2 & 0x0F) != 0) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + if (b3 == 0xFF || (b3 & 0x03) != 0) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + } + } + else + { + // No pads. + // + b3 = base64_decode (e3); + b4 = base64_decode (e4); + + if (b3 == 0xFF || b4 == 0xFF) + { + _schema_error (schema_error::invalid_base64_binary_value); + return; + } + + dst[di++] = (b1 << 2) | (b2 >> 4); + dst[di++] = (b2 << 4) | (b3 >> 2); + dst[di++] = (b3 << 6) | b4; + } + + // Set the real size. + // + buf_->size (di); + } + + buffer* base64_binary_pimpl:: + post_base64_binary () + { + buffer* r = buf_; + buf_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/base64-binary.hxx b/libxsde/xsde/cxx/parser/validating/base64-binary.hxx new file mode 100644 index 0000000..656bf9b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/base64-binary.hxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/parser/validating/base64-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_BASE64_BINARY_HXX +#define XSDE_CXX_PARSER_VALIDATING_BASE64_BINARY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct base64_binary_pimpl: virtual base64_binary_pskel +#else + struct base64_binary_pimpl: base64_binary_pskel +#endif + { + ~base64_binary_pimpl (); + base64_binary_pimpl (bool base = false); + + void + pre_impl (buffer*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual buffer* + post_base64_binary (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + buffer* buf_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_BASE64_BINARY_HXX diff --git a/libxsde/xsde/cxx/parser/validating/boolean.cxx b/libxsde/xsde/cxx/parser/validating/boolean.cxx new file mode 100644 index 0000000..80d88f8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/boolean.cxx @@ -0,0 +1,93 @@ +// file : xsde/cxx/parser/validating/boolean.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void boolean_pimpl:: + _pre () + { + size_ = 0; + state_ = leading_ws; + } + + void boolean_pimpl:: + _characters (const ro_string& s) + { + ro_string tmp (s.data (), s.size ()); + + size_t size = tmp.size (); + + switch (state_) + { + case leading_ws: + { + size = trim_left (tmp); + + if (size != 0) + state_ = literal; + else + break; + // Fall through. + } + case literal: + { + // If this chunk is too long then it has to be the last so trim + // trailing ws. + // + if ((5 - size_) < size) + { + size = trim_right (tmp); + state_ = trailing_ws; // It either had ws or is too large. + } + + if ((5 - size_) >= size) + { + memcpy (str_ + size_, tmp.data (), size); + size_ += size; + } + else + _schema_error (schema_error::invalid_boolean_value); + + break; + } + case trailing_ws: + { + if (trim_left (tmp) != 0) + _schema_error (schema_error::invalid_boolean_value); + } + } + } + + void boolean_pimpl:: + _post () + { + ro_string tmp (str_, size_); + trim_right (tmp); + + if (tmp == "1" || tmp == "true") + value_ = true; + else if (tmp == "0" || tmp == "false") + value_ = false; + else + _schema_error (schema_error::invalid_boolean_value); + } + + bool boolean_pimpl:: + post_boolean () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/boolean.hxx b/libxsde/xsde/cxx/parser/validating/boolean.hxx new file mode 100644 index 0000000..81c1e29 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/boolean.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/validating/boolean.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_BOOLEAN_HXX +#define XSDE_CXX_PARSER_VALIDATING_BOOLEAN_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct boolean_pimpl: virtual boolean_pskel +#else + struct boolean_pimpl: boolean_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual bool + post_boolean (); + + protected: + // We only need strlen("false") + 1 characters to hold all valid + // and trimmed string representations of boolean. + // + char str_[6]; + size_t size_; + enum { leading_ws, literal, trailing_ws } state_; + + bool value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_BOOLEAN_HXX diff --git a/libxsde/xsde/cxx/parser/validating/byte.cxx b/libxsde/xsde/cxx/parser/validating/byte.cxx new file mode 100644 index 0000000..a18c26a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/byte.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/parser/validating/byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void byte_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void byte_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 4)) + _schema_error (schema_error::invalid_byte_value); + } + + void byte_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + // No need to check errno since our string representation + // can never overflow an unsigned long. + // + char* p; + unsigned long ul = strtoul (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || (neg && ul > 128) || (!neg && ul > 127)) + _schema_error (schema_error::invalid_byte_value); + + value_ = neg + ? static_cast (-static_cast (ul)) + : static_cast (ul); + } + else + _schema_error (schema_error::invalid_byte_value); + } + + signed char byte_pimpl:: + post_byte () + { + return value_; + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/validating/byte.hxx b/libxsde/xsde/cxx/parser/validating/byte.hxx new file mode 100644 index 0000000..6a3abce --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/byte.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_BYTE_HXX +#define XSDE_CXX_PARSER_VALIDATING_BYTE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 8-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct byte_pimpl: virtual byte_pskel, number +#else + struct byte_pimpl: byte_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual signed char + post_byte (); + + protected: + // We only need strlen("0128") + 1 characters to hold all valid + // and trimmed string representations of signed byte. + // + char str_[5]; + signed char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_BYTE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/date-time.cxx b/libxsde/xsde/cxx/parser/validating/date-time.cxx new file mode 100644 index 0000000..32f33a7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/date-time.cxx @@ -0,0 +1,259 @@ +// file : xsde/cxx/parser/validating/date-time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul, strtod + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void date_time_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void date_time_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void date_time_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] + // + + if (n < 19 || (s[0] == '-' && n < 20)) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // Find the end of the year token. + // + ro_string::size_type yp = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (yp == ro_string::npos || (n - yp - 1) < 14 + || s[yp + 3] != '-' || s[yp + 6] != 'T' + || s[yp + 9] != ':' || s[yp + 12] != ':') + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // Find the end of the seconds fragment. + // + ro_string::size_type sp = yp + 15; + for (; sp < n; ++sp) + { + char c = s[sp]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // At least one digit should follow the fraction point. + // + if ((sp - yp - 13) == 3) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // Parse it backwards so that we can truncate and reuse + // the string. + // + + // zone + // + if (sp < n) + { + if (!bits::parse_time_zone (s + sp, n - sp, zh_, zm_)) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + z_ = true; + } + else + z_ = false; + + // seconds + // + str_.truncate (sp); + + char* p; + set_errno (0); + seconds_ = strtod (s + yp + 13, &p); + + if (*p != '\0' || get_errno () != 0 || seconds_ >= 60.0) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // minutes + // + char d1 = s[yp + 10]; + char d2 = s[yp + 11]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + minutes_ = 10 * (d1 - '0') + (d2 - '0'); + + if (minutes_ > 59) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // hours + // + d1 = s[yp + 7]; + d2 = s[yp + 8]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + hours_ = 10 * (d1 - '0') + (d2 - '0'); + + if (hours_ > 24) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + if (hours_ == 24 && (minutes_ != 0 || seconds_ != 0.0)) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // day + // + d1 = s[yp + 4]; + d2 = s[yp + 5]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + day_ = 10 * (d1 - '0') + (d2 - '0'); + + if (day_ < 1 || day_ > 31) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // month + // + d1 = s[yp + 1]; + d2 = s[yp + 2]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + month_ = 10 * (d1 - '0') + (d2 - '0'); + + if (month_ < 1 || month_ > 12) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + // year + // + str_.truncate (yp); + + set_errno (0); + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL) || + ul == 0) + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + + year_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + + date_time date_time_pimpl:: + post_date_time () + { + return z_ + ? date_time (year_, month_, day_, hours_, + minutes_, seconds_, zh_, zm_) + : date_time (year_, month_, day_, hours_, minutes_, seconds_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/date-time.hxx b/libxsde/xsde/cxx/parser/validating/date-time.hxx new file mode 100644 index 0000000..dcbbaa9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/date-time.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/date-time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_DATE_TIME_HXX +#define XSDE_CXX_PARSER_VALIDATING_DATE_TIME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_time_pimpl: virtual date_time_pskel +#else + struct date_time_pimpl: date_time_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual date_time + post_date_time (); + + protected: + string str_; + int year_; + unsigned short month_, day_; + unsigned short hours_, minutes_; + double seconds_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_DATE_TIME_HXX diff --git a/libxsde/xsde/cxx/parser/validating/date.cxx b/libxsde/xsde/cxx/parser/validating/date.cxx new file mode 100644 index 0000000..9efc52f --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/date.cxx @@ -0,0 +1,182 @@ +// file : xsde/cxx/parser/validating/date.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void date_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void date_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void date_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] + // + + if (n < 10 || (s[0] == '-' && n < 11)) + { + _schema_error (schema_error::invalid_date_value); + return; + } + + // Find the end of the year token. + // + ro_string::size_type pos = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (pos == ro_string::npos || + (n - pos - 1) < 5 || + s[pos + 3] != '-') + { + _schema_error (schema_error::invalid_date_value); + return; + } + + // Parse the month, day values and time zone first so that we + // can truncate and reuse the string. + // + + // month + // + char d1 = s[pos + 1]; + char d2 = s[pos + 2]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_value); + return; + } + + month_ = 10 * (d1 - '0') + (d2 - '0'); + + if (month_ < 1 || month_ > 12) + { + _schema_error (schema_error::invalid_date_value); + return; + } + + // day + // + d1 = s[pos + 4]; + d2 = s[pos + 5]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_date_value); + return; + } + + day_ = 10 * (d1 - '0') + (d2 - '0'); + + if (day_ < 1 || day_ > 31) + { + _schema_error (schema_error::invalid_date_value); + return; + } + + // zone + // + if ((pos + 6) < n) + { + if (!bits::parse_time_zone (s + pos + 6, n - pos - 6, zh_, zm_)) + { + _schema_error (schema_error::invalid_date_value); + return; + } + + z_ = true; + } + else + z_ = false; + + // year + // + str_.truncate (pos); + + char* p; + set_errno (0); + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL) || + ul == 0) + { + _schema_error (schema_error::invalid_date_value); + return; + } + + year_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + + date date_pimpl:: + post_date () + { + return z_ + ? date (year_, month_, day_, zh_, zm_) + : date (year_, month_, day_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/date.hxx b/libxsde/xsde/cxx/parser/validating/date.hxx new file mode 100644 index 0000000..feb4738 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/date.hxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/parser/validating/date.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_DATE_HXX +#define XSDE_CXX_PARSER_VALIDATING_DATE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_pimpl: virtual date_pskel +#else + struct date_pimpl: date_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual date + post_date (); + + protected: + string str_; + int year_; + unsigned short month_, day_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_DATE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/decimal.cxx b/libxsde/xsde/cxx/parser/validating/decimal.cxx new file mode 100644 index 0000000..15aa4e9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/decimal.cxx @@ -0,0 +1,74 @@ +// file : xsde/cxx/parser/validating/decimal.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void decimal_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void decimal_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 127)) + _schema_error (schema_error::invalid_decimal_value); + } + + void decimal_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + if (tmp == "INF" || tmp == "NaN" || tmp == "NAN") + { + _schema_error (schema_error::invalid_decimal_value); + } + else + { + char* p; + set_errno (0); + value_ = strtod (str_, &p); + + if (*p != '\0' || get_errno () != 0) + _schema_error (schema_error::invalid_decimal_value); + + if (sign_ == minus) + value_ = -value_; + } + } + else + _schema_error (schema_error::invalid_decimal_value); + } + + double decimal_pimpl:: + post_decimal () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/decimal.hxx b/libxsde/xsde/cxx/parser/validating/decimal.hxx new file mode 100644 index 0000000..0669ce6 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/decimal.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/decimal.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_DECIMAL_HXX +#define XSDE_CXX_PARSER_VALIDATING_DECIMAL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct decimal_pimpl: virtual decimal_pskel, number +#else + struct decimal_pimpl: decimal_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual double + post_decimal (); + + protected: + // Assume decimal values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + double value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_DECIMAL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/double.cxx b/libxsde/xsde/cxx/parser/validating/double.cxx new file mode 100644 index 0000000..947f983 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/double.cxx @@ -0,0 +1,99 @@ +// file : xsde/cxx/parser/validating/double.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void double_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void double_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 127)) + _schema_error (schema_error::invalid_double_value); + } + + void double_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + if (tmp == "INF") + { + switch (sign_) + { + case none: + { + value_ = strtod ("INF", 0); + break; + } + case plus: + { + _schema_error (schema_error::invalid_double_value); + break; + } + case minus: + { + value_ = strtod ("-INF", 0); + break; + } + } + } + else if (tmp == "NaN") + { + if (sign_ == none) + value_ = strtod ("NAN", 0); + else + _schema_error (schema_error::invalid_double_value); + + } + else + { + char* p; + set_errno (0); + value_ = strtod (str_, &p); + + if (*p != '\0' || get_errno () != 0) + _schema_error (schema_error::invalid_double_value); + + if (sign_ == minus) + value_ = -value_; + } + } + else + _schema_error (schema_error::invalid_double_value); + } + + double double_pimpl:: + post_double () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/double.hxx b/libxsde/xsde/cxx/parser/validating/double.hxx new file mode 100644 index 0000000..afae038 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/double.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/double.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_DOUBLE_HXX +#define XSDE_CXX_PARSER_VALIDATING_DOUBLE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct double_pimpl: virtual double_pskel, number +#else + struct double_pimpl: double_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual double + post_double (); + + protected: + // Assume double values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + double value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_DOUBLE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/duration.cxx b/libxsde/xsde/cxx/parser/validating/duration.cxx new file mode 100644 index 0000000..9d72609 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/duration.cxx @@ -0,0 +1,265 @@ +// file : xsde/cxx/parser/validating/duration.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul, strtod + +#include +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void duration_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void duration_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + static ro_string::size_type + rfind_delim (const char* s, ro_string::size_type pos) + { + const char* p = s + pos; + for (; p >= s; --p) + { + if (*p == 'Y' || *p == 'D' || *p == 'M' || + *p == 'H' || *p == 'M' || *p == 'S' || + *p == 'T' || *p == 'P') + break; + } + + return p >= s ? p - s : ro_string::npos; + } + + + void duration_pimpl:: + _post () + { + typedef ro_string::size_type size_type; + + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + size_type n = trim_right (tmp); + + negative_ = false; + years_ = 0; + months_ = 0; + days_ = 0; + hours_ = 0; + minutes_ = 0; + seconds_ = 0.0; + + // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] + // + + if (n < 3 || (s[0] == '-' && n < 4)) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + if (s[0] == '-') + negative_ = true; + + if (s[negative_ ? 1 : 0] != 'P') + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + // Parse it backwards so that we can truncate and reuse + // the string. + // + + bool need_t = false; + size_type pos = n - 1; + size_type t_pos = tmp.find ('T'); + + char* p; + unsigned long ul; + + if (s[pos] == 'S') + { + need_t = true; + + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + seconds_ = strtod (s + pos + 1, &p); + + if (*p != '\0' || get_errno () != 0 || seconds_ < 0.0) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + } + + if (s[pos] == 'M' && t_pos != ro_string::npos && t_pos < pos) + { + need_t = true; + + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + ul = strtoul (s + pos + 1, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + minutes_ = static_cast (ul); + } + + if (s[pos] == 'H') + { + need_t = true; + + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + ul = strtoul (s + pos + 1, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + hours_ = static_cast (ul); + } + + if (need_t) + { + if (s[pos] == 'T') + pos = rfind_delim (s, pos - 1); + else + { + _schema_error (schema_error::invalid_duration_value); + return; + } + } + else + { + if (s[pos] == 'T') + { + _schema_error (schema_error::invalid_duration_value); + return; + } + } + + if (s[pos] == 'D') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + ul = strtoul (s + pos + 1, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + days_ = static_cast (ul); + } + + if (s[pos] == 'M') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + ul = strtoul (s + pos + 1, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + months_ = static_cast (ul); + } + + if (s[pos] == 'Y') + { + str_.truncate (pos); + pos = rfind_delim (s, pos - 1); + + set_errno (0); + ul = strtoul (s + pos + 1, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + years_ = static_cast (ul); + } + + // Something did not match or appeared in the wrong order. + // + if (pos != static_cast (negative_ ? 1 : 0)) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + } + + duration duration_pimpl:: + post_duration () + { + return duration ( + negative_, years_, months_, days_, hours_, minutes_, seconds_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/duration.hxx b/libxsde/xsde/cxx/parser/validating/duration.hxx new file mode 100644 index 0000000..3ee53db --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/duration.hxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/parser/validating/duration.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_DURATION_HXX +#define XSDE_CXX_PARSER_VALIDATING_DURATION_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct duration_pimpl: virtual duration_pskel +#else + struct duration_pimpl: duration_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual duration + post_duration (); + + protected: + string str_; + bool negative_; + unsigned int years_, months_, days_; + unsigned int hours_, minutes_; + double seconds_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_DURATION_HXX diff --git a/libxsde/xsde/cxx/parser/validating/float.cxx b/libxsde/xsde/cxx/parser/validating/float.cxx new file mode 100644 index 0000000..7bbbcca --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/float.cxx @@ -0,0 +1,118 @@ +// file : xsde/cxx/parser/validating/float.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtof, strtod + +#include +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void float_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void float_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 127)) + _schema_error (schema_error::invalid_float_value); + } + + void float_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + if (tmp == "INF") + { + switch (sign_) + { + case none: + { +#ifdef XSDE_STRTOF + value_ = strtof ("INF", 0); +#else + value_ = static_cast (strtod ("INF", 0)); +#endif + break; + } + case plus: + { + _schema_error (schema_error::invalid_float_value); + break; + } + case minus: + { +#ifdef XSDE_STRTOF + value_ = strtof ("-INF", 0); +#else + value_ = static_cast (strtod ("-INF", 0)); +#endif + break; + } + } + } + else if (tmp == "NaN") + { + if (sign_ == none) + { +#ifdef XSDE_STRTOF + value_ = strtof ("NAN", 0); +#else + value_ = static_cast (strtod ("NAN", 0)); +#endif + } + else + _schema_error (schema_error::invalid_float_value); + + } + else + { + char* p; + set_errno (0); +#ifdef XSDE_STRTOF + value_ = strtof (str_, &p); +#else + value_ = static_cast (strtod (str_, &p)); +#endif + + if (*p != '\0' || get_errno () != 0) + _schema_error (schema_error::invalid_float_value); + + if (sign_ == minus) + value_ = -value_; + } + } + else + _schema_error (schema_error::invalid_float_value); + } + + float float_pimpl:: + post_float () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/float.hxx b/libxsde/xsde/cxx/parser/validating/float.hxx new file mode 100644 index 0000000..2bb6e7d --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/float.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/float.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_FLOAT_HXX +#define XSDE_CXX_PARSER_VALIDATING_FLOAT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct float_pimpl: virtual float_pskel, number +#else + struct float_pimpl: float_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual float + post_float (); + + protected: + // Assume float values (without leading and trailing whitespaces) + // cannot be longer than 127 characters. + // + char str_[128]; + float value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_FLOAT_HXX diff --git a/libxsde/xsde/cxx/parser/validating/gday.cxx b/libxsde/xsde/cxx/parser/validating/gday.cxx new file mode 100644 index 0000000..a743eee --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gday.cxx @@ -0,0 +1,112 @@ +// file : xsde/cxx/parser/validating/gday.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void gday_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gday_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void gday_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gday := ---DD[Z|(+|-)HH:MM] + // + if (n < 5 || s[0] != '-' || s[1] != '-' || s[2] != '-') + { + _schema_error (schema_error::invalid_gday_value); + return; + } + + char d1 = s[3]; + char d2 = s[4]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_gday_value); + return; + } + + day_ = 10 * (d1 - '0') + (d2 - '0'); + + if (day_ < 1 || day_ > 31) + { + _schema_error (schema_error::invalid_gday_value); + return; + } + + if (n > 5) + { + if (!bits::parse_time_zone (s + 5, n - 5, zh_, zm_)) + { + _schema_error (schema_error::invalid_gday_value); + return; + } + + z_ = true; + } + else + z_ = false; + } + + gday gday_pimpl:: + post_gday () + { + return z_ ? gday (day_, zh_, zm_) : gday (day_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/gday.hxx b/libxsde/xsde/cxx/parser/validating/gday.hxx new file mode 100644 index 0000000..21f8fcd --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gday.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/gday.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_GDAY_HXX +#define XSDE_CXX_PARSER_VALIDATING_GDAY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gday_pimpl: virtual gday_pskel +#else + struct gday_pimpl: gday_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual gday + post_gday (); + + protected: + string str_; + unsigned short day_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_GDAY_HXX diff --git a/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx b/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx new file mode 100644 index 0000000..3b4b4ea --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx @@ -0,0 +1,137 @@ +// file : xsde/cxx/parser/validating/gmonth-day.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void gmonth_day_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gmonth_day_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void gmonth_day_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gmonth_day := --MM-DD[Z|(+|-)HH:MM] + // + if (n < 7 || s[0] != '-' || s[1] != '-' || s[4] != '-') + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + // month + // + char d1 = s[2]; + char d2 = s[3]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + month_ = 10 * (d1 - '0') + (d2 - '0'); + + if (month_ < 1 || month_ > 12) + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + // day + // + d1 = s[5]; + d2 = s[6]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + day_ = 10 * (d1 - '0') + (d2 - '0'); + + if (day_ < 1 || day_ > 31) + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + // zone + // + if (n > 7) + { + if (!bits::parse_time_zone (s + 7, n - 7, zh_, zm_)) + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + + z_ = true; + } + else + z_ = false; + } + + gmonth_day gmonth_day_pimpl:: + post_gmonth_day () + { + return z_ + ? gmonth_day (month_, day_, zh_, zm_) + : gmonth_day (month_, day_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/gmonth-day.hxx b/libxsde/xsde/cxx/parser/validating/gmonth-day.hxx new file mode 100644 index 0000000..7ec4d59 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gmonth-day.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/gmonth-day.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_GMONTH_DAY_HXX +#define XSDE_CXX_PARSER_VALIDATING_GMONTH_DAY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_day_pimpl: virtual gmonth_day_pskel +#else + struct gmonth_day_pimpl: gmonth_day_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual gmonth_day + post_gmonth_day (); + + protected: + string str_; + unsigned short month_, day_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_GMONTH_DAY_HXX diff --git a/libxsde/xsde/cxx/parser/validating/gmonth.cxx b/libxsde/xsde/cxx/parser/validating/gmonth.cxx new file mode 100644 index 0000000..a6f5fc1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gmonth.cxx @@ -0,0 +1,112 @@ +// file : xsde/cxx/parser/validating/gmonth.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void gmonth_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gmonth_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void gmonth_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gmonth := --MM[Z|(+|-)HH:MM] + // + if (n < 4 || s[0] != '-' || s[1] != '-') + { + _schema_error (schema_error::invalid_gmonth_value); + return; + } + + char d1 = s[2]; + char d2 = s[3]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_gmonth_value); + return; + } + + month_ = 10 * (d1 - '0') + (d2 - '0'); + + if (month_ < 1 || month_ > 12) + { + _schema_error (schema_error::invalid_gmonth_value); + return; + } + + if (n > 4) + { + if (!bits::parse_time_zone (s + 4, n - 4, zh_, zm_)) + { + _schema_error (schema_error::invalid_gmonth_value); + return; + } + + z_ = true; + } + else + z_ = false; + } + + gmonth gmonth_pimpl:: + post_gmonth () + { + return z_ ? gmonth (month_, zh_, zm_) : gmonth (month_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/gmonth.hxx b/libxsde/xsde/cxx/parser/validating/gmonth.hxx new file mode 100644 index 0000000..cfd0e92 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gmonth.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/gmonth.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_GMONTH_HXX +#define XSDE_CXX_PARSER_VALIDATING_GMONTH_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_pimpl: virtual gmonth_pskel +#else + struct gmonth_pimpl: gmonth_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual gmonth + post_gmonth (); + + protected: + string str_; + unsigned short month_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_GMONTH_HXX diff --git a/libxsde/xsde/cxx/parser/validating/gyear-month.cxx b/libxsde/xsde/cxx/parser/validating/gyear-month.cxx new file mode 100644 index 0000000..023b06c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gyear-month.cxx @@ -0,0 +1,161 @@ +// file : xsde/cxx/parser/validating/gyear-month.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void gyear_month_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gyear_month_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void gyear_month_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] + // + + if (n < 7 || (s[0] == '-' && n < 8)) + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + // Find the end of the year token. + // + ro_string::size_type pos = tmp.find ('-', s[0] == '-' ? 5 : 4); + + if (pos == ro_string::npos || (n - pos - 1) < 2) + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + // Parse the month value and time zone first so that we can + // truncate and reuse the string. + // + + // month + // + char d1 = s[pos + 1]; + char d2 = s[pos + 2]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + month_ = 10 * (d1 - '0') + (d2 - '0'); + + if (month_ < 1 || month_ > 12) + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + // zone + // + if ((pos + 3) < n) + { + if (!bits::parse_time_zone (s + pos + 3, n - pos - 3, zh_, zm_)) + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + z_ = true; + } + else + z_ = false; + + // year + // + str_.truncate (pos); + + char* p; + set_errno (0); + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL) || + ul == 0) + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + + year_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + + gyear_month gyear_month_pimpl:: + post_gyear_month () + { + return z_ + ? gyear_month (year_, month_, zh_, zm_) + : gyear_month (year_, month_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/gyear-month.hxx b/libxsde/xsde/cxx/parser/validating/gyear-month.hxx new file mode 100644 index 0000000..4e7933c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gyear-month.hxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/parser/validating/gyear-month.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_GYEAR_MONTH_HXX +#define XSDE_CXX_PARSER_VALIDATING_GYEAR_MONTH_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_month_pimpl: virtual gyear_month_pskel +#else + struct gyear_month_pimpl: gyear_month_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual gyear_month + post_gyear_month (); + + protected: + string str_; + int year_; + unsigned short month_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_GYEAR_MONTH_HXX diff --git a/libxsde/xsde/cxx/parser/validating/gyear.cxx b/libxsde/xsde/cxx/parser/validating/gyear.cxx new file mode 100644 index 0000000..cbe87e1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gyear.cxx @@ -0,0 +1,138 @@ +// file : xsde/cxx/parser/validating/gyear.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void gyear_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void gyear_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void gyear_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] + // + + if (n < 4 || (s[0] == '-' && n < 5)) + { + _schema_error (schema_error::invalid_gyear_value); + return; + } + + // Find the end of the year token. + // + ro_string::size_type pos = (s[0] == '-' ? 5 : 4); + for (; pos < n; ++pos) + { + char c = s[pos]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // Parse the time zone first so that we can truncate and + // reuse the string. + // + if (pos < n) + { + if (!bits::parse_time_zone (s + pos, n - pos, zh_, zm_)) + { + _schema_error (schema_error::invalid_gyear_value); + return; + } + + z_ = true; + } + else + z_ = false; + + // Parse the year value. + // + str_.truncate (pos); + + char* p; + set_errno (0); + bool neg = (s[0] == '-'); + unsigned long ul = strtoul (neg ? s + 1 : s, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL) || + ul == 0) + { + _schema_error (schema_error::invalid_gyear_value); + return; + } + + year_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + + gyear gyear_pimpl:: + post_gyear () + { + return z_ ? gyear (year_, zh_, zm_) : gyear (year_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/gyear.hxx b/libxsde/xsde/cxx/parser/validating/gyear.hxx new file mode 100644 index 0000000..557a6e4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/gyear.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/parser/validating/gyear.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_GYEAR_HXX +#define XSDE_CXX_PARSER_VALIDATING_GYEAR_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_pimpl: virtual gyear_pskel +#else + struct gyear_pimpl: gyear_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual gyear + post_gyear (); + + protected: + string str_; + int year_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_GYEAR_HXX diff --git a/libxsde/xsde/cxx/parser/validating/hex-binary.cxx b/libxsde/xsde/cxx/parser/validating/hex-binary.cxx new file mode 100644 index 0000000..5f5a02c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/hex-binary.cxx @@ -0,0 +1,172 @@ +// file : xsde/cxx/parser/validating/hex-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +static unsigned char +hex_decode (char c) +{ + unsigned char r = 0xFF; + + if (c >= '0' && c <= '9') + r = static_cast (c - '0'); + else if (c >= 'A' && c <= 'F') + r = static_cast (10 + (c - 'A')); + else if (c >= 'a' && c <= 'f') + r = static_cast (10 + (c - 'a')); + + return r; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + hex_binary_pimpl:: + ~hex_binary_pimpl () + { + if (!base_) + delete buf_; + } + + void hex_binary_pimpl:: + _reset () + { + hex_binary_pskel::_reset (); + + if (!base_) + { + delete buf_; + buf_ = 0; + } + } + + hex_binary_pimpl:: + hex_binary_pimpl (bool base) + : base_ (base), buf_ (0) + { + } + + void hex_binary_pimpl:: + pre_impl (buffer* b) + { + buf_ = b; + } + + void hex_binary_pimpl:: + _pre () + { + if (buf_ == 0) + { + buf_ = new buffer (); + +#ifndef XSDE_EXCEPTIONS + if (buf_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void hex_binary_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void hex_binary_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + if (size % 2 != 0) + { + _schema_error (schema_error::invalid_hex_binary_value); + return; + } + + size_t n = size / 2; + +#ifdef XSDE_EXCEPTIONS + buf_->size (n); +#else + if (buf_->size (n)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + + if (n != 0) + { + const char* src = tmp.data (); + char* dst = buf_->data (); + size_t i = 0; + + for (; i < n; ++i) + { + unsigned char h = hex_decode (src[2 * i]); + unsigned char l = hex_decode (src[2 * i + 1]); + + if (h == 0xFF || l == 0xFF) + break; + + dst[i] = (h << 4) | l; + } + + if (i != n) + _schema_error (schema_error::invalid_hex_binary_value); + } + } + + buffer* hex_binary_pimpl:: + post_hex_binary () + { + buffer* r = buf_; + buf_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/hex-binary.hxx b/libxsde/xsde/cxx/parser/validating/hex-binary.hxx new file mode 100644 index 0000000..4ba0e96 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/hex-binary.hxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/parser/validating/hex-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_HEX_BINARY_HXX +#define XSDE_CXX_PARSER_VALIDATING_HEX_BINARY_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct hex_binary_pimpl: virtual hex_binary_pskel +#else + struct hex_binary_pimpl: hex_binary_pskel +#endif + { + ~hex_binary_pimpl (); + hex_binary_pimpl (bool base = false); + + void + pre_impl (buffer*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual buffer* + post_hex_binary (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + buffer* buf_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_HEX_BINARY_HXX diff --git a/libxsde/xsde/cxx/parser/validating/id-stl.cxx b/libxsde/xsde/cxx/parser/validating/id-stl.cxx new file mode 100644 index 0000000..84d487c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/id-stl.cxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/parser/validating/id-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void id_pimpl:: + _pre () + { + str_.erase (); + } + + void id_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void id_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.resize (size); + else + _schema_error (schema_error::invalid_id_value); + } + + std::string id_pimpl:: + post_id () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/id-stl.hxx b/libxsde/xsde/cxx/parser/validating/id-stl.hxx new file mode 100644 index 0000000..8ded862 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/id-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/id-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_ID_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_ID_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_pimpl: virtual id_pskel +#else + struct id_pimpl: id_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_id (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_ID_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/id.cxx b/libxsde/xsde/cxx/parser/validating/id.cxx new file mode 100644 index 0000000..f5b1daf --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/id.cxx @@ -0,0 +1,80 @@ +// file : xsde/cxx/parser/validating/id.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void id_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void id_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void id_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.truncate (size); + else + _schema_error (schema_error::invalid_id_value); + } + + char* id_pimpl:: + post_id () + { + return str_.detach (); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/validating/id.hxx b/libxsde/xsde/cxx/parser/validating/id.hxx new file mode 100644 index 0000000..2b02290 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/id.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/id.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_ID_HXX +#define XSDE_CXX_PARSER_VALIDATING_ID_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_pimpl: virtual id_pskel +#else + struct id_pimpl: id_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_id (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_ID_HXX diff --git a/libxsde/xsde/cxx/parser/validating/idref-stl.cxx b/libxsde/xsde/cxx/parser/validating/idref-stl.cxx new file mode 100644 index 0000000..a7a4f10 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idref-stl.cxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/parser/validating/idref-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void idref_pimpl:: + _pre () + { + str_.erase (); + } + + void idref_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void idref_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.resize (size); + else + _schema_error (schema_error::invalid_idref_value); + } + + std::string idref_pimpl:: + post_idref () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/idref-stl.hxx b/libxsde/xsde/cxx/parser/validating/idref-stl.hxx new file mode 100644 index 0000000..0382400 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idref-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/idref-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_IDREF_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_IDREF_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_pimpl: virtual idref_pskel +#else + struct idref_pimpl: idref_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_idref (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_IDREF_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/idref.cxx b/libxsde/xsde/cxx/parser/validating/idref.cxx new file mode 100644 index 0000000..1e0b320 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idref.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/parser/validating/idref.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void idref_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void idref_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void idref_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.truncate (size); + else + _schema_error (schema_error::invalid_idref_value); + } + + char* idref_pimpl:: + post_idref () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/idref.hxx b/libxsde/xsde/cxx/parser/validating/idref.hxx new file mode 100644 index 0000000..bfbacb9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idref.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/idref.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_IDREF_HXX +#define XSDE_CXX_PARSER_VALIDATING_IDREF_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_pimpl: virtual idref_pskel +#else + struct idref_pimpl: idref_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_idref (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_IDREF_HXX diff --git a/libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx b/libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx new file mode 100644 index 0000000..0451a43 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx @@ -0,0 +1,133 @@ +// file : xsde/cxx/parser/validating/idrefs-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + idrefs_pimpl:: + ~idrefs_pimpl () + { + if (!base_) + delete seq_; + } + + void idrefs_pimpl:: + _reset () + { + idrefs_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + idrefs_pimpl:: + idrefs_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void idrefs_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void idrefs_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + idrefs_pskel::_pre (); + } + + void idrefs_pimpl:: + _post () + { + idrefs_pskel::_post (); + + // Should have at least one element. + // + if (!_context ().error_type () && seq_->size () < 1) + _schema_error (schema_error::invalid_idrefs_value); + } + + string_sequence* idrefs_pimpl:: + post_idrefs () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void idrefs_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + idref_pskel& p = parser_; + + p.pre (); + +#ifndef XSDE_EXCEPTIONS + if (!p._error_type ()) + p._pre_impl (ctx); + else + p._copy_error (ctx); +#else + p._pre_impl (ctx); +#endif + if (!ctx.error_type ()) + p._characters (s); + + if (!ctx.error_type ()) + p._post_impl (); + + if (!ctx.error_type ()) + { + const std::string& x = p.post_idref (); + +#ifndef XSDE_EXCEPTIONS + if (!p._error_type ()) + seq_->push_back (x); + else + p._copy_error (ctx); +#else + seq_->push_back (x); +#endif + } + } + } + } + } +} + +#include diff --git a/libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx b/libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx new file mode 100644 index 0000000..44dfea8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/parser/validating/idrefs-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_IDREFS_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_IDREFS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_pimpl: virtual idrefs_pskel +#else + struct idrefs_pimpl: idrefs_pskel +#endif + { + ~idrefs_pimpl (); + idrefs_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _post (); + + virtual string_sequence* + post_idrefs (); + + virtual void + _reset (); + + protected: + bool base_; + idref_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_IDREFS_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/idrefs.cxx b/libxsde/xsde/cxx/parser/validating/idrefs.cxx new file mode 100644 index 0000000..f6072a5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idrefs.cxx @@ -0,0 +1,136 @@ +// file : xsde/cxx/parser/validating/idrefs.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + idrefs_pimpl:: + ~idrefs_pimpl () + { + if (!base_) + delete seq_; + } + + void idrefs_pimpl:: + _reset () + { + idrefs_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + idrefs_pimpl:: + idrefs_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void idrefs_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void idrefs_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + idrefs_pskel::_pre (); + } + + void idrefs_pimpl:: + _post () + { + idrefs_pskel::_post (); + + // Should have at least one element. + // + if (!_context ().error_type () && seq_->size () < 1) + _schema_error (schema_error::invalid_idrefs_value); + } + + string_sequence* idrefs_pimpl:: + post_idrefs () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void idrefs_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + parser_.pre (); + +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + parser_._pre_impl (ctx); + else + parser_._copy_error (ctx); +#else + parser_._pre_impl (ctx); +#endif + if (!ctx.error_type ()) + parser_._characters (s); + + if (!ctx.error_type ()) + parser_._post_impl (); + + if (!ctx.error_type ()) + { + char* x = parser_.post_idref (); + + // push_back() frees the string if it fails. + // +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + { + if (seq_->push_back (x)) + _sys_error (sys_error::no_memory); + } + else + parser_._copy_error (ctx); +#else + seq_->push_back (x); +#endif + } + } + } + } + } +} + +#include diff --git a/libxsde/xsde/cxx/parser/validating/idrefs.hxx b/libxsde/xsde/cxx/parser/validating/idrefs.hxx new file mode 100644 index 0000000..f2415ff --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/idrefs.hxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/parser/validating/idrefs.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_IDREFS_HXX +#define XSDE_CXX_PARSER_VALIDATING_IDREFS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_pimpl: virtual idrefs_pskel +#else + struct idrefs_pimpl: idrefs_pskel +#endif + { + ~idrefs_pimpl (); + idrefs_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _post (); + + virtual string_sequence* + post_idrefs (); + + virtual void + _reset (); + + protected: + bool base_; + idref_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_IDREFS_HXX diff --git a/libxsde/xsde/cxx/parser/validating/inheritance-map-load.hxx b/libxsde/xsde/cxx/parser/validating/inheritance-map-load.hxx new file mode 100644 index 0000000..ad04019 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/inheritance-map-load.hxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/parser/validating/inheritance-map-load.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_LOAD_HXX +#define XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_LOAD_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + size_t + parser_imap_elements (); + + inline size_t + parser_imap_buckets () + { + return XSDE_PARSER_IMAP_BUCKETS; + } + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_LOAD_HXX + diff --git a/libxsde/xsde/cxx/parser/validating/inheritance-map.cxx b/libxsde/xsde/cxx/parser/validating/inheritance-map.cxx new file mode 100644 index 0000000..491ec8d --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/inheritance-map.cxx @@ -0,0 +1,111 @@ +// file : xsde/cxx/parser/validating/inheritance-map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // strcmp + +#ifndef XSDE_EXCEPTIONS +# include // assert +# include // exit +#endif + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + inheritance_map* inheritance_map_init::map = 0; + size_t inheritance_map_init::count = 0; + + bool inheritance_map:: + check (const char* derived, const char* base) const + { + if (strcmp (derived, base) == 0) + return true; + + const void* p = find (derived); + + if (p) + { + const char* b = *static_cast (p); + return strcmp (base, b) == 0 ? true : check (b, base); + } + + return false; + } + + // inheritance_map_init + // + inheritance_map_init:: + inheritance_map_init () + { + if (count == 0) + { + map = new inheritance_map (XSDE_PARSER_IMAP_BUCKETS); + +#ifndef XSDE_EXCEPTIONS + if (map == 0 || map->_error () != inheritance_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + ++count; + } + + inheritance_map_init:: + ~inheritance_map_init () + { + if (--count == 0) + delete map; + } + + // inheritance_map_entry + // + inheritance_map_entry:: + inheritance_map_entry (const char* derived, const char* base) + { + inheritance_map& m = inheritance_map_instance (); + m.insert (derived, base); + +#ifndef XSDE_EXCEPTIONS + if (m._error () != inheritance_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + // + // + size_t + parser_imap_elements () + { + return inheritance_map_instance ().size (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/inheritance-map.hxx b/libxsde/xsde/cxx/parser/validating/inheritance-map.hxx new file mode 100644 index 0000000..6329545 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/inheritance-map.hxx @@ -0,0 +1,63 @@ +// file : xsde/cxx/parser/validating/inheritance-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_HXX +#define XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_HXX + +#include // size_t + +#include +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + struct inheritance_map: hashmap + { + inheritance_map (size_t buckets); + + void + insert (const char* derived, const char* base); + + bool + check (const char* derived, const char* base) const; + }; + + + // Translation unit initializer. + // + struct inheritance_map_init + { + static inheritance_map* map; + static size_t count; + + inheritance_map_init (); + ~inheritance_map_init (); + }; + + inline inheritance_map& + inheritance_map_instance (); + + // Map entry initializer. + // + struct inheritance_map_entry + { + inheritance_map_entry (const char* derived, const char* base); + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_VALIDATING_INHERITANCE_MAP_HXX + diff --git a/libxsde/xsde/cxx/parser/validating/inheritance-map.ixx b/libxsde/xsde/cxx/parser/validating/inheritance-map.ixx new file mode 100644 index 0000000..4f76685 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/inheritance-map.ixx @@ -0,0 +1,34 @@ +// file : xsde/cxx/parser/validating/inheritance-map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + inline inheritance_map:: + inheritance_map (size_t buckets) + : hashmap (buckets, sizeof (const char*)) + { + } + + inline void inheritance_map:: + insert (const char* derived, const char* base) + { + hashmap::insert (derived, &base); + } + + inline inheritance_map& + inheritance_map_instance () + { + return *inheritance_map_init::map; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/int.cxx b/libxsde/xsde/cxx/parser/validating/int.cxx new file mode 100644 index 0000000..bfbac40 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/int.cxx @@ -0,0 +1,75 @@ +// file : xsde/cxx/parser/validating/int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void int_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void int_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 11)) + _schema_error (schema_error::invalid_int_value); + } + + void int_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL)) + _schema_error (schema_error::invalid_int_value); + + value_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + else + _schema_error (schema_error::invalid_int_value); + } + + int int_pimpl:: + post_int () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/int.hxx b/libxsde/xsde/cxx/parser/validating/int.hxx new file mode 100644 index 0000000..7172af7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/int.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_INT_HXX +#define XSDE_CXX_PARSER_VALIDATING_INT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 32-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct int_pimpl: virtual int_pskel, number +#else + struct int_pimpl: int_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual int + post_int (); + + protected: + // We only need strlen("02147483648") + 1 characters to hold all + // valid and trimmed string representations of int. + // + char str_[12]; + int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_INT_HXX diff --git a/libxsde/xsde/cxx/parser/validating/integer.cxx b/libxsde/xsde/cxx/parser/validating/integer.cxx new file mode 100644 index 0000000..e3255e3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/integer.cxx @@ -0,0 +1,75 @@ +// file : xsde/cxx/parser/validating/integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN, LONG_MAX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void integer_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 20)) + _schema_error (schema_error::invalid_integer_value); + } + + void integer_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > static_cast (LONG_MIN)) || + (!neg && ul > LONG_MAX)) + _schema_error (schema_error::invalid_integer_value); + + value_ = neg + ? (ul == static_cast (LONG_MIN) + ? LONG_MIN: -static_cast (ul)) + : static_cast (ul); + } + else + _schema_error (schema_error::invalid_integer_value); + } + + long integer_pimpl:: + post_integer () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/integer.hxx b/libxsde/xsde/cxx/parser/validating/integer.hxx new file mode 100644 index 0000000..ec7c863 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/integer.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_INTEGER_HXX +#define XSDE_CXX_PARSER_VALIDATING_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Arbitrary-length integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct integer_pimpl: virtual integer_pskel, number +#else + struct integer_pimpl: integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual long + post_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/language-stl.cxx b/libxsde/xsde/cxx/parser/validating/language-stl.cxx new file mode 100644 index 0000000..53e0e75 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/language-stl.cxx @@ -0,0 +1,95 @@ +// file : xsde/cxx/parser/validating/language-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void language_pimpl:: + _pre () + { + str_.erase (); + } + + void language_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void language_pimpl:: + _post () + { + typedef ro_string::size_type size_type; + + ro_string tmp (str_); + size_type size = trim_right (tmp); + + // language := ALPHA{1,8} *(-(ALPHA | DIGIT){1,8}) + // + bool ok = true; + size_type i = 0; + + for (size_type tag = 0; ; ++tag) + { + size_type n = 0; + + for (; i < size && n < 8; ++n, ++i) + { + char c = tmp[i]; + + if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (tag != 0 && c >= '0' && c <= '9'))) + break; + } + + if (n == 0) + { + ok = false; + break; + } + + if (i == size) + break; + + if (tmp[i++] != '-') + { + ok = false; + break; + } + } + + if (ok) + str_.resize (size); + else + _schema_error (schema_error::invalid_language_value); + } + + std::string language_pimpl:: + post_language () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/language-stl.hxx b/libxsde/xsde/cxx/parser/validating/language-stl.hxx new file mode 100644 index 0000000..8c0dfca --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/language-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/language-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_LANGUAGE_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_LANGUAGE_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_pimpl: virtual language_pskel +#else + struct language_pimpl: language_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_language (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_LANGUAGE_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/language.cxx b/libxsde/xsde/cxx/parser/validating/language.cxx new file mode 100644 index 0000000..177be73 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/language.cxx @@ -0,0 +1,114 @@ +// file : xsde/cxx/parser/validating/language.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void language_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void language_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void language_pimpl:: + _post () + { + typedef ro_string::size_type size_type; + + ro_string tmp (str_); + size_type size = trim_right (tmp); + + // language := ALPHA{1,8} *(-(ALPHA | DIGIT){1,8}) + // + bool ok = true; + size_type i = 0; + + for (size_type tag = 0; ; ++tag) + { + size_type n = 0; + + for (; i < size && n < 8; ++n, ++i) + { + char c = tmp[i]; + + if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (tag != 0 && c >= '0' && c <= '9'))) + break; + } + + if (n == 0) + { + ok = false; + break; + } + + if (i == size) + break; + + if (tmp[i++] != '-') + { + ok = false; + break; + } + } + + if (ok) + str_.truncate (size); + else + _schema_error (schema_error::invalid_language_value); + } + + char* language_pimpl:: + post_language () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/language.hxx b/libxsde/xsde/cxx/parser/validating/language.hxx new file mode 100644 index 0000000..4321b00 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/language.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/language.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_LANGUAGE_HXX +#define XSDE_CXX_PARSER_VALIDATING_LANGUAGE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_pimpl: virtual language_pskel +#else + struct language_pimpl: language_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_language (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_LANGUAGE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/long-long.cxx b/libxsde/xsde/cxx/parser/validating/long-long.cxx new file mode 100644 index 0000000..66fec5b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/long-long.cxx @@ -0,0 +1,75 @@ +// file : xsde/cxx/parser/validating/long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoull + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void long_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 20)) + _schema_error (schema_error::invalid_long_value); + } + + void long_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long long ull = strtoull (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ull > 9223372036854775808ULL) || + (!neg && ull > 9223372036854775807ULL)) + _schema_error (schema_error::invalid_long_value); + + value_ = neg + ? (ull == 9223372036854775808ULL + ? (-9223372036854775807LL - 1) + : -static_cast (ull)) + : static_cast (ull); + } + else + _schema_error (schema_error::invalid_long_value); + } + + long long long_pimpl:: + post_long () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/long-long.hxx b/libxsde/xsde/cxx/parser/validating/long-long.hxx new file mode 100644 index 0000000..b7e830b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/long-long.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_LONG_LONG_HXX +#define XSDE_CXX_PARSER_VALIDATING_LONG_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 64-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_pimpl: virtual long_pskel, number +#else + struct long_pimpl: long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual long long + post_long (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long long. + // + char str_[21]; + long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/validating/long.cxx b/libxsde/xsde/cxx/parser/validating/long.cxx new file mode 100644 index 0000000..d1f24b4 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/long.cxx @@ -0,0 +1,75 @@ +// file : xsde/cxx/parser/validating/long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void long_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 20)) + _schema_error (schema_error::invalid_long_value); + } + + void long_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || + get_errno () != 0 || + (neg && ul > 2147483648UL) || + (!neg && ul > 2147483647UL)) + _schema_error (schema_error::invalid_long_value); + + value_ = neg + ? (ul == 2147483648UL + ? (-2147483647 - 1) + : -static_cast (ul)) + : static_cast (ul); + } + else + _schema_error (schema_error::invalid_long_value); + } + + long long_pimpl:: + post_long () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/long.hxx b/libxsde/xsde/cxx/parser/validating/long.hxx new file mode 100644 index 0000000..f87c6c6 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/long.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_LONG_HXX +#define XSDE_CXX_PARSER_VALIDATING_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_pimpl: virtual long_pskel, number +#else + struct long_pimpl: long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual long + post_long (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long long. + // + char str_[21]; + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/validating/name-stl.cxx b/libxsde/xsde/cxx/parser/validating/name-stl.cxx new file mode 100644 index 0000000..a691f94 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/name-stl.cxx @@ -0,0 +1,86 @@ +// file : xsde/cxx/parser/validating/name-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void name_pimpl:: + _pre () + { + str_.erase (); + } + + void name_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void name_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + // For now we are only checking the US-ASCII characters. + // + + bool ok = (size != 0); + + if (ok) + { + unsigned char c = static_cast (str_[0]); + + ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask); + + if (ok) + { + for (ro_string::size_type i = 1; i < size; ++i) + { + c = static_cast (str_[i]); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + { + ok = false; + break; + } + } + } + } + + str_.resize (size); + + if (!ok) + _schema_error (schema_error::invalid_name_value); + } + + std::string name_pimpl:: + post_name () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/name-stl.hxx b/libxsde/xsde/cxx/parser/validating/name-stl.hxx new file mode 100644 index 0000000..d3d7e02 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/name-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/name-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NAME_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_NAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_pimpl: virtual name_pskel +#else + struct name_pimpl: name_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_name (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/name.cxx b/libxsde/xsde/cxx/parser/validating/name.cxx new file mode 100644 index 0000000..167aa47 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/name.cxx @@ -0,0 +1,105 @@ +// file : xsde/cxx/parser/validating/name.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void name_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void name_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void name_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + + // For now we are only checking the US-ASCII characters. + // + + bool ok = (size != 0); + + if (ok) + { + unsigned char c = static_cast (str_[0]); + + ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask); + + if (ok) + { + for (ro_string::size_type i = 1; i < size; ++i) + { + c = static_cast (str_[i]); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + { + ok = false; + break; + } + } + } + } + + str_.truncate (size); + + if (!ok) + _schema_error (schema_error::invalid_name_value); + } + + char* name_pimpl:: + post_name () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/name.hxx b/libxsde/xsde/cxx/parser/validating/name.hxx new file mode 100644 index 0000000..9f9046f --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/name.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/name.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NAME_HXX +#define XSDE_CXX_PARSER_VALIDATING_NAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_pimpl: virtual name_pskel +#else + struct name_pimpl: name_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_name (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NAME_HXX diff --git a/libxsde/xsde/cxx/parser/validating/ncname-stl.cxx b/libxsde/xsde/cxx/parser/validating/ncname-stl.cxx new file mode 100644 index 0000000..50bea6f --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/ncname-stl.cxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/parser/validating/ncname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void ncname_pimpl:: + _pre () + { + str_.erase (); + } + + void ncname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void ncname_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.resize (size); + else + _schema_error (schema_error::invalid_ncname_value); + } + + std::string ncname_pimpl:: + post_ncname () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/ncname-stl.hxx b/libxsde/xsde/cxx/parser/validating/ncname-stl.hxx new file mode 100644 index 0000000..6329c18 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/ncname-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/ncname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NCNAME_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_NCNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_pimpl: virtual ncname_pskel +#else + struct ncname_pimpl: ncname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_ncname (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NCNAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/ncname.cxx b/libxsde/xsde/cxx/parser/validating/ncname.cxx new file mode 100644 index 0000000..c664014 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/ncname.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/parser/validating/ncname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void ncname_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void ncname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void ncname_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + + if (xml::valid_ncname (tmp.data (), size)) + str_.truncate (size); + else + _schema_error (schema_error::invalid_ncname_value); + } + + char* ncname_pimpl:: + post_ncname () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/ncname.hxx b/libxsde/xsde/cxx/parser/validating/ncname.hxx new file mode 100644 index 0000000..89a5521 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/ncname.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/ncname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NCNAME_HXX +#define XSDE_CXX_PARSER_VALIDATING_NCNAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_pimpl: virtual ncname_pskel +#else + struct ncname_pimpl: ncname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_ncname (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NCNAME_HXX diff --git a/libxsde/xsde/cxx/parser/validating/negative-integer.cxx b/libxsde/xsde/cxx/parser/validating/negative-integer.cxx new file mode 100644 index 0000000..e5c78a8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/negative-integer.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/parser/validating/negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void negative_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void negative_integer_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 20)) + _schema_error (schema_error::invalid_negative_integer_value); + } + + void negative_integer_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (sign_ == minus && size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + ul == 0 || + ul > static_cast (LONG_MIN)) + _schema_error (schema_error::invalid_negative_integer_value); + + value_ = ul == static_cast (LONG_MIN) + ? LONG_MIN : -static_cast (ul); + } + else + _schema_error (schema_error::invalid_negative_integer_value); + } + + long negative_integer_pimpl:: + post_negative_integer () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/negative-integer.hxx b/libxsde/xsde/cxx/parser/validating/negative-integer.hxx new file mode 100644 index 0000000..0839b03 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/negative-integer.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_VALIDATING_NEGATIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Arbitrary-length negative integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct negative_integer_pimpl: virtual negative_integer_pskel, number +#else + struct negative_integer_pimpl: negative_integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual long + post_negative_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx b/libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx new file mode 100644 index 0000000..0f7e987 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/parser/validating/nmtoken-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void nmtoken_pimpl:: + _pre () + { + str_.erase (); + } + + void nmtoken_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void nmtoken_pimpl:: + _post () + { + ro_string tmp (str_); + ro_string::size_type size = trim_right (tmp); + + // For now we are only checking the US-ASCII characters. + // + + bool ok = (size != 0); + + if (ok) + { + for (ro_string::size_type i = 0; i < size; ++i) + { + unsigned char c = static_cast (str_[i]); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + { + ok = false; + break; + } + } + } + + str_.resize (size); + + if (!ok) + _schema_error (schema_error::invalid_nmtoken_value); + } + + std::string nmtoken_pimpl:: + post_nmtoken () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx b/libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx new file mode 100644 index 0000000..5166018 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/nmtoken-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NMTOKEN_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_NMTOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_pimpl: virtual nmtoken_pskel +#else + struct nmtoken_pimpl: nmtoken_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual std::string + post_nmtoken (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NMTOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/nmtoken.cxx b/libxsde/xsde/cxx/parser/validating/nmtoken.cxx new file mode 100644 index 0000000..875b8e3 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtoken.cxx @@ -0,0 +1,98 @@ +// file : xsde/cxx/parser/validating/nmtoken.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void nmtoken_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void nmtoken_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void nmtoken_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + + // For now we are only checking the US-ASCII characters. + // + + bool ok = (size != 0); + + if (ok) + { + for (ro_string::size_type i = 0; i < size; ++i) + { + unsigned char c = static_cast (str_[i]); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + { + ok = false; + break; + } + } + } + + str_.truncate (size); + + if (!ok) + _schema_error (schema_error::invalid_nmtoken_value); + } + + char* nmtoken_pimpl:: + post_nmtoken () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/nmtoken.hxx b/libxsde/xsde/cxx/parser/validating/nmtoken.hxx new file mode 100644 index 0000000..f4d322e --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtoken.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/parser/validating/nmtoken.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NMTOKEN_HXX +#define XSDE_CXX_PARSER_VALIDATING_NMTOKEN_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_pimpl: virtual nmtoken_pskel +#else + struct nmtoken_pimpl: nmtoken_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual char* + post_nmtoken (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NMTOKEN_HXX diff --git a/libxsde/xsde/cxx/parser/validating/nmtokens-stl.cxx b/libxsde/xsde/cxx/parser/validating/nmtokens-stl.cxx new file mode 100644 index 0000000..1c88132 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtokens-stl.cxx @@ -0,0 +1,127 @@ +// file : xsde/cxx/parser/validating/nmtokens-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + nmtokens_pimpl:: + ~nmtokens_pimpl () + { + if (!base_) + delete seq_; + } + + void nmtokens_pimpl:: + _reset () + { + nmtokens_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + nmtokens_pimpl:: + nmtokens_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void nmtokens_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void nmtokens_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + nmtokens_pskel::_pre (); + } + + void nmtokens_pimpl:: + _post () + { + nmtokens_pskel::_post (); + + // Should have at least one element. + // + if (!_context ().error_type () && seq_->size () < 1) + _schema_error (schema_error::invalid_nmtokens_value); + } + + string_sequence* nmtokens_pimpl:: + post_nmtokens () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void nmtokens_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + parser_.pre (); + +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + parser_._pre_impl (ctx); + else + parser_._copy_error (ctx); +#else + parser_._pre_impl (ctx); +#endif + if (!ctx.error_type ()) + parser_._characters (s); + + if (!ctx.error_type ()) + parser_._post_impl (); + + if (!ctx.error_type ()) + { + const std::string& x = parser_.post_nmtoken (); + +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + seq_->push_back (x); + else + parser_._copy_error (ctx); +#else + seq_->push_back (x); +#endif + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/nmtokens-stl.hxx b/libxsde/xsde/cxx/parser/validating/nmtokens-stl.hxx new file mode 100644 index 0000000..6cbc464 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtokens-stl.hxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/parser/validating/nmtokens-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NMTOKENS_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_NMTOKENS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_pimpl: virtual nmtokens_pskel +#else + struct nmtokens_pimpl: nmtokens_pskel +#endif + { + ~nmtokens_pimpl (); + nmtokens_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _post (); + + virtual string_sequence* + post_nmtokens (); + + virtual void + _reset (); + + protected: + bool base_; + nmtoken_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NMTOKENS_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/nmtokens.cxx b/libxsde/xsde/cxx/parser/validating/nmtokens.cxx new file mode 100644 index 0000000..074294d --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtokens.cxx @@ -0,0 +1,132 @@ +// file : xsde/cxx/parser/validating/nmtokens.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + nmtokens_pimpl:: + ~nmtokens_pimpl () + { + if (!base_) + delete seq_; + } + + void nmtokens_pimpl:: + _reset () + { + nmtokens_pskel::_reset (); + + if (!base_) + { + delete seq_; + seq_ = 0; + } + + parser_._reset (); + } + + nmtokens_pimpl:: + nmtokens_pimpl (bool base) + : base_ (base), seq_ (0) + { + } + + void nmtokens_pimpl:: + pre_impl (string_sequence* seq) + { + seq_ = seq; + } + + void nmtokens_pimpl:: + _pre () + { + if (seq_ == 0) + { + seq_ = new string_sequence (); + +#ifndef XSDE_EXCEPTIONS + if (seq_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + + nmtokens_pskel::_pre (); + } + + void nmtokens_pimpl:: + _post () + { + nmtokens_pskel::_post (); + + // Should have at least one element. + // + if (!_context ().error_type () && seq_->size () < 1) + _schema_error (schema_error::invalid_nmtokens_value); + } + + string_sequence* nmtokens_pimpl:: + post_nmtokens () + { + string_sequence* r = seq_; + seq_ = 0; + return r; + } + + void nmtokens_pimpl:: + _xsde_parse_item (const ro_string& s) + { + context& ctx = _context (); + + parser_.pre (); + +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + parser_._pre_impl (ctx); + else + parser_._copy_error (ctx); +#else + parser_._pre_impl (ctx); +#endif + if (!ctx.error_type ()) + parser_._characters (s); + + if (!ctx.error_type ()) + parser_._post_impl (); + + if (!ctx.error_type ()) + { + char* x = parser_.post_nmtoken (); + + // push_back() frees the string if it fails. + // +#ifndef XSDE_EXCEPTIONS + if (!parser_._error_type ()) + { + if (seq_->push_back (x)) + _sys_error (sys_error::no_memory); + } + else + parser_._copy_error (ctx); +#else + seq_->push_back (x); +#endif + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/nmtokens.hxx b/libxsde/xsde/cxx/parser/validating/nmtokens.hxx new file mode 100644 index 0000000..f24161a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/nmtokens.hxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/parser/validating/nmtokens.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NMTOKENS_HXX +#define XSDE_CXX_PARSER_VALIDATING_NMTOKENS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_pimpl: virtual nmtokens_pskel +#else + struct nmtokens_pimpl: nmtokens_pskel +#endif + { + ~nmtokens_pimpl (); + nmtokens_pimpl (bool base = false); + + void + pre_impl (string_sequence*); + + virtual void + _pre (); + + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _post (); + + virtual string_sequence* + post_nmtokens (); + + virtual void + _reset (); + + protected: + bool base_; + nmtoken_pimpl parser_; + string_sequence* seq_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NMTOKENS_HXX diff --git a/libxsde/xsde/cxx/parser/validating/non-negative-integer.cxx b/libxsde/xsde/cxx/parser/validating/non-negative-integer.cxx new file mode 100644 index 0000000..7333abf --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/non-negative-integer.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/parser/validating/non-negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void non_negative_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void non_negative_integer_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 21)) + _schema_error (schema_error::invalid_non_negative_integer_value); + } + + void non_negative_integer_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + value_ = strtoul (str_, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (sign_ == minus && value_ != 0)) + _schema_error (schema_error::invalid_non_negative_integer_value); + } + else + _schema_error (schema_error::invalid_non_negative_integer_value); + } + + unsigned long non_negative_integer_pimpl:: + post_non_negative_integer () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/non-negative-integer.hxx b/libxsde/xsde/cxx/parser/validating/non-negative-integer.hxx new file mode 100644 index 0000000..36dabf7 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/non-negative-integer.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/validating/non-negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NON_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_VALIDATING_NON_NEGATIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Arbitrary-length non-negative integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_negative_integer_pimpl: virtual non_negative_integer_pskel, +#else + struct non_negative_integer_pimpl: non_negative_integer_pskel, +#endif + number + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned long + post_non_negative_integer (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long, assuming we are on a 64 bit machine. + // + char str_[22]; + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NON_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/non-positive-integer.cxx b/libxsde/xsde/cxx/parser/validating/non-positive-integer.cxx new file mode 100644 index 0000000..0560a34 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/non-positive-integer.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/parser/validating/non-positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul +#include // LONG_MIN + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void non_positive_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void non_positive_integer_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 20)) + _schema_error (schema_error::invalid_non_positive_integer_value); + } + + void non_positive_integer_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + if (*p != '\0' || + get_errno () != 0 || + (sign_ != minus && ul != 0) || + ul > static_cast (LONG_MIN)) + _schema_error (schema_error::invalid_non_positive_integer_value); + + value_ = ul == static_cast (LONG_MIN) + ? LONG_MIN : -static_cast (ul); + } + else + _schema_error (schema_error::invalid_non_positive_integer_value); + } + + long non_positive_integer_pimpl:: + post_non_positive_integer () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/non-positive-integer.hxx b/libxsde/xsde/cxx/parser/validating/non-positive-integer.hxx new file mode 100644 index 0000000..f592289 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/non-positive-integer.hxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/parser/validating/non-positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NON_POSITIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_VALIDATING_NON_POSITIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Arbitrary-length non-positive integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_positive_integer_pimpl: virtual non_positive_integer_pskel, +#else + struct non_positive_integer_pimpl: non_positive_integer_pskel, +#endif + number + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual long + post_non_positive_integer (); + + protected: + // We only need strlen("09223372036854775808") + 1 characters to + // hold all valid and trimmed string representations of long, + // assuming we are on a 64 bit machine. + // + char str_[21]; + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NON_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/normalized-string-stl.cxx b/libxsde/xsde/cxx/parser/validating/normalized-string-stl.cxx new file mode 100644 index 0000000..131b4a1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/normalized-string-stl.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/validating/normalized-string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void normalized_string_pimpl:: + _pre () + { + str_.erase (); + } + + void normalized_string_pimpl:: + _characters (const ro_string& s) + { + str_ += s; + } + + std::string normalized_string_pimpl:: + post_normalized_string () + { + std::string::size_type size = str_.size (); + + for (std::string::size_type i = 0; i < size; ++i) + { + char& c = str_[i]; + + if (c == 0x0A || c == 0x0D || c == 0x09) + c = 0x20; + } + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/normalized-string-stl.hxx b/libxsde/xsde/cxx/parser/validating/normalized-string-stl.hxx new file mode 100644 index 0000000..02247d2 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/normalized-string-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/normalized-string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_pimpl: virtual normalized_string_pskel +#else + struct normalized_string_pimpl: normalized_string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_normalized_string (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/normalized-string.cxx b/libxsde/xsde/cxx/parser/validating/normalized-string.cxx new file mode 100644 index 0000000..634cf2e --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/normalized-string.cxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/parser/validating/normalized-string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void normalized_string_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void normalized_string_pimpl:: + _characters (const ro_string& s) + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + + char* normalized_string_pimpl:: + post_normalized_string () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + + for (size_type i = 0; i < size; ++i) + { + char& c = str_[i]; + + if (c == 0x0A || c == 0x0D || c == 0x09) + c = 0x20; + } + + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/normalized-string.hxx b/libxsde/xsde/cxx/parser/validating/normalized-string.hxx new file mode 100644 index 0000000..5446ceb --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/normalized-string.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/normalized-string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_HXX +#define XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_pimpl: virtual normalized_string_pskel +#else + struct normalized_string_pimpl: normalized_string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_normalized_string (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NORMALIZED_STRING_HXX diff --git a/libxsde/xsde/cxx/parser/validating/number.cxx b/libxsde/xsde/cxx/parser/validating/number.cxx new file mode 100644 index 0000000..62b7d53 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/number.cxx @@ -0,0 +1,133 @@ +// file : xsde/cxx/parser/validating/number.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy + +#include + +using xsde::cxx::ro_string; + +static bool +trim_leading_zeros (ro_string& s) +{ + ro_string::size_type size = s.size (); + + if (size != 0) + { + const char* f = s.data (); + const char* l = f + size; + const char* of = f; + + while (f < l && *f == '0') + ++f; + + if (f != of) + { + s.assign ((f <= l ? f : 0), (f <= l ? l - f : 0)); + return true; + } + } + + return false; +} + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + bool number:: + parse (const ro_string& s, char* str, size_t max) + { + bool r = true; + + ro_string tmp (s.data (), s.size ()); + size_t size = tmp.size (); + + switch (state_) + { + case leading_ws: + { + size = trim_left (tmp); + + if (size != 0) + state_ = sign; + else + break; + // Fall through. + } + case sign: + { + if (tmp[0] == '-') + sign_ = minus; + else if (tmp[0] == '+') + sign_ = plus; + + if (sign_ != none) + tmp.assign (tmp.data () + 1, --size); + + if (size != 0) + state_ = leading_zeros; + else + break; + + // Fall through. + } + case leading_zeros: + { + if (trim_leading_zeros (tmp)) + { + if (size_ == 0) + { + str[0] = '0'; + size_ = 1; + } + + size = tmp.size (); + } + + if (size != 0) + state_ = literal; + else + break; + // Fall through. + } + case literal: + { + // If this chunk is too long then it has to be the last so trim + // trailing ws. + // + if ((max - size_) < size) + { + size = trim_right (tmp); + state_ = trailing_ws; // It either had ws or is too large. + } + + if ((max - size_) >= size) + { + memcpy (str + size_, tmp.data (), size); + size_ += size; + } + else + r = false; + + break; + } + case trailing_ws: + { + if (trim_left (tmp) != 0) + r = false; + } + } + + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/number.hxx b/libxsde/xsde/cxx/parser/validating/number.hxx new file mode 100644 index 0000000..2cd9b62 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/number.hxx @@ -0,0 +1,37 @@ +// file : xsde/cxx/parser/validating/number.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_NUMBER_HXX +#define XSDE_CXX_PARSER_VALIDATING_NUMBER_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + class number + { + protected: + bool + parse (const ro_string&, char* str, size_t max); + + protected: + size_t size_; + enum {leading_ws, sign, leading_zeros, literal, trailing_ws} state_; + enum {none, plus, minus} sign_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_NUMBER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/parser.cxx b/libxsde/xsde/cxx/parser/validating/parser.cxx new file mode 100644 index 0000000..119bf79 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/parser.cxx @@ -0,0 +1,633 @@ +// file : xsde/cxx/parser/validating/parser.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // empty_content + // + +#ifdef XSDE_POLYMORPHIC + bool empty_content:: + _start_element_impl (const ro_string&, + const ro_string&, + const char*) + { + return false; + } +#else + bool empty_content:: + _start_element_impl (const ro_string&, + const ro_string&) + { + return false; + } +#endif + + bool empty_content:: + _end_element_impl (const ro_string&, + const ro_string&) + { + return false; + } + + bool empty_content:: + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + bool empty_content:: + _characters_impl (const ro_string&) + { + return false; + } + + // + // +#ifdef XSDE_POLYMORPHIC + void empty_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (!_start_element_impl (ns, name, type)) + _schema_error (schema_error::unexpected_element); + } +#else + void empty_content:: + _start_element (const ro_string& ns, + const ro_string& name) + { + if (!_start_element_impl (ns, name)) + _schema_error (schema_error::unexpected_element); + } +#endif + + void empty_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + if (!_end_element_impl (ns, name)) + _schema_error (schema_error::unexpected_element); + } + + static const char + xmlns_namespace_[] = "http://www.w3.org/2000/xmlns/"; + + static const char + xsi_namespace_[] = "http://www.w3.org/2001/XMLSchema-instance"; + + static const char + type_[] = "type"; + + static const char + nil_[] = "nil"; + + static const char + schema_location_[] = "schemaLocation"; + + static const char + no_namespace_schema_location_[] = "noNamespaceSchemaLocation"; + + void empty_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _schema_error (schema_error::unexpected_attribute); + } + + void empty_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + _schema_error (schema_error::unexpected_characters); + } + + + // simple_content + // + + void simple_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _schema_error (schema_error::unexpected_attribute); + } + + void simple_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + { + // Mixed content is implemented in the generated code + // by overriding _characters_impl and forwarding to + // _any_characters. + // + + // Scan the string for any non-whitespace characters + // (Structures, section 3.4.4, clause 1.3). + // + ro_string::size_type end = s.size (); + for (ro_string::size_type i = 0; i < end; ++i) + { + char c = s[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + continue; + + _schema_error (schema_error::unexpected_characters); + break; + } + } + } + + void simple_content:: + _pre_impl (context& c) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + assert (parent_ == 0); + + // Set the parent_ pointers in the tied-in implementations. + // + _set_parent_chain (); +#endif + context_ = &c; + + previous_ = c.current_; + + c.current_.parser_ = this; + c.current_.depth_ = 0; + c.current_.any_ = false; + + _pre (); + + if (!c.error_type ()) + _pre_a_validate (); + } + + void simple_content:: + _post_impl () + { + if (!context_->error_type ()) + _post_a_validate (); + + if (!context_->error_type ()) + _post (); + + context_->current_ = previous_; + context_ = 0; + } + + void simple_content:: + _pre_a_validate () + { + } + + void simple_content:: + _post_a_validate () + { + } + + bool simple_content:: + _attribute_impl (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Returns true on error. + // + if (_attribute_impl_phase_one (ns, name, value)) + return true; + + return _attribute_impl_phase_two (ns, name, value); + } + + bool simple_content:: + _attribute_impl_phase_one (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + bool simple_content:: + _attribute_impl_phase_two (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + + // complex_content + // + +#ifdef XSDE_POLYMORPHIC + void complex_content:: + _start_element (const ro_string& ns, + const ro_string& name, + const char* type) + { + if (!_start_element_impl (ns, name, type)) + _schema_error (schema_error::unexpected_element); + } +#else + void complex_content:: + _start_element (const ro_string& ns, + const ro_string& name) + { + if (!_start_element_impl (ns, name)) + _schema_error (schema_error::unexpected_element); + } +#endif + + void complex_content:: + _end_element (const ro_string& ns, + const ro_string& name) + { + if (!_end_element_impl (ns, name)) + _schema_error (schema_error::unexpected_element); + } + + void complex_content:: + _attribute (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Weed out special attributes: xsi:type, xsi:nil, + // xsi:schemaLocation and noNamespaceSchemaLocation. + // See section 3.2.7 in Structures for details. + // + if (ns == xsi_namespace_ && + (name == schema_location_ || + name == no_namespace_schema_location_ || + name == type_ || + name == nil_)) + return; + + // Also some parsers supply us with namespace-prefix + // mapping attributes. + // + if (ns == xmlns_namespace_) + return; + + if (!_attribute_impl (ns, name, value)) + _schema_error (schema_error::unexpected_attribute); + } + + void complex_content:: + _characters (const ro_string& s) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_characters (s); + else +#endif + if (!_characters_impl (s)) + { + // Mixed content is implemented in the generated code + // by overriding _characters_impl and forwarding to + // _any_characters. + // + + // Scan the string for any non-whitespace characters + // (Structures, section 3.4.4, clause 1.3). + // + ro_string::size_type end = s.size (); + for (ro_string::size_type i = 0; i < end; ++i) + { + char c = s[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + continue; + + _schema_error (schema_error::unexpected_characters); + break; + } + } + } + + void complex_content:: + _pre_impl (context& c) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + assert (parent_ == 0); + + // Set the parent_ pointers in the tied-in implementations. + // + _set_parent_chain (); +#endif + if (depth_++ == 0) + context_ = &c; + +#ifdef XSDE_EXCEPTIONS + parser_stack_.push (c.current_); +#else + if (parser_stack_.push (c.current_)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + c.current_.parser_ = this; + c.current_.depth_ = 0; + c.current_.any_ = false; + + _pre (); + + if (!c.error_type ()) + _pre_a_validate (); + + if (!c.error_type ()) + _pre_e_validate (); + } + + void complex_content:: + _post_impl () + { + if (!context_->error_type ()) + _post_e_validate (); + + if (!context_->error_type ()) + _post_a_validate (); + + if (!context_->error_type ()) + _post (); + + context_->current_ = parser_stack_.top (); + parser_stack_.pop (); + + if (--depth_ == 0) + context_ = 0; + } + + void complex_content:: + _pre_e_validate () + { + } + + void complex_content:: + _post_e_validate () + { + } + + void complex_content:: + _pre_a_validate () + { + } + + void complex_content:: + _post_a_validate () + { + } + + bool complex_content:: + _attribute_impl (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + // Returns true on error. + // + if (_attribute_impl_phase_one (ns, name, value)) + return true; + + return _attribute_impl_phase_two (ns, name, value); + } + + bool complex_content:: + _attribute_impl_phase_one (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + bool complex_content:: + _attribute_impl_phase_two (const ro_string&, + const ro_string&, + const ro_string&) + { + return false; + } + + void complex_content:: + _reset () + { + empty_content::_reset (); + + depth_ = 0; + parser_stack_.clear (); + } + + // list_base + // + + // Find first non-space character. + // + static ro_string::size_type + find_ns (const char* s, + ro_string::size_type size, + ro_string::size_type pos) + { + while (pos < size && + (s[pos] == 0x20 || s[pos] == 0x0A || + s[pos] == 0x0D || s[pos] == 0x09)) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + + // Find first space character. + // + static ro_string::size_type + find_s (const char* s, + ro_string::size_type size, + ro_string::size_type pos) + { + while (pos < size && + s[pos] != 0x20 && s[pos] != 0x0A && + s[pos] != 0x0D && s[pos] != 0x09) + ++pos; + + return pos < size ? pos : ro_string::npos; + } + + // Relevant XML Schema Part 2: Datatypes sections: 4.2.1.2, 4.3.6. + // + + void list_base:: + _pre_impl (context& c) + { + simple_content::_pre_impl (c); + + if (!c.error_type ()) + { +#ifdef XSDE_EXCEPTIONS + buf_.assign ("", 0); +#else + if (buf_.assign ("", 0)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + } + + void list_base:: + _characters (const ro_string& s) + { + typedef ro_string::size_type size_type; + + const char* data = s.data (); + size_type size = s.size (); + + // Handle the previous chunk if we start with a ws. + // + if (!buf_.empty () && + (data[0] == 0x20 || data[0] == 0x0A || + data[0] == 0x0D || data[0] == 0x09)) + { + ro_string tmp (buf_); // Private copy ctor. + _xsde_parse_item (tmp); + buf_.assign ("", 0); // Can't fail. + } + + context& ctx = _context (); + + // Traverse the data while logically collapsing spaces. + // + for (size_type i = find_ns (data, size, 0); i != ro_string::npos;) + { + size_type j = find_s (data, size, i); + + if (j != ro_string::npos) + { + if (buf_.empty ()) + { + ro_string tmp (data + i, j - i); // Private copy ctor. + _xsde_parse_item (tmp); + } + else + { + // Assemble the first item in str from buf_ and s. + // + string str; + str.swap (buf_); + +#ifdef XSDE_EXCEPTIONS + str.append (data + i, j - i); +#else + if (str.append (data + i, j - i)) + { + _sys_error (sys_error::no_memory); + break; + } +#endif + ro_string tmp (str); // Private copy ctor. + _xsde_parse_item (tmp); + } + + if (ctx.error_type ()) + break; + + i = find_ns (data, size, j); + } + else + { + // Last fragment, append it to buf_. + // +#ifdef XSDE_EXCEPTIONS + buf_.append (data + i, size - i); +#else + if (buf_.append (data + i, size - i)) + _sys_error (sys_error::no_memory); +#endif + break; + } + } + } + + void list_base:: + _xsde_parse_item (const ro_string&) + { + } + + void list_base:: + _post_impl () + { + // Handle the last item. + // + if (!buf_.empty ()) + { + ro_string tmp (buf_); // Private copy ctor. + _xsde_parse_item (tmp); + } + + simple_content::_post_impl (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/parser.hxx b/libxsde/xsde/cxx/parser/validating/parser.hxx new file mode 100644 index 0000000..246b7c9 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/parser.hxx @@ -0,0 +1,304 @@ +// file : xsde/cxx/parser/validating/parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_PARSER_HXX +#define XSDE_CXX_PARSER_VALIDATING_PARSER_HXX + +#include + +#include // size_t + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // + // + struct empty_content: parser_base + { + +#ifdef XSDE_POLYMORPHIC + virtual bool + _start_element_impl (const ro_string&, + const ro_string&, + const char*); +#else + virtual bool + _start_element_impl (const ro_string&, + const ro_string&); +#endif + + virtual bool + _end_element_impl (const ro_string&, + const ro_string&); + + virtual bool + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&); + + virtual bool + _characters_impl (const ro_string&); + + + // + // +#ifdef XSDE_POLYMORPHIC + virtual void + _start_element (const ro_string&, + const ro_string&, + const char*); +#else + virtual void + _start_element (const ro_string&, + const ro_string&); +#endif + + virtual void + _end_element (const ro_string&, + const ro_string&); + + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + empty_content (); + empty_content (empty_content* impl, void*); +#endif + }; + + + // + // + struct simple_content: empty_content + { + // + // + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + // + // + virtual bool + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&); + + // + // + virtual void + _pre_impl (context&); + + virtual void + _post_impl (); + + + // Implementation callbacks. + // + virtual void + _pre_a_validate (); + + virtual void + _post_a_validate (); + + + // Attribute validation: during phase one we are searching for + // matching attributes (Structures, section 3.4.4, clause 2.1). + // During phase two we are searching for attribute wildcards + // (section 3.4.4, clause 2.2). Both phases run across + // inheritance hierarchy from derived to base for extension + // only. Both functions return true if the match was found and + // validation has been performed. + // + virtual bool + _attribute_impl_phase_one (const ro_string& ns, + const ro_string& name, + const ro_string& value); + + virtual bool + _attribute_impl_phase_two (const ro_string& ns, + const ro_string& name, + const ro_string& value); + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + simple_content (); + simple_content (simple_content* impl, void*); +#endif + }; + + + // + // + struct complex_content: empty_content + { +#ifdef XSDE_POLYMORPHIC + virtual void + _start_element (const ro_string&, + const ro_string&, + const char*); +#else + virtual void + _start_element (const ro_string&, + const ro_string&); +#endif + + virtual void + _end_element (const ro_string&, + const ro_string&); + + virtual void + _attribute (const ro_string&, + const ro_string&, + const ro_string&); + + virtual void + _characters (const ro_string&); + + // + // + virtual bool + _attribute_impl (const ro_string&, + const ro_string&, + const ro_string&); + + // + // + virtual void + _pre_impl (context&); + + virtual void + _post_impl (); + + + // Implementation callbacks. + // + virtual void + _pre_e_validate (); + + virtual void + _post_e_validate (); + + virtual void + _pre_a_validate (); + + virtual void + _post_a_validate (); + + + // Attribute validation: during phase one we are searching for + // matching attributes (Structures, section 3.4.4, clause 2.1). + // During phase two we are searching for attribute wildcards + // (section 3.4.4, clause 2.2). Both phases run across + // inheritance hierarchy from derived to base for extension + // only. Both functions return true if the match was found and + // validation has been performed. + // + virtual bool + _attribute_impl_phase_one (const ro_string& ns, + const ro_string& name, + const ro_string& value); + + virtual bool + _attribute_impl_phase_two (const ro_string& ns, + const ro_string& name, + const ro_string& value); + + // + // + virtual void + _reset (); + + // + // + complex_content (); + +#ifdef XSDE_REUSE_STYLE_TIEIN + complex_content (complex_content* impl, void*); +#endif + protected: + size_t depth_; + parser_stack parser_stack_; + }; + + // Validation state stack for the 'all' particle. + // + struct all_stack + { + all_stack (size_t n, unsigned char* first); + + stack::error + push (); + + void + pop (); + + unsigned char* + top (); + + void + clear (); + + private: + stack stack_; + }; + + // Base for xsd:list. + // + struct list_base: simple_content + { + virtual void + _xsde_parse_item (const ro_string&); + + virtual void + _pre_impl (context&); + + virtual void + _characters (const ro_string&); + + virtual void + _post_impl (); + + // + // +#ifdef XSDE_REUSE_STYLE_TIEIN + list_base (); + list_base (list_base* impl, void*); +#endif + protected: + string buf_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_VALIDATING_PARSER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/parser.ixx b/libxsde/xsde/cxx/parser/validating/parser.ixx new file mode 100644 index 0000000..4a0e176 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/parser.ixx @@ -0,0 +1,121 @@ +// file : xsde/cxx/parser/validating/parser.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + + // empty_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline empty_content:: + empty_content () + { + } + + inline empty_content:: + empty_content (empty_content* impl, void*) + : parser_base (impl, 0) + { + } +#endif + + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline simple_content:: + simple_content () + { + } + + inline simple_content:: + simple_content (simple_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + + // complex_content + // + inline complex_content:: + complex_content () + : depth_ (0), parser_stack_ (previous_) + { + } + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline complex_content:: + complex_content (complex_content* impl, void*) + : empty_content (impl, 0), depth_ (0), parser_stack_ (previous_) + { + } +#endif + + // all_stack + // + + inline all_stack:: + all_stack (size_t n, unsigned char* first) + : stack_ (n, first) + { + } + + inline stack::error all_stack:: + push () + { + if (stack::error e = stack_.push ()) + return e; + + unsigned char* p = static_cast (stack_.top ()); + + for (size_t i = 0; i < stack_.element_size (); ++i) + p[i] = 0; + + return stack::error_none; + } + + inline void all_stack:: + pop () + { + stack_.pop (); + } + + inline unsigned char* all_stack:: + top () + { + return static_cast (stack_.top ()); + } + + inline void all_stack:: + clear () + { + stack_.clear (); + } + + + // list_base + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline list_base:: + list_base () + { + } + + inline list_base:: + list_base (list_base* impl, void*) + : simple_content (impl, 0) + { + } +#endif + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/validating/positive-integer.cxx b/libxsde/xsde/cxx/parser/validating/positive-integer.cxx new file mode 100644 index 0000000..2a6595a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/positive-integer.cxx @@ -0,0 +1,64 @@ +// file : xsde/cxx/parser/validating/positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void positive_integer_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void positive_integer_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 21)) + _schema_error (schema_error::invalid_positive_integer_value); + } + + void positive_integer_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + value_ = strtoul (str_, &p, 10); + + if (*p != '\0' || get_errno () != 0 || value_ == 0) + _schema_error (schema_error::invalid_positive_integer_value); + } + else + _schema_error (schema_error::invalid_positive_integer_value); + } + + unsigned long positive_integer_pimpl:: + post_positive_integer () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/positive-integer.hxx b/libxsde/xsde/cxx/parser/validating/positive-integer.hxx new file mode 100644 index 0000000..59b6b27 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/positive-integer.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_POSITIVE_INTEGER_HXX +#define XSDE_CXX_PARSER_VALIDATING_POSITIVE_INTEGER_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Arbitrary-length positive integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct positive_integer_pimpl: virtual positive_integer_pskel, number +#else + struct positive_integer_pimpl: positive_integer_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned long + post_positive_integer (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long, assuming we are on a 64 bit machine. + // + char str_[22]; + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/parser/validating/qname-stl.cxx b/libxsde/xsde/cxx/parser/validating/qname-stl.cxx new file mode 100644 index 0000000..a65e367 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/qname-stl.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/parser/validating/qname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void qname_pimpl:: + _pre () + { + str_.erase (); + } + + void qname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + void qname_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + ro_string::size_type pos = tmp.find (':'); + + const char* s = tmp.data (); + + if (pos != ro_string::npos) + { + if (xml::valid_ncname (s, pos) && + xml::valid_ncname (s + pos + 1, size - pos - 1)) + { + prefix_.assign (s, pos); + name_.assign (s + pos + 1, size - pos - 1); + } + else + _schema_error (schema_error::invalid_qname_value); + } + else + { + if (xml::valid_ncname (s, size)) + { + prefix_.erase (); + str_.resize (size); + name_.swap (str_); + } + else + _schema_error (schema_error::invalid_qname_value); + } + } + + qname qname_pimpl:: + post_qname () + { + return qname (prefix_, name_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/qname-stl.hxx b/libxsde/xsde/cxx/parser/validating/qname-stl.hxx new file mode 100644 index 0000000..c766c55 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/qname-stl.hxx @@ -0,0 +1,49 @@ +// file : xsde/cxx/parser/validating/qname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_QNAME_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_QNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_pimpl: virtual qname_pskel +#else + struct qname_pimpl: qname_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual qname + post_qname (); + + protected: + std::string str_; + std::string name_; + std::string prefix_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_QNAME_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/qname.cxx b/libxsde/xsde/cxx/parser/validating/qname.cxx new file mode 100644 index 0000000..265179c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/qname.cxx @@ -0,0 +1,180 @@ +// file : xsde/cxx/parser/validating/qname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + qname_pimpl:: + ~qname_pimpl () + { + if (!base_) + delete qn_; + } + + void qname_pimpl:: + _reset () + { + qname_pskel::_reset (); + + if (!base_) + { + delete qn_; + qn_ = 0; + } + } + + qname_pimpl:: + qname_pimpl (bool base) + : base_ (base), qn_ (0) + { + } + + void qname_pimpl:: + pre_impl (qname* qn) + { + qn_ = qn; + } + + void qname_pimpl:: + _pre () + { + if (qn_ == 0) + { + qn_ = new qname (); + +#ifndef XSDE_EXCEPTIONS + if (qn_ == 0) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void qname_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void qname_pimpl:: + _post () + { + ro_string tmp (str_.data (), str_.size ()); + ro_string::size_type size = trim_right (tmp); + ro_string::size_type pos = tmp.find (':'); + + string name; + string prefix; + + const char* s = tmp.data (); + + if (pos != ro_string::npos) + { + if (xml::valid_ncname (s, pos) && + xml::valid_ncname (s + pos + 1, size - pos - 1)) + { +#ifdef XSDE_EXCEPTIONS + prefix.assign (s, pos); + name.assign (s + pos + 1, size - pos - 1); +#else + if (prefix.assign (s, pos) || + name.assign (s + pos + 1, size - pos - 1)) + { + _sys_error (sys_error::no_memory); + return; + } +#endif + } + else + { + _schema_error (schema_error::invalid_qname_value); + return; + } + } + else + { + if (xml::valid_ncname (s, size)) + { +#ifdef XSDE_EXCEPTIONS + prefix.assign ("", 0); + str_.truncate (size); + name.swap (str_); +#else + if (prefix.assign ("", 0)) + { + _sys_error (sys_error::no_memory); + return; + } + else + { + str_.truncate (size); + name.swap (str_); + } +#endif + } + else + { + _schema_error (schema_error::invalid_qname_value); + return; + } + } + + qn_->prefix (prefix.detach ()); + qn_->name (name.detach ()); + } + + qname* qname_pimpl:: + post_qname () + { + qname* r = qn_; + qn_ = 0; + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/qname.hxx b/libxsde/xsde/cxx/parser/validating/qname.hxx new file mode 100644 index 0000000..2201699 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/qname.hxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/parser/validating/qname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_QNAME_HXX +#define XSDE_CXX_PARSER_VALIDATING_QNAME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_pimpl: virtual qname_pskel +#else + struct qname_pimpl: qname_pskel +#endif + { + ~qname_pimpl (); + qname_pimpl (bool base = false); + + void + pre_impl (qname*); + + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual qname* + post_qname (); + + virtual void + _reset (); + + protected: + bool base_; + string str_; + qname* qn_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_QNAME_HXX diff --git a/libxsde/xsde/cxx/parser/validating/short.cxx b/libxsde/xsde/cxx/parser/validating/short.cxx new file mode 100644 index 0000000..199465b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/short.cxx @@ -0,0 +1,70 @@ +// file : xsde/cxx/parser/validating/short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void short_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void short_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 6)) + _schema_error (schema_error::invalid_short_value); + } + + void short_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + // No need to check errno since our string representation + // can never overflow an unsigned long. + // + char* p; + unsigned long ul = strtoul (str_, &p, 10); + + bool neg = (sign_ == minus); + + if (*p != '\0' || (neg && ul > 32768) || (!neg && ul > 32767)) + _schema_error (schema_error::invalid_short_value); + + value_ = neg + ? static_cast (-static_cast (ul)) + : static_cast (ul); + } + else + _schema_error (schema_error::invalid_short_value); + } + + short short_pimpl:: + post_short () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/short.hxx b/libxsde/xsde/cxx/parser/validating/short.hxx new file mode 100644 index 0000000..1bbe7bd --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/short.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_SHORT_HXX +#define XSDE_CXX_PARSER_VALIDATING_SHORT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 16-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct short_pimpl: virtual short_pskel, number +#else + struct short_pimpl: short_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual short + post_short (); + + protected: + // We only need strlen("032768") + 1 characters to hold all valid + // and trimmed string representations of short. + // + char str_[7]; + short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_SHORT_HXX diff --git a/libxsde/xsde/cxx/parser/validating/string-stl.cxx b/libxsde/xsde/cxx/parser/validating/string-stl.cxx new file mode 100644 index 0000000..a0394db --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/string-stl.cxx @@ -0,0 +1,38 @@ +// file : xsde/cxx/parser/validating/string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void string_pimpl:: + _pre () + { + str_.erase (); + } + + void string_pimpl:: + _characters (const ro_string& s) + { + str_ += s; + } + + std::string string_pimpl:: + post_string () + { + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/string-stl.hxx b/libxsde/xsde/cxx/parser/validating/string-stl.hxx new file mode 100644 index 0000000..a6220d1 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/string-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_STRING_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_pimpl: virtual string_pskel +#else + struct string_pimpl: string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_string (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/string.cxx b/libxsde/xsde/cxx/parser/validating/string.cxx new file mode 100644 index 0000000..a4319fb --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/string.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/parser/validating/string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void string_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void string_pimpl:: + _characters (const ro_string& s) + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + + char* string_pimpl:: + post_string () + { + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/string.hxx b/libxsde/xsde/cxx/parser/validating/string.hxx new file mode 100644 index 0000000..2e2bcd5 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/string.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_STRING_HXX +#define XSDE_CXX_PARSER_VALIDATING_STRING_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_pimpl: virtual string_pskel +#else + struct string_pimpl: string_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_string (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_STRING_HXX diff --git a/libxsde/xsde/cxx/parser/validating/time-zone.cxx b/libxsde/xsde/cxx/parser/validating/time-zone.cxx new file mode 100644 index 0000000..fb25f56 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/time-zone.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/parser/validating/time-zone.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + namespace bits + { + bool + parse_time_zone (const char* s, size_t n, short& h, short& m) + { + // time_zone := Z|(+|-)HH:MM + // + if (n == 0) + { + return false; + } + else if (s[0] == 'Z') + { + if (n != 1) + return false; + + h = 0; + m = 0; + } + else + { + if (n != 6 || (s[0] != '-' && s[0] != '+') || s[3] != ':') + return false; + + // Parse hours. + // + char d1 = s[1]; + char d2 = s[2]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + return false; + + h = 10 * (d1 - '0') + (d2 - '0'); + + if (h > 14) + return false; + + // Parse minutes. + // + d1 = s[4]; + d2 = s[5]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + return false; + + m = 10 * (d1 - '0') + (d2 - '0'); + + if (m > 59 || (h == 14 && m != 0)) + return false; + + if (s[0] == '-') + { + h = -h; + m = -m; + } + } + + return true; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/time-zone.hxx b/libxsde/xsde/cxx/parser/validating/time-zone.hxx new file mode 100644 index 0000000..93a8205 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/time-zone.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/parser/validating/time-zone.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_TIME_ZONE_HXX +#define XSDE_CXX_PARSER_VALIDATING_TIME_ZONE_HXX + +#include // size_t + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + namespace bits + { + bool + parse_time_zone (const char* s, + size_t size, + short& hours, + short& minutes); + } + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_TIME_ZONE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/time.cxx b/libxsde/xsde/cxx/parser/validating/time.cxx new file mode 100644 index 0000000..eaddc58 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/time.cxx @@ -0,0 +1,181 @@ +// file : xsde/cxx/parser/validating/time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtod + +#include +#include + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void time_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void time_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + void time_pimpl:: + _post () + { + char* s = str_.data (); + ro_string tmp (s, str_.size ()); + ro_string::size_type n = trim_right (tmp); + + // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] + // + + if (n < 8 || s[2] != ':' || s[5] != ':') + { + _schema_error (schema_error::invalid_time_value); + return; + } + + // hours + // + char d1 = s[0]; + char d2 = s[1]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_time_value); + return; + } + + hours_ = 10 * (d1 - '0') + (d2 - '0'); + + if (hours_ > 24) + { + _schema_error (schema_error::invalid_time_value); + return; + } + + // minutes + // + d1 = s[3]; + d2 = s[4]; + + if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9') + { + _schema_error (schema_error::invalid_time_value); + return; + } + + minutes_ = 10 * (d1 - '0') + (d2 - '0'); + + if (minutes_ > 59) + { + _schema_error (schema_error::invalid_time_value); + return; + } + + // Find the end of the seconds fragment. + // + ro_string::size_type pos = 8; + for (; pos < n; ++pos) + { + char c = s[pos]; + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + // At least one digit should follow the fraction point. + // + if ((pos - 6) == 3) + { + _schema_error (schema_error::invalid_time_value); + return; + } + + // Parse the time zone first so that we can truncate and + // reuse the string. + // + if (pos < n) + { + if (!bits::parse_time_zone (s + pos, n - pos, zh_, zm_)) + { + _schema_error (schema_error::invalid_time_value); + return; + } + + z_ = true; + } + else + z_ = false; + + // seconds + // + str_.truncate (pos); + + char* p; + set_errno (0); + seconds_ = strtod (s + 6, &p); + + if (*p != '\0' || get_errno () != 0 || seconds_ >= 60.0) + { + _schema_error (schema_error::invalid_time_value); + return; + } + + if (hours_ == 24 && (minutes_ != 0 || seconds_ != 0.0)) + { + _schema_error (schema_error::invalid_time_value); + return; + } + } + + time time_pimpl:: + post_time () + { + return z_ + ? time (hours_, minutes_, seconds_, zh_, zm_) + : time (hours_, minutes_, seconds_); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/time.hxx b/libxsde/xsde/cxx/parser/validating/time.hxx new file mode 100644 index 0000000..3f68b4c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/time.hxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/parser/validating/time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_TIME_HXX +#define XSDE_CXX_PARSER_VALIDATING_TIME_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct time_pimpl: virtual time_pskel +#else + struct time_pimpl: time_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual time + post_time (); + + protected: + string str_; + unsigned short hours_, minutes_; + double seconds_; + bool z_; + short zh_, zm_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_TIME_HXX diff --git a/libxsde/xsde/cxx/parser/validating/token-stl.cxx b/libxsde/xsde/cxx/parser/validating/token-stl.cxx new file mode 100644 index 0000000..e6ac6ea --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/token-stl.cxx @@ -0,0 +1,73 @@ +// file : xsde/cxx/parser/validating/token-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void token_pimpl:: + _pre () + { + str_.erase (); + } + + void token_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string token_pimpl:: + post_token () + { + std::string::size_type size = str_.size (); + std::string::size_type j = 0; + + bool subs = false; + + for (std::string::size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + { + subs = false; + str_[j++] = 0x20; + } + + str_[j++] = c; + } + } + + str_.resize (j); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/token-stl.hxx b/libxsde/xsde/cxx/parser/validating/token-stl.hxx new file mode 100644 index 0000000..29e4f9a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/token-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/token-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_TOKEN_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_TOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_pimpl: virtual token_pskel +#else + struct token_pimpl: token_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_token (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_TOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/token.cxx b/libxsde/xsde/cxx/parser/validating/token.cxx new file mode 100644 index 0000000..5e12a60 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/token.cxx @@ -0,0 +1,94 @@ +// file : xsde/cxx/parser/validating/token.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void token_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void token_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* token_pimpl:: + post_token () + { + typedef string::size_type size_type; + + size_type size = str_.size (); + size_type j = 0; + + bool subs = false; + + for (size_type i = 0; i < size; ++i) + { + char c = str_[i]; + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + { + subs = true; + } + else + { + if (subs) + { + subs = false; + str_[j++] = 0x20; + } + + str_[j++] = c; + } + } + + str_.truncate (j); + + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/token.hxx b/libxsde/xsde/cxx/parser/validating/token.hxx new file mode 100644 index 0000000..230466b --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/token.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/token.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_TOKEN_HXX +#define XSDE_CXX_PARSER_VALIDATING_TOKEN_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_pimpl: virtual token_pskel +#else + struct token_pimpl: token_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_token (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_TOKEN_HXX diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-byte.cxx b/libxsde/xsde/cxx/parser/validating/unsigned-byte.cxx new file mode 100644 index 0000000..ace72f8 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-byte.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/parser/validating/unsigned-byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void unsigned_byte_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_byte_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 4)) + _schema_error (schema_error::invalid_unsigned_byte_value); + } + + void unsigned_byte_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + // No need to check errno since our string representation + // can never overflow an unsigned long. + // + char* p; + unsigned long ul = strtoul (str_, &p, 10); + + if (*p != '\0' || ul > 255) + _schema_error (schema_error::invalid_unsigned_byte_value); + + value_ = static_cast (ul); + } + else + _schema_error (schema_error::invalid_unsigned_byte_value); + } + + unsigned char unsigned_byte_pimpl:: + post_unsigned_byte () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-byte.hxx b/libxsde/xsde/cxx/parser/validating/unsigned-byte.hxx new file mode 100644 index 0000000..bec1e6d --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-byte.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/unsigned-byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_UNSIGNED_BYTE_HXX +#define XSDE_CXX_PARSER_VALIDATING_UNSIGNED_BYTE_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 8-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_byte_pimpl: virtual unsigned_byte_pskel, number +#else + struct unsigned_byte_pimpl: unsigned_byte_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned char + post_unsigned_byte (); + + protected: + // We only need strlen("0256") + 1 characters to hold all valid + // and trimmed string representations of unsigned byte. + // + char str_[5]; + unsigned char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_UNSIGNED_BYTE_HXX diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-int.cxx b/libxsde/xsde/cxx/parser/validating/unsigned-int.cxx new file mode 100644 index 0000000..fbb18aa --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-int.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/parser/validating/unsigned-int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void unsigned_int_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_int_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 11)) + _schema_error (schema_error::invalid_unsigned_int_value); + } + + void unsigned_int_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + unsigned long ul = strtoul (str_, &p, 10); + + if (*p != '\0' || get_errno () != 0 || ul > 4294967295UL) + _schema_error (schema_error::invalid_unsigned_int_value); + + value_ = static_cast (ul); + } + else + _schema_error (schema_error::invalid_unsigned_int_value); + } + + unsigned int unsigned_int_pimpl:: + post_unsigned_int () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-int.hxx b/libxsde/xsde/cxx/parser/validating/unsigned-int.hxx new file mode 100644 index 0000000..2811557 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-int.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/unsigned-int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_UNSIGNED_INT_HXX +#define XSDE_CXX_PARSER_VALIDATING_UNSIGNED_INT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 32-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_int_pimpl: virtual unsigned_int_pskel, number +#else + struct unsigned_int_pimpl: unsigned_int_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned int + post_unsigned_int (); + + protected: + // We only need strlen("04294967295") + 1 characters to hold all + // valid and trimmed string representations of unsigned int. + // + char str_[12]; + unsigned int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_UNSIGNED_INT_HXX diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-long-long.cxx b/libxsde/xsde/cxx/parser/validating/unsigned-long-long.cxx new file mode 100644 index 0000000..5464028 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-long-long.cxx @@ -0,0 +1,64 @@ +// file : xsde/cxx/parser/validating/unsigned-long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoull + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void unsigned_long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_long_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 21)) + _schema_error (schema_error::invalid_unsigned_long_value); + } + + void unsigned_long_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + value_ = strtoull (str_, &p, 10); + + if (*p != '\0' || get_errno () != 0) + _schema_error (schema_error::invalid_unsigned_long_value); + } + else + _schema_error (schema_error::invalid_unsigned_long_value); + } + + unsigned long long unsigned_long_pimpl:: + post_unsigned_long () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-long-long.hxx b/libxsde/xsde/cxx/parser/validating/unsigned-long-long.hxx new file mode 100644 index 0000000..b0aa4cb --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-long-long.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/unsigned-long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_LONG_HXX +#define XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 64-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_pimpl: virtual unsigned_long_pskel, number +#else + struct unsigned_long_pimpl: unsigned_long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned long long + post_unsigned_long (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long long. + // + char str_[22]; + unsigned long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-long.cxx b/libxsde/xsde/cxx/parser/validating/unsigned-long.cxx new file mode 100644 index 0000000..eababbf --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-long.cxx @@ -0,0 +1,64 @@ +// file : xsde/cxx/parser/validating/unsigned-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void unsigned_long_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_long_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 21)) + _schema_error (schema_error::invalid_unsigned_long_value); + } + + void unsigned_long_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + char* p; + set_errno (0); + value_ = strtoul (str_, &p, 10); + + if (*p != '\0' || get_errno () != 0) + _schema_error (schema_error::invalid_unsigned_long_value); + } + else + _schema_error (schema_error::invalid_unsigned_long_value); + } + + unsigned long unsigned_long_pimpl:: + post_unsigned_long () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-long.hxx b/libxsde/xsde/cxx/parser/validating/unsigned-long.hxx new file mode 100644 index 0000000..6b2ac19 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-long.hxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/unsigned-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_HXX +#define XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_pimpl: virtual unsigned_long_pskel, number +#else + struct unsigned_long_pimpl: unsigned_long_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned long + post_unsigned_long (); + + protected: + // We only need strlen("018446744073709551615") + 1 characters to + // hold all valid and trimmed string representations of unsigned + // long long. + // + char str_[22]; + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_UNSIGNED_LONG_HXX diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-short.cxx b/libxsde/xsde/cxx/parser/validating/unsigned-short.cxx new file mode 100644 index 0000000..b40b51c --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-short.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/parser/validating/unsigned-short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strtoul + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void unsigned_short_pimpl:: + _pre () + { + size_ = 0; + sign_ = none; + state_ = leading_ws; + } + + void unsigned_short_pimpl:: + _characters (const ro_string& s) + { + if (!parse (s, str_, 6)) + _schema_error (schema_error::invalid_unsigned_short_value); + } + + void unsigned_short_pimpl:: + _post () + { + ro_string tmp (str_, size_); + size_t size = trim_right (tmp); + + if (size != 0 && sign_ != minus && tmp[0] != '-' && tmp[0] != '+') + { + str_[size] = '\0'; + + // No need to check errno since our string representation + // can never overflow an unsigned long. + // + char* p; + unsigned long ul = strtoul (str_, &p, 10); + + if (*p != '\0' || ul > 65535) + _schema_error (schema_error::invalid_unsigned_short_value); + + value_ = static_cast (ul); + } + else + _schema_error (schema_error::invalid_unsigned_short_value); + } + + unsigned short unsigned_short_pimpl:: + post_unsigned_short () + { + return value_; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/unsigned-short.hxx b/libxsde/xsde/cxx/parser/validating/unsigned-short.hxx new file mode 100644 index 0000000..be7228a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/unsigned-short.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/parser/validating/unsigned-short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_UNSIGNED_SHORT_HXX +#define XSDE_CXX_PARSER_VALIDATING_UNSIGNED_SHORT_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // 16-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_short_pimpl: virtual unsigned_short_pskel, number +#else + struct unsigned_short_pimpl: unsigned_short_pskel, number +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual void + _post (); + + virtual unsigned short + post_unsigned_short (); + + protected: + // We only need strlen("065535") + 1 characters to hold all valid + // and trimmed string representations of unsigned short. + // + char str_[7]; + unsigned short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_UNSIGNED_SHORT_HXX diff --git a/libxsde/xsde/cxx/parser/validating/uri-stl.cxx b/libxsde/xsde/cxx/parser/validating/uri-stl.cxx new file mode 100644 index 0000000..c2947dd --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/uri-stl.cxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/parser/validating/uri-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void uri_pimpl:: + _pre () + { + str_.erase (); + } + + void uri_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + str_ += tmp; + } + else + str_ += s; + } + + std::string uri_pimpl:: + post_uri () + { + // According to Datatypes 3.2.17 and RFC2396 pretty much anything + // can be a URI and conforming processors do not need to figure + // out and verify particular URI schemes. + // + ro_string tmp (str_); + str_.resize (trim_right (tmp)); + + std::string r; + r.swap (str_); + return r; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/uri-stl.hxx b/libxsde/xsde/cxx/parser/validating/uri-stl.hxx new file mode 100644 index 0000000..b964aff --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/uri-stl.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/uri-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_URI_STL_HXX +#define XSDE_CXX_PARSER_VALIDATING_URI_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_pimpl: virtual uri_pskel +#else + struct uri_pimpl: uri_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual std::string + post_uri (); + + protected: + std::string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_URI_STL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/uri.cxx b/libxsde/xsde/cxx/parser/validating/uri.cxx new file mode 100644 index 0000000..37acfea --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/uri.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/parser/validating/uri.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + void uri_pimpl:: + _pre () + { +#ifdef XSDE_EXCEPTIONS + str_.assign ("", 0); +#else + if (str_.assign ("", 0)) + _sys_error (sys_error::no_memory); +#endif + } + + void uri_pimpl:: + _characters (const ro_string& s) + { + if (str_.size () == 0) + { + ro_string tmp (s.data (), s.size ()); + + if (trim_left (tmp) != 0) + { +#ifdef XSDE_EXCEPTIONS + str_.append (tmp.data (), tmp.size ()); +#else + if (str_.append (tmp.data (), tmp.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + else + { +#ifdef XSDE_EXCEPTIONS + str_.append (s.data (), s.size ()); +#else + if (str_.append (s.data (), s.size ())) + _sys_error (sys_error::no_memory); +#endif + } + } + + char* uri_pimpl:: + post_uri () + { + // According to Datatypes 3.2.17 and RFC2396 pretty much anything + // can be a URI and conforming processors do not need to figure + // out and verify particular URI schemes. + // + ro_string tmp (str_); + str_.truncate (trim_right (tmp)); + return str_.detach (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/validating/uri.hxx b/libxsde/xsde/cxx/parser/validating/uri.hxx new file mode 100644 index 0000000..2e19aef --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/uri.hxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/parser/validating/uri.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_URI_HXX +#define XSDE_CXX_PARSER_VALIDATING_URI_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_pimpl: virtual uri_pskel +#else + struct uri_pimpl: uri_pskel +#endif + { + virtual void + _pre (); + + virtual void + _characters (const ro_string&); + + virtual char* + post_uri (); + + protected: + string str_; + }; + } + } + } +} + +#endif // XSDE_CXX_PARSER_VALIDATING_URI_HXX diff --git a/libxsde/xsde/cxx/parser/validating/xml-schema-pimpl.hxx b/libxsde/xsde/cxx/parser/validating/xml-schema-pimpl.hxx new file mode 100644 index 0000000..7552521 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/xml-schema-pimpl.hxx @@ -0,0 +1,82 @@ +// file : xsde/cxx/parser/validating/xml-schema-pimpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PIMPL_HXX +#define XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PIMPL_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_LONGLONG +# include +# include +#else +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_STL +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PIMPL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.cxx b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.cxx new file mode 100644 index 0000000..894f674 --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.cxx @@ -0,0 +1,617 @@ +// file : xsde/cxx/parser/validating/xml-schema-pskel.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // any_type + // +#ifdef XSDE_POLYMORPHIC + bool any_type_pskel:: + _start_element_impl (const ro_string& ns, + const ro_string& name, + const char* type) + { + context& ctx = _context (); + ctx.current_.any_ = true; + ctx.current_.depth_++; + + _start_any_element (ns, name, type); + return true; + } +#else + bool any_type_pskel:: + _start_element_impl (const ro_string& ns, const ro_string& name) + { + context& ctx = _context (); + ctx.current_.any_ = true; + ctx.current_.depth_++; + + _start_any_element (ns, name); + return true; + } +#endif + + bool any_type_pskel:: + _end_element_impl (const ro_string& ns, const ro_string& name) + { + _end_any_element (ns, name); + return true; + } + + bool any_type_pskel:: + _attribute_impl_phase_two (const ro_string& ns, + const ro_string& name, + const ro_string& value) + { + _any_attribute (ns, name, value); + return true; + } + + bool any_type_pskel:: + _characters_impl (const ro_string& s) + { + _any_characters (s); + return true; + } + + void any_type_pskel:: + post_any_type () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_type_impl_) + any_type_impl_->post_any_type (); +#endif + } + + // any_simple_type + // + bool any_simple_type_pskel:: + _characters_impl (const ro_string& s) + { + _any_characters (s); + return true; + } + + void any_simple_type_pskel:: + post_any_simple_type () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_simple_type_impl_) + any_simple_type_impl_->post_any_simple_type (); +#endif + } + + // static/dynamic_type function implementations. + // +#ifdef XSDE_POLYMORPHIC + const char* any_type_pskel:: + _static_type () + { + return "anyType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_type_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* any_simple_type_pskel:: + _static_type () + { + return "anySimpleType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_simple_type_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* boolean_pskel:: + _static_type () + { + return "boolean http://www.w3.org/2001/XMLSchema"; + } + + const char* boolean_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* byte_pskel:: + _static_type () + { + return "byte http://www.w3.org/2001/XMLSchema"; + } + + const char* byte_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_byte_pskel:: + _static_type () + { + return "unsignedByte http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_byte_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* short_pskel:: + _static_type () + { + return "short http://www.w3.org/2001/XMLSchema"; + } + + const char* short_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_short_pskel:: + _static_type () + { + return "unsignedShort http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_short_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* int_pskel:: + _static_type () + { + return "int http://www.w3.org/2001/XMLSchema"; + } + + const char* int_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_int_pskel:: + _static_type () + { + return "unsignedInt http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_int_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* long_pskel:: + _static_type () + { + return "long http://www.w3.org/2001/XMLSchema"; + } + + const char* long_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_long_pskel:: + _static_type () + { + return "unsignedLong http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_long_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* integer_pskel:: + _static_type () + { + return "integer http://www.w3.org/2001/XMLSchema"; + } + + const char* integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* negative_integer_pskel:: + _static_type () + { + return "negativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* negative_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_positive_integer_pskel:: + _static_type () + { + return "nonPositiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_positive_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* positive_integer_pskel:: + _static_type () + { + return "positiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* positive_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_negative_integer_pskel:: + _static_type () + { + return "nonNegativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_negative_integer_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* float_pskel:: + _static_type () + { + return "float http://www.w3.org/2001/XMLSchema"; + } + + const char* float_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* double_pskel:: + _static_type () + { + return "double http://www.w3.org/2001/XMLSchema"; + } + + const char* double_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* decimal_pskel:: + _static_type () + { + return "decimal http://www.w3.org/2001/XMLSchema"; + } + + const char* decimal_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* string_pskel:: + _static_type () + { + return "string http://www.w3.org/2001/XMLSchema"; + } + + const char* string_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* normalized_string_pskel:: + _static_type () + { + return "normalizedString http://www.w3.org/2001/XMLSchema"; + } + + const char* normalized_string_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* token_pskel:: + _static_type () + { + return "token http://www.w3.org/2001/XMLSchema"; + } + + const char* token_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* name_pskel:: + _static_type () + { + return "Name http://www.w3.org/2001/XMLSchema"; + } + + const char* name_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtoken_pskel:: + _static_type () + { + return "NMTOKEN http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtoken_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtokens_pskel:: + _static_type () + { + return "NMTOKENS http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtokens_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* ncname_pskel:: + _static_type () + { + return "NCName http://www.w3.org/2001/XMLSchema"; + } + + const char* ncname_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* id_pskel:: + _static_type () + { + return "ID http://www.w3.org/2001/XMLSchema"; + } + + const char* id_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idref_pskel:: + _static_type () + { + return "IDREF http://www.w3.org/2001/XMLSchema"; + } + + const char* idref_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idrefs_pskel:: + _static_type () + { + return "IDREFS http://www.w3.org/2001/XMLSchema"; + } + + const char* idrefs_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* language_pskel:: + _static_type () + { + return "language http://www.w3.org/2001/XMLSchema"; + } + + const char* language_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* uri_pskel:: + _static_type () + { + return "anyURI http://www.w3.org/2001/XMLSchema"; + } + + const char* uri_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* qname_pskel:: + _static_type () + { + return "QName http://www.w3.org/2001/XMLSchema"; + } + + const char* qname_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* base64_binary_pskel:: + _static_type () + { + return "base64Binary http://www.w3.org/2001/XMLSchema"; + } + + const char* base64_binary_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* hex_binary_pskel:: + _static_type () + { + return "hexBinary http://www.w3.org/2001/XMLSchema"; + } + + const char* hex_binary_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gday_pskel:: + _static_type () + { + return "gDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gday_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_pskel:: + _static_type () + { + return "gMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_pskel:: + _static_type () + { + return "gYear http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_day_pskel:: + _static_type () + { + return "gMonthDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_day_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_month_pskel:: + _static_type () + { + return "gYearMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_month_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_pskel:: + _static_type () + { + return "date http://www.w3.org/2001/XMLSchema"; + } + + const char* date_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* time_pskel:: + _static_type () + { + return "time http://www.w3.org/2001/XMLSchema"; + } + + const char* time_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_time_pskel:: + _static_type () + { + return "dateTime http://www.w3.org/2001/XMLSchema"; + } + + const char* date_time_pskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* duration_pskel:: + _static_type () + { + return "duration http://www.w3.org/2001/XMLSchema"; + } + + const char* duration_pskel:: + _dynamic_type () const + { + return _static_type (); + } +#endif // XSDE_POLYMORPHIC + } + } + } +} + diff --git a/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.hxx b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.hxx new file mode 100644 index 0000000..8f9e33a --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.hxx @@ -0,0 +1,1385 @@ +// file : xsde/cxx/parser/validating/xml-schema-pskel.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PSKEL_HXX +#define XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PSKEL_HXX + +#include + +#ifdef XSDE_STL +# include +#endif + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // anyType and anySimpleType. All events are routed to the + // _any_* callbacks. + // + struct any_type_pskel: complex_content + { +#ifdef XSDE_POLYMORPHIC + virtual bool + _start_element_impl (const ro_string&, + const ro_string&, + const char*); +#else + virtual bool + _start_element_impl (const ro_string&, const ro_string&); +#endif + + virtual bool + _end_element_impl (const ro_string&, const ro_string&); + + virtual bool + _attribute_impl_phase_two (const ro_string&, + const ro_string&, + const ro_string&); + + virtual bool + _characters_impl (const ro_string&); + + virtual void + post_any_type (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_type_pskel (); + any_type_pskel (any_type_pskel* impl, void*); + + protected: + any_type_pskel* any_type_impl_; +#endif + }; + + struct any_simple_type_pskel: simple_content + { + virtual bool + _characters_impl (const ro_string&); + + virtual void + post_any_simple_type (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_simple_type_pskel (); + any_simple_type_pskel (any_simple_type_pskel* impl, void*); + + protected: + any_simple_type_pskel* any_simple_type_impl_; +#endif + }; + + + // Boolean. + // + struct boolean_pskel: simple_content + { + virtual bool + post_boolean () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + boolean_pskel (); + boolean_pskel (boolean_pskel* impl, void*); + + protected: + boolean_pskel* boolean_impl_; +#endif + }; + + + // 8-bit + // + + struct byte_pskel: simple_content + { + virtual signed char + post_byte () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + byte_pskel (); + byte_pskel (byte_pskel* impl, void*); + + protected: + byte_pskel* byte_impl_; +#endif + }; + + struct unsigned_byte_pskel: simple_content + { + virtual unsigned char + post_unsigned_byte () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_byte_pskel (); + unsigned_byte_pskel (unsigned_byte_pskel* impl, void*); + + protected: + unsigned_byte_pskel* unsigned_byte_impl_; +#endif + }; + + + // 16-bit + // + + struct short_pskel: simple_content + { + virtual short + post_short () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + short_pskel (); + short_pskel (short_pskel* impl, void*); + + protected: + short_pskel* short_impl_; +#endif + }; + + struct unsigned_short_pskel: simple_content + { + virtual unsigned short + post_unsigned_short () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_short_pskel (); + unsigned_short_pskel (unsigned_short_pskel* impl, void*); + + protected: + unsigned_short_pskel* unsigned_short_impl_; +#endif + }; + + + // 32-bit + // + + struct int_pskel: simple_content + { + virtual int + post_int () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + int_pskel (); + int_pskel (int_pskel* impl, void*); + + protected: + int_pskel* int_impl_; +#endif + }; + + struct unsigned_int_pskel: simple_content + { + virtual unsigned int + post_unsigned_int () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_int_pskel (); + unsigned_int_pskel (unsigned_int_pskel* impl, void*); + + protected: + unsigned_int_pskel* unsigned_int_impl_; +#endif + }; + + + // 64-bit + // +#ifdef XSDE_LONGLONG + + struct long_pskel: simple_content + { + virtual long long + post_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_pskel (); + long_pskel (long_pskel* impl, void*); + + protected: + long_pskel* long_impl_; +#endif + }; + + struct unsigned_long_pskel: simple_content + { + virtual unsigned long long + post_unsigned_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_pskel (); + unsigned_long_pskel (unsigned_long_pskel* impl, void*); + + protected: + unsigned_long_pskel* unsigned_long_impl_; +#endif + }; + +#else + + struct long_pskel: simple_content + { + virtual long + post_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_pskel (); + long_pskel (long_pskel* impl, void*); + + protected: + long_pskel* long_impl_; +#endif + }; + + struct unsigned_long_pskel: simple_content + { + virtual unsigned long + post_unsigned_long () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_pskel (); + unsigned_long_pskel (unsigned_long_pskel* impl, void*); + + protected: + unsigned_long_pskel* unsigned_long_impl_; +#endif + }; +#endif + + + // Arbitrary-length integers. + // + + struct integer_pskel: simple_content + { + virtual long + post_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + integer_pskel (); + integer_pskel (integer_pskel* impl, void*); + + protected: + integer_pskel* integer_impl_; +#endif + }; + + struct negative_integer_pskel: simple_content + { + virtual long + post_negative_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + negative_integer_pskel (); + negative_integer_pskel (negative_integer_pskel* impl, void*); + + protected: + negative_integer_pskel* negative_integer_impl_; +#endif + }; + + struct non_positive_integer_pskel: simple_content + { + virtual long + post_non_positive_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_positive_integer_pskel (); + non_positive_integer_pskel (non_positive_integer_pskel* impl, void*); + + protected: + non_positive_integer_pskel* non_positive_integer_impl_; +#endif + }; + + struct positive_integer_pskel: simple_content + { + virtual unsigned long + post_positive_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + positive_integer_pskel (); + positive_integer_pskel (positive_integer_pskel* impl, void*); + + protected: + positive_integer_pskel* positive_integer_impl_; +#endif + }; + + struct non_negative_integer_pskel: simple_content + { + virtual unsigned long + post_non_negative_integer () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_negative_integer_pskel (); + non_negative_integer_pskel (non_negative_integer_pskel* impl, void*); + + protected: + non_negative_integer_pskel* non_negative_integer_impl_; +#endif + }; + + + // Floats. + // + + struct float_pskel: simple_content + { + virtual float + post_float () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + float_pskel (); + float_pskel (float_pskel* impl, void*); + + protected: + float_pskel* float_impl_; +#endif + }; + + struct double_pskel: simple_content + { + virtual double + post_double () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + double_pskel (); + double_pskel (double_pskel* impl, void*); + + protected: + double_pskel* double_impl_; +#endif + }; + + struct decimal_pskel: simple_content + { + virtual double + post_decimal () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + decimal_pskel (); + decimal_pskel (decimal_pskel* impl, void*); + + protected: + decimal_pskel* decimal_impl_; +#endif + }; + + + // String-based types. + // +#ifdef XSDE_STL + + struct string_pskel: simple_content + { + virtual std::string + post_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_pskel (); + string_pskel (string_pskel* impl, void*); + + protected: + string_pskel* string_impl_; +#endif + }; + + struct normalized_string_pskel: simple_content + { + virtual std::string + post_normalized_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_pskel (); + normalized_string_pskel (normalized_string_pskel* impl, void*); + + protected: + normalized_string_pskel* normalized_string_impl_; +#endif + }; + + struct token_pskel: simple_content + { + virtual std::string + post_token () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_pskel (); + token_pskel (token_pskel* impl, void*); + + protected: + token_pskel* token_impl_; +#endif + }; + + struct name_pskel: simple_content + { + virtual std::string + post_name () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_pskel (); + name_pskel (name_pskel* impl, void*); + + protected: + name_pskel* name_impl_; +#endif + }; + + struct nmtoken_pskel: simple_content + { + virtual std::string + post_nmtoken () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_pskel (); + nmtoken_pskel (nmtoken_pskel* impl, void*); + + protected: + nmtoken_pskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_pskel: list_base + { + virtual string_sequence* + post_nmtokens () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_pskel (); + nmtokens_pskel (nmtokens_pskel* impl, void*); + + protected: + nmtokens_pskel* nmtokens_impl_; +#endif + }; + + struct ncname_pskel: simple_content + { + virtual std::string + post_ncname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_pskel (); + ncname_pskel (ncname_pskel* impl, void*); + + protected: + ncname_pskel* ncname_impl_; +#endif + }; + + struct id_pskel: simple_content + { + virtual std::string + post_id () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_pskel (); + id_pskel (id_pskel* impl, void*); + + protected: + id_pskel* id_impl_; +#endif + }; + + struct idref_pskel: simple_content + { + virtual std::string + post_idref () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_pskel (); + idref_pskel (idref_pskel* impl, void*); + + protected: + idref_pskel* idref_impl_; +#endif + }; + + struct idrefs_pskel: list_base + { + virtual string_sequence* + post_idrefs () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_pskel (); + idrefs_pskel (idrefs_pskel* impl, void*); + + protected: + idrefs_pskel* idrefs_impl_; +#endif + }; + + struct language_pskel: simple_content + { + virtual std::string + post_language () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_pskel (); + language_pskel (language_pskel* impl, void*); + + protected: + language_pskel* language_impl_; +#endif + }; + + struct uri_pskel: simple_content + { + virtual std::string + post_uri () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_pskel (); + uri_pskel (uri_pskel* impl, void*); + + protected: + uri_pskel* uri_impl_; +#endif + }; + + struct qname_pskel: simple_content + { + virtual qname + post_qname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_pskel (); + qname_pskel (qname_pskel* impl, void*); + + protected: + qname_pskel* qname_impl_; +#endif + }; + +#else // XSDE_STL + + // Note that in this case you are getting a C string that you + // have to delete with delete[]. + // + struct string_pskel: simple_content + { + virtual char* + post_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_pskel (); + string_pskel (string_pskel* impl, void*); + + protected: + string_pskel* string_impl_; +#endif + }; + + struct normalized_string_pskel: simple_content + { + virtual char* + post_normalized_string () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_pskel (); + normalized_string_pskel (normalized_string_pskel* impl, void*); + + protected: + normalized_string_pskel* normalized_string_impl_; +#endif + }; + + struct token_pskel: simple_content + { + virtual char* + post_token () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_pskel (); + token_pskel (token_pskel* impl, void*); + + protected: + token_pskel* token_impl_; +#endif + }; + + struct name_pskel: simple_content + { + virtual char* + post_name () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_pskel (); + name_pskel (name_pskel* impl, void*); + + protected: + name_pskel* name_impl_; +#endif + }; + + struct nmtoken_pskel: simple_content + { + virtual char* + post_nmtoken () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_pskel (); + nmtoken_pskel (nmtoken_pskel* impl, void*); + + protected: + nmtoken_pskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_pskel: list_base + { + virtual string_sequence* + post_nmtokens () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_pskel (); + nmtokens_pskel (nmtokens_pskel* impl, void*); + + protected: + nmtokens_pskel* nmtokens_impl_; +#endif + }; + + struct ncname_pskel: simple_content + { + virtual char* + post_ncname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_pskel (); + ncname_pskel (ncname_pskel* impl, void*); + + protected: + ncname_pskel* ncname_impl_; +#endif + }; + + struct id_pskel: simple_content + { + virtual char* + post_id () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_pskel (); + id_pskel (id_pskel* impl, void*); + + protected: + id_pskel* id_impl_; +#endif + }; + + struct idref_pskel: simple_content + { + virtual char* + post_idref () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_pskel (); + idref_pskel (idref_pskel* impl, void*); + + protected: + idref_pskel* idref_impl_; +#endif + }; + + struct idrefs_pskel: list_base + { + virtual string_sequence* + post_idrefs () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_pskel (); + idrefs_pskel (idrefs_pskel* impl, void*); + + protected: + idrefs_pskel* idrefs_impl_; +#endif + }; + + struct language_pskel: simple_content + { + virtual char* + post_language () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_pskel (); + language_pskel (language_pskel* impl, void*); + + protected: + language_pskel* language_impl_; +#endif + }; + + struct uri_pskel: simple_content + { + virtual char* + post_uri () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_pskel (); + uri_pskel (uri_pskel* impl, void*); + + protected: + uri_pskel* uri_impl_; +#endif + }; + + struct qname_pskel: simple_content + { + virtual qname* + post_qname () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_pskel (); + qname_pskel (qname_pskel* impl, void*); + + protected: + qname_pskel* qname_impl_; +#endif + }; +#endif // XSDE_STL + + + // base64Binary + // + struct base64_binary_pskel: simple_content + { + virtual buffer* + post_base64_binary () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + base64_binary_pskel (); + base64_binary_pskel (base64_binary_pskel* impl, void*); + + protected: + base64_binary_pskel* base64_binary_impl_; +#endif + }; + + // hexBinary + // + struct hex_binary_pskel: simple_content + { + virtual buffer* + post_hex_binary () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + hex_binary_pskel (); + hex_binary_pskel (hex_binary_pskel* impl, void*); + + protected: + hex_binary_pskel* hex_binary_impl_; +#endif + }; + + // Time and date types. + // + struct gday_pskel: simple_content + { + virtual gday + post_gday () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gday_pskel (); + gday_pskel (gday_pskel* impl, void*); + + protected: + gday_pskel* gday_impl_; +#endif + }; + + struct gmonth_pskel: simple_content + { + virtual gmonth + post_gmonth () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_pskel (); + gmonth_pskel (gmonth_pskel* impl, void*); + + protected: + gmonth_pskel* gmonth_impl_; +#endif + }; + + struct gyear_pskel: simple_content + { + virtual gyear + post_gyear () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_pskel (); + gyear_pskel (gyear_pskel* impl, void*); + + protected: + gyear_pskel* gyear_impl_; +#endif + }; + + struct gmonth_day_pskel: simple_content + { + virtual gmonth_day + post_gmonth_day () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_day_pskel (); + gmonth_day_pskel (gmonth_day_pskel* impl, void*); + + protected: + gmonth_day_pskel* gmonth_day_impl_; +#endif + }; + + struct gyear_month_pskel: simple_content + { + virtual gyear_month + post_gyear_month () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_month_pskel (); + gyear_month_pskel (gyear_month_pskel* impl, void*); + + protected: + gyear_month_pskel* gyear_month_impl_; +#endif + }; + + struct date_pskel: simple_content + { + virtual date + post_date () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_pskel (); + date_pskel (date_pskel* impl, void*); + + protected: + date_pskel* date_impl_; +#endif + }; + + struct time_pskel: simple_content + { + virtual time + post_time () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + time_pskel (); + time_pskel (time_pskel* impl, void*); + + protected: + time_pskel* time_impl_; +#endif + }; + + struct date_time_pskel: simple_content + { + virtual date_time + post_date_time () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_time_pskel (); + date_time_pskel (date_time_pskel* impl, void*); + + protected: + date_time_pskel* date_time_impl_; +#endif + }; + + struct duration_pskel: simple_content + { + virtual duration + post_duration () = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + duration_pskel (); + duration_pskel (duration_pskel* impl, void*); + + protected: + duration_pskel* duration_impl_; +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_PARSER_VALIDATING_XML_SCHEMA_PSKEL_HXX diff --git a/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.ixx b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.ixx new file mode 100644 index 0000000..bb94f3e --- /dev/null +++ b/libxsde/xsde/cxx/parser/validating/xml-schema-pskel.ixx @@ -0,0 +1,704 @@ +// file : xsde/cxx/parser/validating/xml-schema-pskel.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace parser + { + namespace validating + { + // any_type_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_type_pskel:: + any_type_pskel () + : any_type_impl_ (0) + { + } + + inline any_type_pskel:: + any_type_pskel (any_type_pskel* impl, void*) + : complex_content (impl, 0), any_type_impl_ (impl) + { + } +#endif + + // any_simple_type_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_simple_type_pskel:: + any_simple_type_pskel () + : any_simple_type_impl_ (0) + { + } + + inline any_simple_type_pskel:: + any_simple_type_pskel (any_simple_type_pskel* impl, void*) + : simple_content (impl, 0), any_simple_type_impl_ (impl) + { + } +#endif + + // boolean_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline boolean_pskel:: + boolean_pskel () + : boolean_impl_ (0) + { + } + + inline boolean_pskel:: + boolean_pskel (boolean_pskel* impl, void*) + : simple_content (impl, 0), boolean_impl_ (impl) + { + } +#endif + + // byte_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline byte_pskel:: + byte_pskel () + : byte_impl_ (0) + { + } + + inline byte_pskel:: + byte_pskel (byte_pskel* impl, void*) + : simple_content (impl, 0), byte_impl_ (impl) + { + } +#endif + + // unsigned_byte_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_byte_pskel:: + unsigned_byte_pskel () + : unsigned_byte_impl_ (0) + { + } + + inline unsigned_byte_pskel:: + unsigned_byte_pskel (unsigned_byte_pskel* impl, void*) + : simple_content (impl, 0), unsigned_byte_impl_ (impl) + { + } +#endif + + // short_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline short_pskel:: + short_pskel () + : short_impl_ (0) + { + } + + inline short_pskel:: + short_pskel (short_pskel* impl, void*) + : simple_content (impl, 0), short_impl_ (impl) + { + } +#endif + + // unsigned_short_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_short_pskel:: + unsigned_short_pskel () + : unsigned_short_impl_ (0) + { + } + + inline unsigned_short_pskel:: + unsigned_short_pskel (unsigned_short_pskel* impl, void*) + : simple_content (impl, 0), unsigned_short_impl_ (impl) + { + } +#endif + + // int_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline int_pskel:: + int_pskel () + : int_impl_ (0) + { + } + + inline int_pskel:: + int_pskel (int_pskel* impl, void*) + : simple_content (impl, 0), int_impl_ (impl) + { + } +#endif + + // unsigned_int_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_int_pskel:: + unsigned_int_pskel () + : unsigned_int_impl_ (0) + { + } + + inline unsigned_int_pskel:: + unsigned_int_pskel (unsigned_int_pskel* impl, void*) + : simple_content (impl, 0), unsigned_int_impl_ (impl) + { + } +#endif + + // long_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline long_pskel:: + long_pskel () + : long_impl_ (0) + { + } + + inline long_pskel:: + long_pskel (long_pskel* impl, void*) + : simple_content (impl, 0), long_impl_ (impl) + { + } +#endif + + // unsigned_long_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_long_pskel:: + unsigned_long_pskel () + : unsigned_long_impl_ (0) + { + } + + inline unsigned_long_pskel:: + unsigned_long_pskel (unsigned_long_pskel* impl, void*) + : simple_content (impl, 0), unsigned_long_impl_ (impl) + { + } +#endif + + // integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline integer_pskel:: + integer_pskel () + : integer_impl_ (0) + { + } + + inline integer_pskel:: + integer_pskel (integer_pskel* impl, void*) + : simple_content (impl, 0), integer_impl_ (impl) + { + } +#endif + + // negative_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline negative_integer_pskel:: + negative_integer_pskel () + : negative_integer_impl_ (0) + { + } + + inline negative_integer_pskel:: + negative_integer_pskel (negative_integer_pskel* impl, void*) + : simple_content (impl, 0), negative_integer_impl_ (impl) + { + } +#endif + + // non_positive_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_positive_integer_pskel:: + non_positive_integer_pskel () + : non_positive_integer_impl_ (0) + { + } + + inline non_positive_integer_pskel:: + non_positive_integer_pskel (non_positive_integer_pskel* impl, void*) + : simple_content (impl, 0), non_positive_integer_impl_ (impl) + { + } +#endif + + // positive_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline positive_integer_pskel:: + positive_integer_pskel () + : positive_integer_impl_ (0) + { + } + + inline positive_integer_pskel:: + positive_integer_pskel (positive_integer_pskel* impl, void*) + : simple_content (impl, 0), positive_integer_impl_ (impl) + { + } +#endif + + // non_negative_integer_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_negative_integer_pskel:: + non_negative_integer_pskel () + : non_negative_integer_impl_ (0) + { + } + + inline non_negative_integer_pskel:: + non_negative_integer_pskel (non_negative_integer_pskel* impl, void*) + : simple_content (impl, 0), non_negative_integer_impl_ (impl) + { + } +#endif + + // float_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline float_pskel:: + float_pskel () + : float_impl_ (0) + { + } + + inline float_pskel:: + float_pskel (float_pskel* impl, void*) + : simple_content (impl, 0), float_impl_ (impl) + { + } +#endif + + // double_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline double_pskel:: + double_pskel () + : double_impl_ (0) + { + } + + inline double_pskel:: + double_pskel (double_pskel* impl, void*) + : simple_content (impl, 0), double_impl_ (impl) + { + } +#endif + + // decimal_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline decimal_pskel:: + decimal_pskel () + : decimal_impl_ (0) + { + } + + inline decimal_pskel:: + decimal_pskel (decimal_pskel* impl, void*) + : simple_content (impl, 0), decimal_impl_ (impl) + { + } +#endif + + // string_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline string_pskel:: + string_pskel () + : string_impl_ (0) + { + } + + inline string_pskel:: + string_pskel (string_pskel* impl, void*) + : simple_content (impl, 0), string_impl_ (impl) + { + } +#endif + + // normalized_string_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline normalized_string_pskel:: + normalized_string_pskel () + : normalized_string_impl_ (0) + { + } + + inline normalized_string_pskel:: + normalized_string_pskel (normalized_string_pskel* impl, void*) + : simple_content (impl, 0), normalized_string_impl_ (impl) + { + } +#endif + + // token_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline token_pskel:: + token_pskel () + : token_impl_ (0) + { + } + + inline token_pskel:: + token_pskel (token_pskel* impl, void*) + : simple_content (impl, 0), token_impl_ (impl) + { + } +#endif + + // name_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline name_pskel:: + name_pskel () + : name_impl_ (0) + { + } + + inline name_pskel:: + name_pskel (name_pskel* impl, void*) + : simple_content (impl, 0), name_impl_ (impl) + { + } +#endif + + // nmtoken_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtoken_pskel:: + nmtoken_pskel () + : nmtoken_impl_ (0) + { + } + + inline nmtoken_pskel:: + nmtoken_pskel (nmtoken_pskel* impl, void*) + : simple_content (impl, 0), nmtoken_impl_ (impl) + { + } +#endif + + // nmtokens_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtokens_pskel:: + nmtokens_pskel () + : nmtokens_impl_ (0) + { + } + + inline nmtokens_pskel:: + nmtokens_pskel (nmtokens_pskel* impl, void*) + : list_base (impl, 0), nmtokens_impl_ (impl) + { + } +#endif + + // ncname_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline ncname_pskel:: + ncname_pskel () + : ncname_impl_ (0) + { + } + + inline ncname_pskel:: + ncname_pskel (ncname_pskel* impl, void*) + : simple_content (impl, 0), ncname_impl_ (impl) + { + } +#endif + + // id_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline id_pskel:: + id_pskel () + : id_impl_ (0) + { + } + + inline id_pskel:: + id_pskel (id_pskel* impl, void*) + : simple_content (impl, 0), id_impl_ (impl) + { + } +#endif + + // idref_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idref_pskel:: + idref_pskel () + : idref_impl_ (0) + { + } + + inline idref_pskel:: + idref_pskel (idref_pskel* impl, void*) + : simple_content (impl, 0), idref_impl_ (impl) + { + } +#endif + + // idrefs_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idrefs_pskel:: + idrefs_pskel () + : idrefs_impl_ (0) + { + } + + inline idrefs_pskel:: + idrefs_pskel (idrefs_pskel* impl, void*) + : list_base (impl, 0), idrefs_impl_ (impl) + { + } +#endif + + // language_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline language_pskel:: + language_pskel () + : language_impl_ (0) + { + } + + inline language_pskel:: + language_pskel (language_pskel* impl, void*) + : simple_content (impl, 0), language_impl_ (impl) + { + } +#endif + + // uri_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline uri_pskel:: + uri_pskel () + : uri_impl_ (0) + { + } + + inline uri_pskel:: + uri_pskel (uri_pskel* impl, void*) + : simple_content (impl, 0), uri_impl_ (impl) + { + } +#endif + + // qname_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline qname_pskel:: + qname_pskel () + : qname_impl_ (0) + { + } + + inline qname_pskel:: + qname_pskel (qname_pskel* impl, void*) + : simple_content (impl, 0), qname_impl_ (impl) + { + } +#endif + + // base64_binary_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline base64_binary_pskel:: + base64_binary_pskel () + : base64_binary_impl_ (0) + { + } + + inline base64_binary_pskel:: + base64_binary_pskel (base64_binary_pskel* impl, void*) + : simple_content (impl, 0), base64_binary_impl_ (impl) + { + } +#endif + + // hex_binary_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline hex_binary_pskel:: + hex_binary_pskel () + : hex_binary_impl_ (0) + { + } + + inline hex_binary_pskel:: + hex_binary_pskel (hex_binary_pskel* impl, void*) + : simple_content (impl, 0), hex_binary_impl_ (impl) + { + } +#endif + + // gday_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gday_pskel:: + gday_pskel () + : gday_impl_ (0) + { + } + + inline gday_pskel:: + gday_pskel (gday_pskel* impl, void*) + : simple_content (impl, 0), gday_impl_ (impl) + { + } +#endif + + // gmonth_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_pskel:: + gmonth_pskel () + : gmonth_impl_ (0) + { + } + + inline gmonth_pskel:: + gmonth_pskel (gmonth_pskel* impl, void*) + : simple_content (impl, 0), gmonth_impl_ (impl) + { + } +#endif + + // gyear_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_pskel:: + gyear_pskel () + : gyear_impl_ (0) + { + } + + inline gyear_pskel:: + gyear_pskel (gyear_pskel* impl, void*) + : simple_content (impl, 0), gyear_impl_ (impl) + { + } +#endif + + // gmonth_day_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_day_pskel:: + gmonth_day_pskel () + : gmonth_day_impl_ (0) + { + } + + inline gmonth_day_pskel:: + gmonth_day_pskel (gmonth_day_pskel* impl, void*) + : simple_content (impl, 0), gmonth_day_impl_ (impl) + { + } +#endif + + // gyear_month_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_month_pskel:: + gyear_month_pskel () + : gyear_month_impl_ (0) + { + } + + inline gyear_month_pskel:: + gyear_month_pskel (gyear_month_pskel* impl, void*) + : simple_content (impl, 0), gyear_month_impl_ (impl) + { + } +#endif + + // date_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_pskel:: + date_pskel () + : date_impl_ (0) + { + } + + inline date_pskel:: + date_pskel (date_pskel* impl, void*) + : simple_content (impl, 0), date_impl_ (impl) + { + } +#endif + + // time_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline time_pskel:: + time_pskel () + : time_impl_ (0) + { + } + + inline time_pskel:: + time_pskel (time_pskel* impl, void*) + : simple_content (impl, 0), time_impl_ (impl) + { + } +#endif + + // date_time_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_time_pskel:: + date_time_pskel () + : date_time_impl_ (0) + { + } + + inline date_time_pskel:: + date_time_pskel (date_time_pskel* impl, void*) + : simple_content (impl, 0), date_time_impl_ (impl) + { + } +#endif + + // duration_pskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline duration_pskel:: + duration_pskel () + : duration_impl_ (0) + { + } + + inline duration_pskel:: + duration_pskel (duration_pskel* impl, void*) + : simple_content (impl, 0), duration_impl_ (impl) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/parser/xml-schema.hxx b/libxsde/xsde/cxx/parser/xml-schema.hxx new file mode 100644 index 0000000..5b17568 --- /dev/null +++ b/libxsde/xsde/cxx/parser/xml-schema.hxx @@ -0,0 +1,20 @@ +// file : xsde/cxx/parser/xml-schema.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_PARSER_XML_SCHEMA_HXX +#define XSDE_CXX_PARSER_XML_SCHEMA_HXX + +#include +#include + +#ifdef XSDE_STL +# include +# include +#else +# include +# include +#endif + +#endif // XSDE_CXX_PARSER_XML_SCHEMA_HXX diff --git a/libxsde/xsde/cxx/post.hxx b/libxsde/xsde/cxx/post.hxx new file mode 100644 index 0000000..2f913ec --- /dev/null +++ b/libxsde/xsde/cxx/post.hxx @@ -0,0 +1,14 @@ +// file : xsde/cxx/post.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifdef _MSC_VER +# if (_MSC_VER >= 1400) +# include +# elif (_MSC_VER >= 1300) +# include +# elif (_MSC_VER >= 1200) +# include +# endif +#endif diff --git a/libxsde/xsde/cxx/pre.hxx b/libxsde/xsde/cxx/pre.hxx new file mode 100644 index 0000000..a73dff1 --- /dev/null +++ b/libxsde/xsde/cxx/pre.hxx @@ -0,0 +1,15 @@ +// file : xsde/cxx/pre.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + + +#ifdef _MSC_VER +# if (_MSC_VER >= 1400) +# include +# elif (_MSC_VER >= 1300) +# include +# elif (_MSC_VER >= 1200) +# include +# endif +#endif diff --git a/libxsde/xsde/cxx/qname-stl.hxx b/libxsde/xsde/cxx/qname-stl.hxx new file mode 100644 index 0000000..ea5b5d8 --- /dev/null +++ b/libxsde/xsde/cxx/qname-stl.hxx @@ -0,0 +1,59 @@ +// file : xsde/cxx/qname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_QNAME_STL_HXX +#define XSDE_CXX_QNAME_STL_HXX + +#include + +namespace xsde +{ + namespace cxx + { + class qname + { + public: + qname (); + explicit + qname (const std::string& name); + qname (const std::string& prefix, const std::string& name); + + void + swap (qname&); + + const std::string& + prefix () const; + + std::string& + prefix (); + + void + prefix (const std::string&); + + const std::string& + name () const; + + std::string& + name (); + + void + name (const std::string&); + + private: + std::string prefix_; + std::string name_; + }; + + bool + operator== (const qname&, const qname&); + + bool + operator!= (const qname&, const qname&); + } +} + +#include + +#endif // XSDE_CXX_QNAME_STL_HXX diff --git a/libxsde/xsde/cxx/qname-stl.ixx b/libxsde/xsde/cxx/qname-stl.ixx new file mode 100644 index 0000000..f4122e5 --- /dev/null +++ b/libxsde/xsde/cxx/qname-stl.ixx @@ -0,0 +1,82 @@ +// file : xsde/cxx/qname-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline qname:: + qname () + { + } + + inline qname:: + qname (const std::string& name) + : prefix_ (), name_ (name) + { + } + + inline qname:: + qname (const std::string& prefix, const std::string& name) + : prefix_ (prefix), name_ (name) + { + } + + inline void qname:: + swap (qname& x) + { + prefix_.swap (x.prefix_); + name_.swap (x.name_); + } + + inline const std::string& qname:: + prefix () const + { + return prefix_; + } + + inline std::string& qname:: + prefix () + { + return prefix_; + } + + inline void qname:: + prefix (const std::string& prefix) + { + prefix_ = prefix; + } + + inline const std::string& qname:: + name () const + { + return name_; + } + + inline std::string& qname:: + name () + { + return name_; + } + + inline void qname:: + name (const std::string& name) + { + name_ = name; + } + + inline bool + operator== (const qname& x, const qname& y) + { + return x.name () == y.name () && x.prefix () == y.prefix (); + } + + inline bool + operator!= (const qname& x, const qname& y) + { + return !(x == y); + } + } +} diff --git a/libxsde/xsde/cxx/qname.cxx b/libxsde/xsde/cxx/qname.cxx new file mode 100644 index 0000000..ea89f4e --- /dev/null +++ b/libxsde/xsde/cxx/qname.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/qname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen, memcpy +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { +#ifndef XSDE_EXCEPTIONS + qname::error qname:: +#else + void qname:: +#endif + prefix_copy (const char* prefix) + { + delete[] prefix_; + + if (prefix) + { + size_t size = strlen (prefix) + 1; + prefix_ = new char[size]; + +#ifndef XSDE_EXCEPTIONS + if (prefix_ == 0) + return error_no_memory; +#endif + memcpy (prefix_, prefix, size); + } + else + prefix_ = 0; + +#ifndef XSDE_EXCEPTIONS + return error_none; +#endif + } + +#ifndef XSDE_EXCEPTIONS + qname::error qname:: +#else + void qname:: +#endif + name_copy (const char* name) + { + delete[] name_; + + if (name) + { + size_t size = strlen (name) + 1; + name_ = new char[size]; + +#ifndef XSDE_EXCEPTIONS + if (name_ == 0) + return error_no_memory; +#endif + memcpy (name_, name, size); + } + else + name_ = 0; + +#ifndef XSDE_EXCEPTIONS + return error_none; +#endif + } + } +} diff --git a/libxsde/xsde/cxx/qname.hxx b/libxsde/xsde/cxx/qname.hxx new file mode 100644 index 0000000..350b8f1 --- /dev/null +++ b/libxsde/xsde/cxx/qname.hxx @@ -0,0 +1,99 @@ +// file : xsde/cxx/qname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_QNAME_HXX +#define XSDE_CXX_QNAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + class qname + { + public: +#ifndef XSDE_EXCEPTIONS + enum error + { + error_none, + error_no_memory + }; +#endif + + ~qname (); + + // The default c-tor creates an uninitialized qname. Use + // modifiers to initialize it. + // + qname (); + + explicit + qname (char* name); + qname (char* prefix, char* name); + + void + swap (qname&); + + private: + qname (const qname&); + qname& operator= (const qname&); + + public: + char* + prefix (); + + const char* + prefix () const; + + void + prefix (char*); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + prefix_copy (const char*); + + char* + prefix_detach (); + + public: + char* + name (); + + const char* + name () const; + + void + name (char*); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + name_copy (const char*); + + char* + name_detach (); + + private: + char* prefix_; + char* name_; + }; + + bool + operator== (const qname&, const qname&); + + bool + operator!= (const qname&, const qname&); + } +} + +#include + +#endif // XSDE_CXX_QNAME_HXX diff --git a/libxsde/xsde/cxx/qname.ixx b/libxsde/xsde/cxx/qname.ixx new file mode 100644 index 0000000..6772556 --- /dev/null +++ b/libxsde/xsde/cxx/qname.ixx @@ -0,0 +1,125 @@ +// file : xsde/cxx/qname.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strcmp + +namespace xsde +{ + namespace cxx + { + // c-tors, d-tor and swap + // + inline qname:: + ~qname () + { + delete[] prefix_; + delete[] name_; + } + + inline qname:: + qname () + : prefix_ (0), name_ (0) + { + } + + inline qname:: + qname (char* n) + : prefix_ (0), name_ (n) + { + } + + inline qname:: + qname (char* p, char* n) + : prefix_ (p), name_ (n) + { + } + + inline void qname:: + swap (qname& x) + { + char* p = prefix_; + char* n = name_; + + prefix_ = x.prefix_; + name_ = x.name_; + + x.prefix_ = p; + x.name_ = n; + } + + // preix + // + inline char* qname:: + prefix () + { + return prefix_; + } + + inline const char* qname:: + prefix () const + { + return prefix_; + } + + inline void qname:: + prefix (char* prefix) + { + delete[] prefix_; + prefix_ = prefix; + } + + inline char* qname:: + prefix_detach () + { + char* r = prefix_; + prefix_ = 0; + return r; + } + + // name + // + inline char* qname:: + name () + { + return name_; + } + + inline const char* qname:: + name () const + { + return name_; + } + + inline void qname:: + name (char* name) + { + delete[] name_; + name_ = name; + } + + inline char* qname:: + name_detach () + { + char* r = name_; + name_ = 0; + return r; + } + + // + // + inline bool + operator== (const qname& x, const qname& y) + { + return strcmp (x.name (), y.name ()) == 0 && + strcmp (x.prefix (), y.prefix ()) == 0; + } + + inline bool + operator!= (const qname& x, const qname& y) + { + return !(x == y); + } + } +} diff --git a/libxsde/xsde/cxx/ro-string.cxx b/libxsde/xsde/cxx/ro-string.cxx new file mode 100644 index 0000000..c74b34f --- /dev/null +++ b/libxsde/xsde/cxx/ro-string.cxx @@ -0,0 +1,116 @@ +// file : xsde/cxx/ro-string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +namespace xsde +{ + namespace cxx + { + // ro_string + const size_t ro_string::npos = ~(size_t (0)); + + // operator << + // +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream& os, const ro_string& str) + { + if (str.size () != 0) + os.write (str.data (), str.size ()); + + return os; + } +#endif + + size_t + trim_left (ro_string& s) + { + size_t size = s.size (); + + if (size != 0) + { + const char* f = s.data (); + const char* l = f + size; + const char* of = f; + + while (f < l && + (*f == 0x20 || *f == 0x0A || *f == 0x0D || *f == 0x09)) + ++f; + + if (f != of) + { + size = f <= l ? l - f : 0; + s.assign ((f <= l ? f : 0), size); + } + } + + return size; + } + + size_t + trim_right (ro_string& s) + { + size_t size = s.size (); + + if (size != 0) + { + const char* f = s.data (); + const char* l = f + size - 1; + const char* ol = l; + + while (l > f && + (*l == 0x20 || *l == 0x0A || *l == 0x0D || *l == 0x09)) + --l; + + if (l != ol) + { + size = f <= l ? l - f + 1 : 0; + s.assign ((f <= l ? f : 0), size); + } + } + + return size; + } + + size_t + trim (ro_string& s) + { + size_t size = s.size (); + + if (size != 0) + { + const char* f = s.data (); + const char* l = f + size; + + const char* of = f; + + while (f < l && + (*f == 0x20 || *f == 0x0A || *f == 0x0D || *f == 0x09)) + ++f; + + --l; + + const char* ol = l; + + while (l > f && + (*l == 0x20 || *l == 0x0A || *l == 0x0D || *l == 0x09)) + --l; + + if (f != of || l != ol) + { + size = f <= l ? l - f + 1 : 0; + s.assign ((f <= l ? f : 0), size); + } + } + + return size; + } + } +} diff --git a/libxsde/xsde/cxx/ro-string.hxx b/libxsde/xsde/cxx/ro-string.hxx new file mode 100644 index 0000000..aebe6e3 --- /dev/null +++ b/libxsde/xsde/cxx/ro-string.hxx @@ -0,0 +1,281 @@ +// file : xsde/cxx/ro-string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_RO_STRING_HXX +#define XSDE_CXX_RO_STRING_HXX + +#include + +#include // size_t + +#ifdef XSDE_STL +# include +#endif + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + // Read-only string. + // + struct ro_string + { + typedef size_t size_type; + static const size_t npos; + + public: + ro_string (); + ro_string (const char*); + ro_string (const char*, size_t); + ro_string (const string&); + +#ifdef XSDE_STL + ro_string (const std::string&); + operator std::string () const; +#endif + + private: + ro_string (const ro_string&); + + ro_string& + operator= (const ro_string&); + + public: + // The returned string is not necessarily terminated with '\0'. + // If size() returns 0, the returned pointer may be 0. + // + const char* + data () const; + + size_t + size () const; + + size_t + length () const; + + public: + bool + empty () const; + + char + operator[] (size_t) const; + + public: + void + assign (const char*); + + void + assign (const char*, size_t); + + void + assign (const string&); + +#ifdef XSDE_STL + void + assign (const std::string&); +#endif + + public: + int + compare (const ro_string&) const; + + int + compare (const char*) const; + + int + compare (const char*, size_t) const; + + int + compare (const string&) const; + +#ifdef XSDE_STL + int + compare (const std::string&) const; +#endif + + public: + size_t + find (char, size_t pos = 0) const; + + private: + const char* data_; + size_t size_; + }; + + + // operator == + // + + bool + operator== (const ro_string&, const ro_string&); + + bool + operator== (const ro_string&, const char*); + + bool + operator== (const char*, const ro_string&); + + bool + operator== (const ro_string&, const string&); + + bool + operator== (const string&, const ro_string&); + +#ifdef XSDE_STL + bool + operator== (const ro_string&, const std::string&); + + bool + operator== (const std::string&, const ro_string&); +#endif + + + // operator != + // + + bool + operator!= (const ro_string&, const ro_string&); + + bool + operator!= (const ro_string&, const char*); + + bool + operator!= (const char*, const ro_string&); + + bool + operator!= (const ro_string&, const string&); + + bool + operator!= (const string&, const ro_string&); + +#ifdef XSDE_STL + bool + operator!= (const ro_string&, const std::string&); + + bool + operator!= (const std::string&, const ro_string&); +#endif + + + // operator < + // + + bool + operator< (const ro_string&, const ro_string&); + + bool + operator< (const ro_string&, const char*); + + bool + operator< (const char*, const ro_string&); + +#ifdef XSDE_STL + bool + operator< (const ro_string&, const std::string&); + + bool + operator< (const std::string&, const ro_string&); +#endif + + + // operator > + // + + bool + operator> (const ro_string&, const ro_string&); + + bool + operator> (const ro_string&, const char*); + + bool + operator> (const char*, const ro_string&); + +#ifdef XSDE_STL + bool + operator> (const ro_string&, const std::string&); + + bool + operator> (const std::string&, const ro_string&); +#endif + + + // operator <= + // + + bool + operator<= (const ro_string&, const ro_string&); + + bool + operator<= (const ro_string&, const char*); + + bool + operator<= (const char*, const ro_string&); + +#ifdef XSDE_STL + bool + operator<= (const ro_string&, const std::string&); + + bool + operator<= (const std::string&, const ro_string&); +#endif + + + // operator>= + // + + bool + operator>= (const ro_string&, const ro_string&); + + bool + operator>= (const ro_string&, const char*); + + bool + operator>= (const char*, const ro_string&); + +#ifdef XSDE_STL + bool + operator>= (const ro_string&, const std::string&); + + bool + operator>= (const std::string&, const ro_string&); +#endif + + // operator += + // +#ifdef XSDE_STL + std::string& + operator+= (std::string&, const ro_string&); +#endif + + // operator << + // +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream&, const ro_string&); +#endif + + // Trim leading and trailing XML whitespaces. Return the new + // string size. + // + size_t + trim_left (ro_string&); + + size_t + trim_right (ro_string&); + + size_t + trim (ro_string&); + } +} + +#include + +#endif // XSDE_CXX_RO_STRING_HXX diff --git a/libxsde/xsde/cxx/ro-string.ixx b/libxsde/xsde/cxx/ro-string.ixx new file mode 100644 index 0000000..ff863a3 --- /dev/null +++ b/libxsde/xsde/cxx/ro-string.ixx @@ -0,0 +1,409 @@ +// file : xsde/cxx/ro-string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + inline ro_string:: + ro_string () + : data_ (0), size_ (0) + { + } + + inline ro_string:: + ro_string (const char* s) + : data_ (s), size_ (strlen (s)) + { + } + + inline ro_string:: + ro_string (const char* s, size_t size) + : data_ (s), size_ (size) + { + } + + inline ro_string:: + ro_string (const string& s) + : data_ (s.data ()), size_ (s.size ()) + { + } + +#ifdef XSDE_STL + inline ro_string:: + ro_string (const std::string& s) + : data_ (s.data ()), size_ (s.size ()) + { + } + + inline ro_string:: + operator std::string () const + { + return std::string (data (), size ()); + } +#endif + + inline const char* ro_string:: + data () const + { + return data_; + } + + inline size_t ro_string:: + size () const + { + return size_; + } + + inline size_t ro_string:: + length () const + { + return size_; + } + + inline bool ro_string:: + empty () const + { + return size_ == 0; + } + + inline char ro_string:: + operator[] (size_t pos) const + { + return data_[pos]; + } + + inline void ro_string:: + assign (const char* s) + { + data_ = s; + size_ = strlen (s); + } + + inline void ro_string:: + assign (const char* s, size_t size) + { + data_ = s; + size_ = size; + } + + inline void ro_string:: + assign (const string& s) + { + data_ = s.data (); + size_ = s.size (); + } + +#ifdef XSDE_STL + inline void ro_string:: + assign (const std::string& s) + { + data_ = s.c_str (); + size_ = s.size (); + } +#endif + + inline int ro_string:: + compare (const ro_string& str) const + { + return compare (str.data (), str.size ()); + } + + inline int ro_string:: + compare (const char* str) const + { + return compare (str, strlen (str)); + } + + inline int ro_string:: + compare (const char* str, size_t n) const + { + size_t s = size_ < n ? size_ : n; + + int r = s != 0 ? strncmp (data_, str, s) : 0; + + if (!r && size_ != n) + r = size_ < n ? -1 : 1; + + return r; + } + + inline int ro_string:: + compare (const string& s) const + { + return compare (s.data (), s.size ()); + } + +#ifdef XSDE_STL + inline int ro_string:: + compare (const std::string& str) const + { + return compare (str.c_str (), str.size ()); + } +#endif + + inline size_t ro_string:: + find (char c, size_type pos) const + { + for (; pos < size_; ++pos) + if (data_[pos] == c) + return pos; + + return npos; + } + + // operator == + // + + inline bool + operator== (const ro_string& a, const ro_string& b) + { + return a.compare (b) == 0; + } + + inline bool + operator== (const ro_string& a, const char* b) + { + return a.compare (b) == 0; + } + + inline bool + operator== (const char* a, const ro_string& b) + { + return b.compare (a) == 0; + } + + inline bool + operator== (const ro_string& a, const string& b) + { + return a.compare (b) == 0; + } + + inline bool + operator== (const string& a, const ro_string& b) + { + return b.compare (a) == 0; + } + +#ifdef XSDE_STL + inline bool + operator== (const ro_string& a, const std::string& b) + { + return a.compare (b) == 0; + } + + inline bool + operator== (const std::string& a, const ro_string& b) + { + return b.compare (a) == 0; + } +#endif + + + // operator != + // + + inline bool + operator!= (const ro_string& a, const ro_string& b) + { + return a.compare (b) != 0; + } + + inline bool + operator!= (const ro_string& a, const char* b) + { + return a.compare (b) != 0; + } + + inline bool + operator!= (const char* a, const ro_string& b) + { + return b.compare (a) != 0; + } + + inline bool + operator!= (const ro_string& a, const string& b) + { + return a.compare (b) != 0; + } + + inline bool + operator!= (const string& a, const ro_string& b) + { + return b.compare (a) != 0; + } + +#ifdef XSDE_STL + inline bool + operator!= (const ro_string& a, const std::string& b) + { + return a.compare (b) != 0; + } + + inline bool + operator!= (const std::string& a, const ro_string& b) + { + return b.compare (a) != 0; + } +#endif + + + // operator < + // + + inline bool + operator< (const ro_string& l, const ro_string& r) + { + return l.compare (r) < 0; + } + + inline bool + operator< (const ro_string& l, const char* r) + { + return l.compare (r) < 0; + } + + inline bool + operator< (const char* l, const ro_string& r) + { + return r.compare (l) > 0; + } + +#ifdef XSDE_STL + inline bool + operator< (const ro_string& l, const std::string& r) + { + return l.compare (r) < 0; + } + + inline bool + operator< (const std::string& l, const ro_string& r) + { + return r.compare (l) > 0; + } +#endif + + + // operator > + // + + inline bool + operator> (const ro_string& l, const ro_string& r) + { + return l.compare (r) > 0; + } + + inline bool + operator> (const ro_string& l, const char* r) + { + return l.compare (r) > 0; + } + + inline bool + operator> (const char* l, const ro_string& r) + { + return r.compare (l) < 0; + } + +#ifdef XSDE_STL + inline bool + operator> (const ro_string& l, const std::string& r) + { + return l.compare (r) > 0; + } + + inline bool + operator> (const std::string& l, const ro_string& r) + { + return r.compare (l) < 0; + } +#endif + + + // operator <= + // + + inline bool + operator<= (const ro_string& l, const ro_string& r) + { + return l.compare (r) <= 0; + } + + inline bool + operator<= (const ro_string& l, const char* r) + { + return l.compare (r) <= 0; + } + + inline bool + operator<= (const char* l, const ro_string& r) + { + return r.compare (l) >= 0; + } + +#ifdef XSDE_STL + inline bool + operator<= (const ro_string& l, const std::string& r) + { + return l.compare (r) <= 0; + } + + inline bool + operator<= (const std::string& l, const ro_string& r) + { + return r.compare (l) >= 0; + } +#endif + + + // operator>= + // + + inline bool + operator>= (const ro_string& l, const ro_string& r) + { + return l.compare (r) >= 0; + } + + inline bool + operator>= (const ro_string& l, const char* r) + { + return l.compare (r) >= 0; + } + + inline bool + operator>= (const char* l, const ro_string& r) + { + return r.compare (l) <= 0; + } + +#ifdef XSDE_STL + inline bool + operator>= (const ro_string& l, const std::string& r) + { + return l.compare (r) >= 0; + } + + inline bool + operator>= (const std::string& l, const ro_string& r) + { + return r.compare (l) <= 0; + } +#endif + + // operator += + // +#ifdef XSDE_STL + inline std::string& + operator+= (std::string& l, const ro_string& r) + { + l.append (r.data (), r.size ()); + return l; + } +#endif + } +} diff --git a/libxsde/xsde/cxx/schema-error.cxx b/libxsde/xsde/cxx/schema-error.cxx new file mode 100644 index 0000000..7ff8b39 --- /dev/null +++ b/libxsde/xsde/cxx/schema-error.cxx @@ -0,0 +1,69 @@ +// file : xsde/cxx/schema-error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + static const char* const text_[] = + { + "no error", + "expected attribute not encountered", + "unexpected attribute encountered", + "expected element not encountered", + "unexpected element encountered", + "unexpected characters encountered", + "invalid boolean value", + "invalid byte value", + "invalid unsignedByte value", + "invalid short value", + "invalid unsignedShort value", + "invalid int value", + "invalid unsignedInt value", + "invalid long value", + "invalid unsignedLong value", + "invalid integer value", + "invalid negativeInteger value", + "invalid nonPositiveInteger value", + "invalid positiveInteger value", + "invalid nonNegativeInteger value", + "invalid float value", + "invalid double value", + "invalid decimal value", + "invalid normalizedString value", + "invalid token value", + "invalid Name value", + "invalid NMTOKEN value", + "invalid NMTOKENS value", + "invalid NCName value", + "invalid ID value", + "invalid IDREF value", + "invalid IDREFS value", + "invalid language value", + "invalid QName value", + "invalid base64Binary value", + "invalid hexBinary value", + "invalid gDay value", + "invalid gMonth value", + "invalid gYear value", + "invalid gMonthDay value", + "invalid gYearMonth value", + "invalid date value", + "invalid time value", + "invalid dateTime value", + "invalid duration value", + "invalid xsi:type attribute", + "dynamic and static types are not related by inheritance" + }; + + const char* schema_error:: + text (value v) + { + return text_[v]; + } + } +} diff --git a/libxsde/xsde/cxx/schema-error.hxx b/libxsde/xsde/cxx/schema-error.hxx new file mode 100644 index 0000000..b8bf1b1 --- /dev/null +++ b/libxsde/xsde/cxx/schema-error.hxx @@ -0,0 +1,84 @@ +// file : xsde/cxx/schema-error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SCHEMA_ERROR_HXX +#define XSDE_CXX_SCHEMA_ERROR_HXX + +namespace xsde +{ + namespace cxx + { + struct schema_error + { + enum value + { + none, + expected_attribute, + unexpected_attribute, + expected_element, + unexpected_element, + unexpected_characters, + invalid_boolean_value, + invalid_byte_value, + invalid_unsigned_byte_value, + invalid_short_value, + invalid_unsigned_short_value, + invalid_int_value, + invalid_unsigned_int_value, + invalid_long_value, + invalid_unsigned_long_value, + invalid_integer_value, + invalid_negative_integer_value, + invalid_non_positive_integer_value, + invalid_positive_integer_value, + invalid_non_negative_integer_value, + invalid_float_value, + invalid_double_value, + invalid_decimal_value, + invalid_normalized_string_value, + invalid_token_value, + invalid_name_value, + invalid_nmtoken_value, + invalid_nmtokens_value, + invalid_ncname_value, + invalid_id_value, + invalid_idref_value, + invalid_idrefs_value, + invalid_language_value, + invalid_qname_value, + invalid_base64_binary_value, + invalid_hex_binary_value, + invalid_gday_value, + invalid_gmonth_value, + invalid_gyear_value, + invalid_gmonth_day_value, + invalid_gyear_month_value, + invalid_date_value, + invalid_time_value, + invalid_date_time_value, + invalid_duration_value, + invalid_xsi_type, + not_derived + }; + + schema_error (value v); + + operator value () const + { + return v_; + } + + static const char* + text (value); + + private: + value v_; + }; + } +} + +#include + +#endif // XSDE_CXX_SCHEMA_ERROR_HXX diff --git a/libxsde/xsde/cxx/schema-error.ixx b/libxsde/xsde/cxx/schema-error.ixx new file mode 100644 index 0000000..e63e556 --- /dev/null +++ b/libxsde/xsde/cxx/schema-error.ixx @@ -0,0 +1,16 @@ +// file : xsde/cxx/schema-error.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline schema_error:: + schema_error (value v) + : v_ (v) + { + } + } +} diff --git a/libxsde/xsde/cxx/sequence-base.cxx b/libxsde/xsde/cxx/sequence-base.cxx new file mode 100644 index 0000000..03f33f5 --- /dev/null +++ b/libxsde/xsde/cxx/sequence-base.cxx @@ -0,0 +1,135 @@ +// file : xsde/cxx/sequence-base.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy, memmove + +#include + +namespace xsde +{ + namespace cxx + { + void sequence_base:: + erase_ (void* vp, size_t es, move_forward_func mv) + { + char* p = static_cast (vp); + char* d = static_cast (data_); + + if (mv) + mv (p, size_ - 1 - (p - d) / es); + else + memmove (p, p + es, (size_ - 1) * es - (p - d)); + + --size_; + } + +#ifdef XSDE_EXCEPTIONS + struct guard + { + guard (void* p) : p_ (p) {} + ~guard () {if (p_) operator delete (p_);} + + void + release () { p_ = 0; } + + private: + void* p_; + }; + + void sequence_base:: + grow_ (size_t n, size_t es, move_func mv) + { + size_t c = n == 0 ? (capacity_ != 0 ? capacity_ * 2 : 8) : n; + void* d = operator new (c * es); + + if (size_) + { + if (mv) + { + guard g (d); + mv (d, data_, size_); + g.release (); + } + else + memcpy (d, data_, size_ * es); + } + + if (data_) + operator delete (data_); + + data_ = d; + capacity_ = c; + } + + void* sequence_base:: + insert_ (void* vp, size_t es, move_func mv, move_backward_func mvb) + { + size_t i = static_cast (vp) - static_cast (data_); + + if (capacity_ < size_ + 1) + grow_ (0, es, mv); + + char* d = static_cast (data_); + char* p = d + i; + + if (mvb) + mvb (p, size_ - i / es, size_); // increments size_ + else + { + memmove (p + es, p, size_ * es - i); + ++size_; + } + + return p; + } +#else + sequence_base::error sequence_base:: + grow_ (size_t n, size_t es, move_func mv) + { + size_t c = n == 0 ? (capacity_ != 0 ? capacity_ * 2 : 8) : n; + void* d = operator new (c * es); + + if (d == 0) + return error_no_memory; + + if (size_) + { + if (mv) + mv (d, data_, size_); + else + memcpy (d, data_, size_ * es); + } + + if (data_) + operator delete (data_); + + data_ = d; + capacity_ = c; + + return error_none; + } + + void* sequence_base:: + insert_ (void* vp, size_t es, move_func mv, move_backward_func mvb) + { + size_t i = static_cast (vp) - static_cast (data_); + + if (capacity_ < size_ + 1 && grow_ (0, es, mv) != error_none) + return 0; + + char* d = static_cast (data_); + char* p = d + i; + + if (mvb) + mvb (p, size_ - i / es); + else + memmove (p + es, p, size_ * es - i); + + ++size_; + return p; + } +#endif + } +} diff --git a/libxsde/xsde/cxx/sequence-base.hxx b/libxsde/xsde/cxx/sequence-base.hxx new file mode 100644 index 0000000..537ee7c --- /dev/null +++ b/libxsde/xsde/cxx/sequence-base.hxx @@ -0,0 +1,83 @@ +// file : xsde/cxx/sequence-base.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SEQUENCE_BASE_HXX +#define XSDE_CXX_SEQUENCE_BASE_HXX + +#include + +#include // size_t + +namespace xsde +{ + namespace cxx + { + // + // + class sequence_base + { + public: +#ifndef XSDE_EXCEPTIONS + enum error + { + error_none, + error_no_memory + }; +#endif + + private: + sequence_base (sequence_base&); + sequence_base& operator= (sequence_base&); + + public: + ~sequence_base (); + sequence_base (); + + bool + empty () const; + + size_t + size () const; + + size_t + capacity () const; + + protected: + typedef void (*move_func) (void*, void*, size_t); + typedef void (*move_forward_func) (void*, size_t); +#ifdef XSDE_EXCEPTIONS + typedef void (*move_backward_func) (void*, size_t, size_t&); +#else + typedef void (*move_backward_func) (void*, size_t); +#endif + + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + grow_ (size_t n, size_t element_size, move_func); + + void + erase_ (void*, size_t element_size, move_forward_func); + + void* + insert_ (void*, size_t element_size, move_func, move_backward_func); + + void + swap_ (sequence_base&); + + protected: + void* data_; + size_t size_; + size_t capacity_; + }; + } +} + +#include + +#endif // XSDE_CXX_SEQUENCE_BASE_HXX diff --git a/libxsde/xsde/cxx/sequence-base.ixx b/libxsde/xsde/cxx/sequence-base.ixx new file mode 100644 index 0000000..214070d --- /dev/null +++ b/libxsde/xsde/cxx/sequence-base.ixx @@ -0,0 +1,57 @@ +// file : xsde/cxx/sequence-base.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline sequence_base:: + sequence_base () + : data_ (0), size_ (0), capacity_ (0) + { + } + + inline sequence_base:: + ~sequence_base () + { + if (data_) + operator delete (data_); + } + + inline bool sequence_base:: + empty () const + { + return size_ == 0; + } + + inline size_t sequence_base:: + size () const + { + return size_; + } + + inline size_t sequence_base:: + capacity () const + { + return capacity_; + } + + inline void sequence_base:: + swap_ (sequence_base& x) + { + void* d = x.data_; + size_t s = x.size_; + size_t c = x.capacity_; + + x.data_ = data_; + x.size_ = size_; + x.capacity_ = capacity_; + + data_ = d; + size_ = s; + capacity_ = c; + } + } +} diff --git a/libxsde/xsde/cxx/serializer/context.cxx b/libxsde/xsde/cxx/serializer/context.cxx new file mode 100644 index 0000000..f340e7a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/context.cxx @@ -0,0 +1,107 @@ +// file : xsde/cxx/serializer/context.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#ifdef XSDE_EXCEPTIONS +# include // std::bad_alloc +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { +#ifdef XSDE_POLYMORPHIC +#ifdef XSDE_EXCEPTIONS + void context:: +#else + bool context:: +#endif + set_type (const char* type) + { + ro_string t (type); + const char* prefix = 0; + + size_t pos = t.find (' '); + + if (pos != ro_string::npos) + { + prefix = lookup_namespace_prefix (type + pos + 1); + + //@@ TODO: what if prefix is not found? + // +#ifndef XSDE_EXCEPTIONS + if (prefix == 0) + return false; +#endif + if (*prefix == '\0') + prefix = 0; + } + +#ifdef XSDE_EXCEPTIONS + start_attribute ("http://www.w3.org/2001/XMLSchema-instance", "type"); + + if (prefix) + { + characters (prefix); + characters (":"); + } + + characters (type, pos != ro_string::npos ? pos : t.size ()); + end_attribute (); +#else + if (!start_attribute ( + "http://www.w3.org/2001/XMLSchema-instance", "type")) + return false; + + if (prefix) + { + if (!characters (prefix) || !characters (":")) + return false; + } + + if (!characters (type, pos != ro_string::npos ? pos : t.size ()) || + !end_attribute ()) + return false; + + return true; +#endif + } +#endif // XSDE_POLYMORPHIC + +#ifdef XSDE_EXCEPTIONS + void context:: + throw_xml_error (genx::xml_error e) + { + switch (e) + { + case GENX_ALLOC_FAILED: + { + throw std::bad_alloc (); + } + case GENX_IO_ERROR: + { + // This should never happen with consistent exception + // handling usage since the write/flush functions + // throw exceptions to indicate write failures. + // + throw xml (e); + } + default: + { + throw xml (e); + } + } + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/serializer/context.hxx b/libxsde/xsde/cxx/serializer/context.hxx new file mode 100644 index 0000000..fe817eb --- /dev/null +++ b/libxsde/xsde/cxx/serializer/context.hxx @@ -0,0 +1,261 @@ +// file : xsde/cxx/serializer/context.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_CONTEXT_HXX +#define XSDE_CXX_SERIALIZER_CONTEXT_HXX + +#include + +#include // size_t + +#include + +#ifndef XSDE_EXCEPTIONS +# include +#endif + +#include + +#ifdef XSDE_SERIALIZER_VALIDATION +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + class context + { + public: + context (genxWriter xml_serializer); + + public: + genxWriter + xml_serializer (); + +#ifdef XSDE_POLYMORPHIC + public: + // Set/get the dynamic serializer type id (as opaque const void*) + // in case of polymorphic serialization. If type id is not set, + // static type is assumed. + // + void + type_id (const void*); + + const void* + type_id (); +#endif + + public: +#ifdef XSDE_EXCEPTIONS + void + start_element (const char* name); + + void + start_element (const char* ns, const char* name); + + void + end_element (); + + void + start_attribute (const char* name); + + void + start_attribute (const char* ns, const char* name); + + void + end_attribute (); + + void + attribute (const char* name, const char* value); + + void + attribute (const char* ns, const char* name, const char* value); + + void + characters (const char*); + + void + characters (const char*, size_t); + + void + declare_namespace (const char* ns, const char* prefix); + + void + declare_default_namespace (const char* ns); + + void + clear_default_namespace (); + + const char* + lookup_namespace_prefix (const char* ns); + +#ifdef XSDE_POLYMORPHIC + void + set_type (const char* type); +#endif +#else + bool + start_element (const char* name); + + bool + start_element (const char* ns, const char* name); + + bool + end_element (); + + bool + start_attribute (const char* name); + + bool + start_attribute (const char* ns, const char* name); + + bool + end_attribute (); + + bool + attribute (const char* name, const char* value); + + bool + attribute (const char* ns, const char* name, const char* value); + + bool + characters (const char*); + + bool + characters (const char*, size_t); + + bool + declare_namespace (const char* ns, const char* prefix); + + bool + declare_default_namespace (const char* ns); + + bool + clear_default_namespace (); + + const char* + lookup_namespace_prefix (const char* ns); + +#ifdef XSDE_POLYMORPHIC + bool + set_type (const char* type); +#endif +#endif + + // Error handling via exceptions. + // + +#ifdef XSDE_EXCEPTIONS + public: + void + throw_xml_error (genx::xml_error); +#endif + + // Error handling via codes. + // + + // Application error. + // +#ifndef XSDE_EXCEPTIONS + public: + int + app_error () const; + + void + app_error (int); +#endif + + // Schema error. + // +#ifdef XSDE_SERIALIZER_VALIDATION + public: + typedef cxx::schema_error::value schema_error_t; + + schema_error_t + schema_error () const; + + void + schema_error (schema_error_t); +#endif + + // XML error. + // +#ifndef XSDE_EXCEPTIONS + public: + typedef genx::xml_error xml_error_t; + + xml_error_t + xml_error () const; + + void + xml_error (xml_error_t); +#endif + + // System error. + // +#ifndef XSDE_EXCEPTIONS + public: + typedef cxx::sys_error::value sys_error_t; + + sys_error_t + sys_error () const; + + void + sys_error (sys_error_t); +#endif + + // Implementation details. + // +#if defined(XSDE_SERIALIZER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + public: + enum error_type_t + { + error_none = 0, + error_app, + error_schema, + error_xml, + error_sys + }; + + error_type_t + error_type () const; + + protected: + error_type_t error_type_; + + union + { +#ifndef XSDE_EXCEPTIONS + int app; + xml_error_t xml; +#endif +#ifdef XSDE_SERIALIZER_VALIDATION + schema_error_t schema; +#endif +#ifndef XSDE_EXCEPTIONS + sys_error_t sys; +#endif + } error_code_; + +#endif // XSDE_SERIALIZER_VALIDATION || !XSDE_EXCEPTIONS + + protected: + genxWriter xml_serializer_; + +#ifdef XSDE_POLYMORPHIC + const void* type_id_; +#endif + + }; + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_CONTEXT_HXX diff --git a/libxsde/xsde/cxx/serializer/context.ixx b/libxsde/xsde/cxx/serializer/context.ixx new file mode 100644 index 0000000..d3e578d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/context.ixx @@ -0,0 +1,449 @@ +// file : xsde/cxx/serializer/context.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + inline context:: + context (genxWriter xml_serializer) + : xml_serializer_ (xml_serializer) + { +#if defined(XSDE_SERIALIZER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + error_type_ = error_none; +#endif + } + + inline genxWriter context:: + xml_serializer () + { + return xml_serializer_; + } + +#ifdef XSDE_POLYMORPHIC + inline void context:: + type_id (const void* ti) + { + type_id_ = ti; + } + + inline const void* context:: + type_id () + { + return type_id_; + } +#endif + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + start_element (const char* name) + { + genxStatus e = genxStartElementLiteral ( + xml_serializer_, + 0, + reinterpret_cast (name)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + start_element (const char* ns, const char* name) + { + genxStatus e = genxStartElementLiteral ( + xml_serializer_, + reinterpret_cast (ns), + reinterpret_cast (name)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + end_element () + { + genxStatus e = genxEndElement (xml_serializer_); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + start_attribute (const char* name) + { + genxStatus e = genxStartAttributeLiteral ( + xml_serializer_, + 0, + reinterpret_cast (name)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + start_attribute (const char* ns, const char* name) + { + genxStatus e = genxStartAttributeLiteral ( + xml_serializer_, + reinterpret_cast (ns), + reinterpret_cast (name)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + end_attribute () + { + genxStatus e = genxEndAttribute (xml_serializer_); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + attribute (const char* name, const char* value) + { + genxStatus e = genxAddAttributeLiteral ( + xml_serializer_, + 0, + reinterpret_cast (name), + reinterpret_cast (value)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + attribute (const char* ns, const char* name, const char* value) + { + genxStatus e = genxAddAttributeLiteral ( + xml_serializer_, + reinterpret_cast (ns), + reinterpret_cast (name), + reinterpret_cast (value)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + characters (const char* s) + { + genxStatus e = genxAddText ( + xml_serializer_, + reinterpret_cast (s)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + characters (const char* s, size_t n) + { + genxStatus e = genxAddCountedText ( + xml_serializer_, + reinterpret_cast (s), + static_cast (n)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + declare_namespace (const char* ns, const char* prefix) + { + genxStatus e = genxAddNamespaceLiteral ( + xml_serializer_, + reinterpret_cast (ns), + reinterpret_cast (prefix)); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + declare_default_namespace (const char* ns) + { + genxStatus e = genxAddNamespaceLiteral ( + xml_serializer_, + reinterpret_cast (ns), + reinterpret_cast ("")); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // +#ifdef XSDE_EXCEPTIONS + inline void context:: +#else + inline bool context:: +#endif + clear_default_namespace () + { + genxStatus e = genxUnsetDefaultNamespace (xml_serializer_); + +#ifdef XSDE_EXCEPTIONS + if (e != GENX_SUCCESS) + throw_xml_error (e); +#else + if (e != GENX_SUCCESS) + xml_error (e); + + return e == GENX_SUCCESS; +#endif + } + + // + // + inline const char* context:: + lookup_namespace_prefix (const char* ns) + { + genxStatus e; + genxNamespace gns = genxDeclareNamespace ( + xml_serializer_, reinterpret_cast (ns), 0, &e); + + if (e != GENX_SUCCESS) + { +#ifdef XSDE_EXCEPTIONS + throw_xml_error (e); +#else + xml_error (e); +#endif + return 0; + } + + return reinterpret_cast ( + genxGetNamespacePrefix (gns)); + } + + // + // +#ifndef XSDE_EXCEPTIONS + inline int context:: + app_error () const + { + return error_code_.app; + } + + inline void context:: + app_error (int e) + { + error_type_ = error_app; + error_code_.app = e; + } + + inline void context:: + sys_error (sys_error_t e) + { + error_type_ = error_sys; + error_code_.sys = e; + } + + inline context::sys_error_t context:: + sys_error () const + { + return error_code_.sys; + } + + inline void context:: + xml_error (xml_error_t e) + { + error_type_ = error_xml; + error_code_.xml = e; + } + + inline context::xml_error_t context:: + xml_error () const + { + return error_code_.xml; + } +#endif + +#ifdef XSDE_SERIALIZER_VALIDATION + inline context::schema_error_t context:: + schema_error () const + { + return error_code_.schema; + } + + inline void context:: + schema_error (schema_error_t e) + { + error_type_ = error_schema; + error_code_.schema = e; + } +#endif + +#if defined(XSDE_SERIALIZER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + inline context::error_type_t context:: + error_type () const + { + return error_type_; + } +#endif + + } + } +} diff --git a/libxsde/xsde/cxx/serializer/elements.cxx b/libxsde/xsde/cxx/serializer/elements.cxx new file mode 100644 index 0000000..d20601e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/elements.cxx @@ -0,0 +1,122 @@ +// file : xsde/cxx/serializer/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // serializer_base + // + serializer_base:: + ~serializer_base () + { + } + + void serializer_base:: + _pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_pre (); +#endif + } + + void serializer_base:: + _serialize_attributes () + { + } + + void serializer_base:: + _serialize_content () + { + } + + void serializer_base:: + _post () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_post (); +#endif + } + + void serializer_base:: + post () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->post (); +#endif + } + + void serializer_base:: + _pre_impl (context& c) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + assert (parent_ == 0); + + // Set the parent_ pointers in the tied-in implementations. + // + _set_parent_chain (); +#endif + ++depth_; + context_ = &c; + + _pre (); + } + + void serializer_base:: + _post_impl () + { +#if defined(XSDE_SERIALIZER_VALIDATION) || !defined(XSDE_EXCEPTIONS) + if (!context_->error_type ()) +#endif + _post (); + + if (--depth_ == 0) + context_ = 0; + } + +#ifdef XSDE_POLYMORPHIC + const char* serializer_base:: + _dynamic_type () const + { + return 0; + } +#endif + + void serializer_base:: + _reset () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (impl_) + impl_->_reset (); +#endif + +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif + context_ = 0; + depth_ = 0; + } + +#if defined (XSDE_REUSE_STYLE_TIEIN) && !defined (XSDE_EXCEPTIONS) + const serializer_base* serializer_base:: + _ultimate_impl () const + { + const serializer_base* s = impl_; + for (; s->impl_ != 0; s = s->impl_) /*noop*/; + return s; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/serializer/elements.hxx b/libxsde/xsde/cxx/serializer/elements.hxx new file mode 100644 index 0000000..f6c354a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/elements.hxx @@ -0,0 +1,302 @@ +// file : xsde/cxx/serializer/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_ELEMENTS_HXX +#define XSDE_CXX_SERIALIZER_ELEMENTS_HXX + +#include + +#include // size_t + +#include + +#ifndef XSDE_EXCEPTIONS +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // pre() and post() are overridable pre/post callbacks, i.e., the + // derived serializer can override them without calling the base + // version. _pre() and _post() are not overridable pre/post callbacks + // in the sense that the derived serializer may override them but + // has to call the base version. The call sequence is as shown below: + // + // pre (arg) + // _pre () + // _post () + // post () + // + struct serializer_base + { + virtual + ~serializer_base (); + + serializer_base (); + +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base (serializer_base* impl, void*); +#endif + + // The pre() signature varies depending on the serializer argument + // type. + // + + virtual void + _pre (); + + virtual void + _serialize_attributes (); + + virtual void + _serialize_content (); + + virtual void + _post (); + + virtual void + post (); + + // Implementation callbacks for _pre and _post. The _pre and _post + // callbacks should never be called directly. Instead, the *_impl + // versions should be used. The _pre_impl and _post_impl functions + // will eventually call _pre and _post respectively. + // + virtual void + _pre_impl (context&); + + virtual void + _post_impl (); + +#ifdef XSDE_POLYMORPHIC + public: + // Dynamic type in the form " " with + // the space and namespace part absent if the type does + // not have a namespace. + // + virtual const char* + _dynamic_type () const; +#endif + + public: + context& + _context (); + + // The XML generation functions below can only be called starting + // from _pre() and ending with _post(). Because namespace declarations + // should come after the start_element and before any attributes, + // _pre is the appropriate place to call the namespace declaration + // functions. If exceptions are disabled, these functions return + // true on success and false otherwise. + // + // The set_type() function sets the xsi:type attribute. Its argument + // is the type id in the form " " with the space + // and namespace part absent if the type does not have a namespace. + // +#ifdef XSDE_EXCEPTIONS + void + _start_element (const char* name); + + void + _start_element (const char* ns, const char* name); + + void + _end_element (); + + void + _start_attribute (const char* name); + + void + _start_attribute (const char* ns, const char* name); + + void + _end_attribute (); + + void + _attribute (const char* name, const char* value); + + void + _attribute (const char* ns, const char* name, const char* value); + + void + _characters (const char*); + + void + _characters (const char*, size_t); + + void + _declare_namespace (const char* ns, const char* prefix); + + void + _declare_default_namespace (const char* ns); + + void + _clear_default_namespace (); + + const char* + _lookup_namespace_prefix (const char* ns); + +#ifdef XSDE_POLYMORPHIC + void + _set_type (const char* type); +#endif +#else + bool + _start_element (const char* name); + + bool + _start_element (const char* ns, const char* name); + + bool + _end_element (); + + bool + _start_attribute (const char* name); + + bool + _start_attribute (const char* ns, const char* name); + + bool + _end_attribute (); + + bool + _attribute (const char* name, const char* value); + + bool + _attribute (const char* ns, const char* name, const char* value); + + bool + _characters (const char*); + + bool + _characters (const char*, size_t); + + bool + _declare_namespace (const char* ns, const char* prefix); + + bool + _declare_default_namespace (const char* ns); + + bool + _clear_default_namespace (); + + const char* + _lookup_namespace_prefix (const char* ns); + +#ifdef XSDE_POLYMORPHIC + bool + _set_type (const char* type); +#endif +#endif + // Reset the serializer state after an error. + // + virtual void + _reset (); + + // Error handling via codes. If the error is set while serializer + // is in the context, the error is set in the context, instead + // of the serializer. Since pre() and post() calls are not in + // context, the serializer stores application and system errors + // locally for this case. + // + +#ifndef XSDE_EXCEPTIONS + public: + error + _error () const; + + // Set application error. + // + void + _app_error (int); + + int + _app_error () const; +#endif + + // Schema error. + // +#ifdef XSDE_SERIALIZER_VALIDATION + public: + void + _schema_error (context::schema_error_t); +#endif + + // XML error. + // +#ifndef XSDE_EXCEPTIONS + public: + void + _xml_error (context::xml_error_t); +#endif + + // System error. + // +#ifndef XSDE_EXCEPTIONS + public: + context::sys_error_t + _sys_error () const; + + void + _sys_error (context::sys_error_t); +#endif + + // Implementation. + // +#ifndef XSDE_EXCEPTIONS + public: + enum error_type_t + { + error_none = 0, + error_app, + error_sys + }; + + error_type_t + _error_type () const; + + void + _copy_error (context&) const; + + protected: + error_type_t error_type_; + + union + { + int app; + context::sys_error_t sys; + } error_code_; +#endif + + protected: + bool resetting_; + context* context_; + size_t depth_; + +#ifdef XSDE_REUSE_STYLE_TIEIN + protected: + serializer_base* parent_; + serializer_base* impl_; + + void + _set_parent_chain (); + +#ifndef XSDE_EXCEPTIONS + const serializer_base* + _ultimate_impl () const; +#endif +#endif + }; + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_ELEMENTS_HXX diff --git a/libxsde/xsde/cxx/serializer/elements.ixx b/libxsde/xsde/cxx/serializer/elements.ixx new file mode 100644 index 0000000..ead289a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/elements.ixx @@ -0,0 +1,569 @@ +// file : xsde/cxx/serializer/elements.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + inline serializer_base:: + serializer_base () + : resetting_ (false), context_ (0), depth_ (0) + { +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif +#ifdef XSDE_REUSE_STYLE_TIEIN + parent_ = 0; + impl_ = 0; +#endif + } + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline serializer_base:: + serializer_base (serializer_base* impl, void*) + : resetting_ (false), context_ (0), depth_ (0) + { +#ifndef XSDE_EXCEPTIONS + error_type_ = error_none; +#endif + parent_ = 0; + impl_ = impl; + } +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + inline void serializer_base:: + _set_parent_chain () + { + if (impl_ && impl_->parent_ == 0) + { + for (serializer_base* s = impl_; s != 0; s = s->impl_) + s->parent_ = this; + } + } +#endif + + inline context& serializer_base:: + _context () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + return *(parent_ ? parent_->context_ : context_); +#else + return *context_; +#endif + } + +#ifdef XSDE_EXCEPTIONS + inline void serializer_base:: + _start_element (const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->start_element (name); + } + + inline void serializer_base:: + _start_element (const char* ns, const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->start_element (ns, name); + } + + inline void serializer_base:: + _end_element () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->end_element (); + } + + inline void serializer_base:: + _start_attribute (const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->start_attribute (name); + } + + inline void serializer_base:: + _start_attribute (const char* ns, const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->start_attribute (ns, name); + } + + inline void serializer_base:: + _end_attribute () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->end_attribute (); + } + + inline void serializer_base:: + _attribute (const char* name, const char* value) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->attribute (name, value); + } + + inline void serializer_base:: + _attribute (const char* ns, const char* name, const char* value) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->attribute (ns, name, value); + } + + inline void serializer_base:: + _characters (const char* str) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->characters (str); + } + + inline void serializer_base:: + _characters (const char* str, size_t n) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->characters (str, n); + } + + inline void serializer_base:: + _declare_namespace (const char* ns, const char* p) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->declare_namespace (ns, p); + } + + inline void serializer_base:: + _declare_default_namespace (const char* ns) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->declare_default_namespace (ns); + } + + inline void serializer_base:: + _clear_default_namespace () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->clear_default_namespace (); + } + + inline const char* serializer_base:: + _lookup_namespace_prefix (const char* ns) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->lookup_namespace_prefix (ns); + } + +#ifdef XSDE_POLYMORPHIC + inline void serializer_base:: + _set_type (const char* type) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->set_type (type); + } +#endif + +#else // XSDE_EXCEPTIONS + + inline bool serializer_base:: + _start_element (const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->start_element (name); + } + + inline bool serializer_base:: + _start_element (const char* ns, const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->start_element (ns, name); + } + + inline bool serializer_base:: + _end_element () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->end_element (); + } + + inline bool serializer_base:: + _start_attribute (const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->start_attribute (name); + } + + inline bool serializer_base:: + _start_attribute (const char* ns, const char* name) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->start_attribute (ns, name); + } + + inline bool serializer_base:: + _end_attribute () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->end_attribute (); + } + + inline bool serializer_base:: + _attribute (const char* name, const char* value) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->attribute (name, value); + } + + inline bool serializer_base:: + _attribute (const char* ns, const char* name, const char* value) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->attribute (ns, name, value); + } + + inline bool serializer_base:: + _characters (const char* str) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->characters (str); + } + + inline bool serializer_base:: + _characters (const char* str, size_t n) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->characters (str, n); + } + + inline bool serializer_base:: + _declare_namespace (const char* ns, const char* p) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->declare_namespace (ns, p); + } + + inline bool serializer_base:: + _declare_default_namespace (const char* ns) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->declare_default_namespace (ns); + } + + inline bool serializer_base:: + _clear_default_namespace () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->clear_default_namespace (); + } + + inline const char* serializer_base:: + _lookup_namespace_prefix (const char* ns) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->lookup_namespace_prefix (ns); + } + +#ifdef XSDE_POLYMORPHIC + inline bool serializer_base:: + _set_type (const char* type) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + return s->context_->set_type (type); + } +#endif + +#endif // !XSDE_EXCEPTIONS + + // Error handling. + // +#ifndef XSDE_EXCEPTIONS + inline error serializer_base:: + _error () const + { + // Unlike context, which is stored in the top-level + // serializer, error state is stored in the "bottom- + // level" implementation. It is done this way since the + // error handling mechanism can be used in constructors + // which would otherwise require passing the pointer to + // parent serializer to each implementation's c-tor. + // +#ifdef XSDE_REUSE_STYLE_TIEIN + const serializer_base* s = !impl_ ? this : _ultimate_impl (); +#else + const serializer_base* s = this; +#endif + switch (s->error_type_) + { + case error_sys: + { + return error (s->error_code_.sys); + } + case error_app: + { + return error (s->error_code_.app); + } + default: + { + return error (); + } + } + } + + inline void serializer_base:: + _app_error (int e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + + if (s->context_ != 0) + { + s->context_->app_error (e); + } + else + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (!impl_) + s = this; + else + for (s = impl_; s->impl_ != 0; s = s->impl_) /*noop*/; +#endif + s->error_type_ = error_app; + s->error_code_.app = e; + } + } + + inline int serializer_base:: + _app_error () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const serializer_base* s = !impl_ ? this : _ultimate_impl (); +#else + const serializer_base* s = this; +#endif + return s->error_code_.app; + } + + inline void serializer_base:: + _sys_error (context::sys_error_t e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + if (s->context_ != 0) + { + s->context_->sys_error (e); + } + else + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (!impl_) + s = this; + else + for (s = impl_; s->impl_ != 0; s = s->impl_) /*noop*/; +#endif + s->error_type_ = error_sys; + s->error_code_.sys = e; + } + } + + inline context::sys_error_t serializer_base:: + _sys_error () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const serializer_base* s = !impl_ ? this : _ultimate_impl (); +#else + const serializer_base* s = this; +#endif + return s->error_code_.sys; + } + + inline void serializer_base:: + _xml_error (context::xml_error_t e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->xml_error (e); + } + + inline serializer_base::error_type_t serializer_base:: + _error_type () const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const serializer_base* s = !impl_ ? this : _ultimate_impl (); +#else + const serializer_base* s = this; +#endif + return s->error_type_; + } + + inline void serializer_base:: + _copy_error (context& ctx) const + { +#ifdef XSDE_REUSE_STYLE_TIEIN + const serializer_base* s = !impl_ ? this : _ultimate_impl (); +#else + const serializer_base* s = this; +#endif + switch (s->error_type_) + { + case error_app: + { + ctx.app_error (s->error_code_.app); + break; + } + case error_sys: + { + ctx.sys_error (s->error_code_.sys); + break; + } + default: + break; + } + } +#endif // XSDE_EXCEPTIONS + +#ifdef XSDE_SERIALIZER_VALIDATION + inline void serializer_base:: + _schema_error (context::schema_error_t e) + { +#ifdef XSDE_REUSE_STYLE_TIEIN + serializer_base* s = parent_ ? parent_ : this; +#else + serializer_base* s = this; +#endif + s->context_->schema_error (e); + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/serializer/error.cxx b/libxsde/xsde/cxx/serializer/error.cxx new file mode 100644 index 0000000..7ee1981 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/error.cxx @@ -0,0 +1,20 @@ +// file : xsde/cxx/serializer/error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + void error:: + true_ () + { + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/error.hxx b/libxsde/xsde/cxx/serializer/error.hxx new file mode 100644 index 0000000..62776e9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/error.hxx @@ -0,0 +1,121 @@ +// file : xsde/cxx/serializer/error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_ERROR_HXX +#define XSDE_CXX_SERIALIZER_ERROR_HXX + +#include +#include + +#include + +#ifdef XSDE_SERIALIZER_VALIDATION +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + using genx::xml_error; + + // This type is only used when C++ exceptions are not used. + // + struct error + { + enum error_type + { + none, + sys, + xml, + schema, + app + }; + + public: + error_type + type () const; + + // Returns true if there is an error so that you can write + // if (s.error ()) or if (error e = s.error ()). + // + typedef void (error::*bool_convertible) (); + operator bool_convertible () const; + + + // sys + // + public: + error (sys_error::value); + + sys_error + sys_code () const; + + const char* + sys_text () const; + + // xml + // + public: + error (xml_error); + + xml_error + xml_code () const; + + const char* + xml_text () const; + + + // schema + // +#ifdef XSDE_SERIALIZER_VALIDATION + public: + error (schema_error::value); + + schema_error + schema_code () const; + + const char* + schema_text () const; +#endif + + // app + // + public: + error (int app_code); + + int + app_code () const; + + + public: + error (); + + private: + void + true_ (); + + private: + error_type type_; + + union + { + sys_error::value sys; + xml_error xml; +#ifdef XSDE_SERIALIZER_VALIDATION + schema_error::value schema; +#endif + int app; + } code_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_ERROR_HXX diff --git a/libxsde/xsde/cxx/serializer/error.ixx b/libxsde/xsde/cxx/serializer/error.ixx new file mode 100644 index 0000000..73b2196 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/error.ixx @@ -0,0 +1,128 @@ +// file : xsde/cxx/serializer/error.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + inline + error::error_type error:: + type () const + { + return type_; + } + + inline + error:: + operator error::bool_convertible () const + { + return type_ != none ? &error::true_ : 0; + } + + // sys + // + + inline + error:: + error (sys_error::value e) + : type_ (sys) + { + code_.sys = e; + } + + inline + sys_error error:: + sys_code () const + { + return code_.sys; + } + + inline + const char* error:: + sys_text () const + { + return sys_error::text (code_.sys); + } + + // xml + // + inline + error:: + error (xml_error e) + : type_ (xml) + { + code_.xml = e; + } + + inline + xml_error error:: + xml_code () const + { + return code_.xml; + } + + inline + const char* error:: + xml_text () const + { + return genx::xml_error_text (code_.xml); + } + + // schema + // + +#ifdef XSDE_SERIALIZER_VALIDATION + inline + error:: + error (schema_error::value e) + : type_ (schema) + { + code_.schema = e; + } + + inline + schema_error error:: + schema_code () const + { + return code_.schema; + } + + inline + const char* error:: + schema_text () const + { + return schema_error::text (code_.schema); + } +#endif + + // app + // + + inline + error:: + error (int e) + : type_ (app) + { + code_.app = e; + } + + inline + int error:: + app_code () const + { + return code_.app; + } + + inline + error:: + error () + : type_ (none) + { + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/exceptions.cxx b/libxsde/xsde/cxx/serializer/exceptions.cxx new file mode 100644 index 0000000..b6ad765 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/exceptions.cxx @@ -0,0 +1,62 @@ +// file : xsde/cxx/serializer/exceptions.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // exception + // + +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream& os, const exception& e) + { + return os << e.text (); + } +#endif + + // xml + // + const char* xml:: + text () const + { + return genx::xml_error_text (code_); + } + + const char* xml:: + what () const throw () + { + return "xml error"; + } + + // schema + // +#ifdef XSDE_SERIALIZER_VALIDATION + const char* schema:: + text () const + { + return schema_error::text (code_); + } + + const char* schema:: + what () const throw () + { + return "schema error"; + } +#endif + } + } +} diff --git a/libxsde/xsde/cxx/serializer/exceptions.hxx b/libxsde/xsde/cxx/serializer/exceptions.hxx new file mode 100644 index 0000000..03c2243 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/exceptions.hxx @@ -0,0 +1,91 @@ +// file : xsde/cxx/serializer/exceptions.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_EXCEPTIONS_HXX +#define XSDE_CXX_SERIALIZER_EXCEPTIONS_HXX + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include // xsde::cxx::exception + +#ifdef XSDE_SERIALIZER_VALIDATION +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // exception + // + struct exception: xsde::cxx::exception + { + virtual const char* + text () const = 0; + }; + +#ifdef XSDE_IOSTREAM + std::ostream& + operator<< (std::ostream&, const exception&); +#endif + + + // xml + // + using genx::xml_error; + + struct xml: exception + { + xml (xml_error); + + xml_error + code () const; + + virtual const char* + text () const; + + virtual const char* + what () const throw (); + + private: + xml_error code_; + }; + + + // schema + // +#ifdef XSDE_SERIALIZER_VALIDATION + struct schema: exception + { + schema (schema_error); + + schema_error + code () const; + + virtual const char* + text () const; + + virtual const char* + what () const throw (); + + private: + schema_error code_; + }; +#endif + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_EXCEPTIONS_HXX diff --git a/libxsde/xsde/cxx/serializer/exceptions.ixx b/libxsde/xsde/cxx/serializer/exceptions.ixx new file mode 100644 index 0000000..1f81c47 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/exceptions.ixx @@ -0,0 +1,44 @@ +// file : xsde/cxx/serializer/exceptions.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // xml + // + inline xml:: + xml (xml_error code) + : code_ (code) + { + } + + inline xml_error xml:: + code () const + { + return code_; + } + + // schema + // +#ifdef XSDE_SERIALIZER_VALIDATION + inline schema:: + schema (schema_error code) + : code_ (code) + { + } + + inline schema_error schema:: + code () const + { + return code_; + } +#endif + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/genx/document.cxx b/libxsde/xsde/cxx/serializer/genx/document.cxx new file mode 100644 index 0000000..bba4b26 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/genx/document.cxx @@ -0,0 +1,822 @@ +// file : xsde/cxx/serializer/genx/document.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // strlen, strcmp + +#ifdef XSDE_EXCEPTIONS +# include // std::bad_alloc +#endif + +#ifdef XSDE_IOSTREAM +# include +#endif + +#ifdef XSDE_EXCEPTIONS +# include +#else +# include +#endif + +#include + +#ifdef XSDE_POLYMORPHIC +# include +#endif + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace genx + { +#ifdef XSDE_POLYMORPHIC + static substitution_map_init substitution_map_init_; +#endif + + // writer + // + writer:: + ~writer () + { + } + +#ifdef XSDE_EXCEPTIONS + void writer:: + write (const char* s) + { + write (s, strlen (s)); + } +#else + bool writer:: + write (const char* s) + { + return write (s, strlen (s)); + } +#endif + + // document_simpl + // + + document_simpl:: + ~document_simpl () + { + // Prevents auto-generation of this dtor. + } + + document_simpl:: +#ifdef XSDE_POLYMORPHIC + document_simpl (serializer_base& serializer, + const char* name, + bool, + const char* st) +#else + document_simpl (serializer_base& serializer, const char* name) +#endif + : serializer_ (serializer) + { +#ifdef XSDE_POLYMORPHIC + root_static_type_ = st; +#endif + // Leave root_ns_ uninitialized. + // +#ifdef XSDE_EXCEPTIONS + root_name_.assign (name); +#else + if (root_name_.assign (name)) + error_ = error (sys_error::no_memory); +#endif + } + + document_simpl:: +#ifdef XSDE_POLYMORPHIC + document_simpl (serializer_base& serializer, + const char* ns, + const char* name, + bool, + const char* st) +#else + document_simpl (serializer_base& serializer, + const char* ns, + const char* name) +#endif + : serializer_ (serializer) + { +#ifdef XSDE_POLYMORPHIC + root_static_type_ = st; +#endif +#ifdef XSDE_EXCEPTIONS + root_ns_.assign (ns); + root_name_.assign (name); +#else + if (root_ns_.assign (ns) || root_name_.assign (name)) + error_ = error (sys_error::no_memory); +#endif + } + +#ifdef XSDE_STL + document_simpl:: +#ifdef XSDE_POLYMORPHIC + document_simpl (serializer_base& serializer, + const std::string& name, + bool, + const char* st) +#else + document_simpl (serializer_base& serializer, const std::string& name) +#endif + : serializer_ (serializer) + { +#ifdef XSDE_POLYMORPHIC + root_static_type_ = st; +#endif + // Leave root_ns_ uninitialized. + // +#ifdef XSDE_EXCEPTIONS + root_name_.assign (name.c_str (), name.size ()); +#else + if (root_name_.assign (name.c_str (), name.size ())) + error_ = error (sys_error::no_memory); +#endif + } + + document_simpl:: +#ifdef XSDE_POLYMORPHIC + document_simpl (serializer_base& serializer, + const std::string& ns, + const std::string& name, + bool, + const char* st) +#else + document_simpl (serializer_base& serializer, + const std::string& ns, + const std::string& name) +#endif + : serializer_ (serializer) + { +#ifdef XSDE_POLYMORPHIC + root_static_type_ = st; +#endif +#ifdef XSDE_EXCEPTIONS + root_ns_.assign (ns.c_str (), ns.size ()); + root_name_.assign (name.c_str (), name.size ()); +#else + if (root_ns_.assign (ns.c_str (), ns.size ()) || + root_name_.assign (name.c_str (), name.size ())) + error_ = error (sys_error::no_memory); +#endif + } +#endif // XSDE_STL + + + void document_simpl:: + add_prefix (const char* p, const char* ns) + { +#if defined (XSDE_STL) + prefixes_.push_back (p); + prefix_namespaces_.push_back (ns); +#else +#if defined (XSDE_EXCEPTIONS) + prefixes_.push_back_copy (p); + prefix_namespaces_.push_back_copy (ns); +#else + if (prefixes_.push_back_copy (p) || + prefix_namespaces_.push_back_copy (ns)) + error_ = error (sys_error::no_memory); +#endif +#endif + } + + void document_simpl:: + add_default_prefix (const char* ns) + { +#if defined (XSDE_STL) + prefixes_.push_back (""); + prefix_namespaces_.push_back (ns); +#else +#if defined (XSDE_EXCEPTIONS) + prefixes_.push_back_copy (""); + prefix_namespaces_.push_back_copy (ns); +#else + if (prefixes_.push_back_copy ("") || + prefix_namespaces_.push_back_copy (ns)) + error_ = error (sys_error::no_memory); +#endif +#endif + } + + void document_simpl:: + add_schema (const char* ns, const char* l) + { +#if defined (XSDE_STL) + schemas_.push_back (l); + schema_namespaces_.push_back (ns); +#else +#if defined (XSDE_EXCEPTIONS) + schemas_.push_back_copy (l); + schema_namespaces_.push_back_copy (ns); +#else + if (schemas_.push_back_copy (l) || + schema_namespaces_.push_back_copy (ns)) + error_ = error (sys_error::no_memory); +#endif +#endif + } + + void document_simpl:: + add_no_namespace_schema (const char* l) + { +#if defined (XSDE_STL) + schemas_.push_back (l); + schema_namespaces_.push_back (""); +#else +#if defined (XSDE_EXCEPTIONS) + schemas_.push_back_copy (l); + schema_namespaces_.push_back_copy (""); +#else + if (schemas_.push_back_copy (l) || + schema_namespaces_.push_back_copy ("")) + error_ = error (sys_error::no_memory); +#endif +#endif + } + + // + // + void document_simpl:: + reset () + { +#ifndef XSDE_EXCEPTIONS + error_ = error (); +#endif + if (xml_serializer_) + genxReset (xml_serializer_); + + serializer_._reset (); + } + + // istream + // +#ifdef XSDE_IOSTREAM + +#ifdef XSDE_EXCEPTIONS + static void + ostream_write (void* p, const char* s, size_t n) + { + std::ostream* os = reinterpret_cast (p); + os->write (s, static_cast (n)); + + if (os->bad ()) + throw std::ios_base::failure ("write failed"); + } + + static void + ostream_flush (void* p) + { + std::ostream* os = reinterpret_cast (p); + os->flush (); + + if (os->bad ()) + throw std::ios_base::failure ("flush failed"); + } +#else + static bool + ostream_write (void* p, const char* s, size_t n) + { + std::ostream* os = reinterpret_cast (p); + os->write (s, static_cast (n)); + return !os->bad (); + } + + static bool + ostream_flush (void* p) + { + std::ostream* os = reinterpret_cast (p); + os->flush (); + return !os->bad (); + } +#endif + + void document_simpl:: + serialize (std::ostream& os) + { + serialize (&ostream_write, &ostream_flush, &os); + } +#endif // XSDE_IOSTREAM + + // + // +#ifdef XSDE_EXCEPTIONS + static void + write_thunk (void* p, const char* s) + { + reinterpret_cast (p)->write (s); + } + + static void + write_bound_thunk (void* p, const char* s, size_t n) + { + reinterpret_cast (p)->write (s, n); + } + + static void + flush_thunk (void* p) + { + reinterpret_cast (p)->flush (); + } +#else + static bool + write_thunk (void* p, const char* s) + { + return reinterpret_cast (p)->write (s); + } + + static bool + write_bound_thunk (void* p, const char* s, size_t n) + { + return reinterpret_cast (p)->write (s, n); + } + + static bool + flush_thunk (void* p) + { + return reinterpret_cast (p)->flush (); + } +#endif + + void document_simpl:: + serialize (writer& w) + { + serialize (&write_thunk, &write_bound_thunk, &flush_thunk, &w); + } + + // Genx write functions. + // + struct writer_info + { + void* user_data; + document_simpl::write_func write; + document_simpl::write_bound_func write_bound; + document_simpl::flush_func flush; + }; + + extern "C" genxStatus + genx_write (void* p, constUtf8 us) + { + const char* s = reinterpret_cast (us); + writer_info* wi = reinterpret_cast (p); + + if (wi->write != 0) + { +#ifdef XSDE_EXCEPTIONS + wi->write (wi->user_data, s); +#else + if (!wi->write (wi->user_data, s)) + return GENX_IO_ERROR; +#endif + } + else + { +#ifdef XSDE_EXCEPTIONS + wi->write_bound (wi->user_data, s, strlen (s)); +#else + if (!wi->write_bound (wi->user_data, s, strlen (s))) + return GENX_IO_ERROR; +#endif + } + + return GENX_SUCCESS; + } + + extern "C" genxStatus + genx_write_bound (void* p, constUtf8 start, constUtf8 end) + { + size_t size = static_cast (end - start); + const char* s = reinterpret_cast (start); + writer_info* wi = reinterpret_cast (p); + +#ifdef XSDE_EXCEPTIONS + wi->write_bound (wi->user_data, s, size); +#else + if (!wi->write_bound (wi->user_data, s, size)) + return GENX_IO_ERROR; +#endif + + return GENX_SUCCESS; + } + + extern "C" genxStatus + genx_flush (void* p) + { + writer_info* wi = reinterpret_cast (p); + +#ifdef XSDE_EXCEPTIONS + wi->flush (wi->user_data); +#else + if (!wi->flush (wi->user_data)) + return GENX_IO_ERROR; +#endif + + return GENX_SUCCESS; + } + + void document_simpl:: + serialize (write_func w, write_bound_func wb, flush_func f, + void* user_data) + { + if (xml_serializer_ == 0) + { + xml_serializer_ = genxNew (0, 0, 0); + + if (xml_serializer_ == 0) + { +#ifdef XSDE_EXCEPTIONS + throw std::bad_alloc (); +#else + error_ = error (sys_error::no_memory); + return; +#endif + } + } + + writer_info wi; + wi.user_data = user_data; + wi.write = w; + wi.write_bound = wb; + wi.flush = f; + + genxSetUserData (xml_serializer_, &wi); + + genxSender sender; + sender.send = &genx_write; + sender.sendBounded = &genx_write_bound; + sender.flush = &genx_flush; + + genxStatus e = genxStartDocSender (xml_serializer_, &sender); + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + serialize (xml_serializer_); + +#ifndef XSDE_EXCEPTIONS + if (error_) + return; +#endif + + e = genxEndDocument (xml_serializer_); + + if (e != GENX_SUCCESS) + filter_xml_error (e); + } + + // + // + static const char xsi[] = "http://www.w3.org/2001/XMLSchema-instance"; + + void document_simpl:: + serialize (genxWriter s) + { +#ifndef XSDE_POLYMORPHIC + genxStatus e = genxStartElementLiteral ( + s, + reinterpret_cast (root_ns_.data ()), + reinterpret_cast (root_name_.data ())); +#else + const char* ns = root_ns_.data (); + const char* n = root_name_.data (); + const char* dt = 0; + + if (root_static_type_ != 0) + { + dt = serializer_._dynamic_type (); + + // Call to check sets ns and n if successful. + // + if (strcmp (dt, root_static_type_) == 0 || + substitution_map_instance ().check (ns, n, dt)) + dt = 0; + } + + genxStatus e = genxStartElementLiteral ( + s, + reinterpret_cast (ns), + reinterpret_cast (n)); + +#endif // XSDE_POLYMORPHIC + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + // Add namespace prefixes. + // + for (size_t i = 0; i < prefixes_.size (); ++i) + { +#ifdef XSDE_STL + e = genxAddNamespaceLiteral ( + s, + reinterpret_cast (prefix_namespaces_[i].c_str ()), + reinterpret_cast (prefixes_[i].c_str ())); +#else + e = genxAddNamespaceLiteral ( + s, + reinterpret_cast (prefix_namespaces_[i]), + reinterpret_cast (prefixes_[i])); +#endif + if (e != GENX_SUCCESS) + break; + } + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + // Add the schema location attributes. + // + if (schemas_.size () != 0) + { + e = genxAddNamespaceLiteral ( + s, + reinterpret_cast (xsi), + reinterpret_cast ("xsi")); + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + // First add the xsi:schemaLocation attribute. + // + bool start = false; + + for (size_t j = 0; j < schemas_.size (); ++j) + { +#ifdef XSDE_STL + const char* l = schemas_[j].c_str (); + const char* ns = schema_namespaces_[j].c_str (); +#else + const char* l = schemas_[j]; + const char* ns = schema_namespaces_[j]; +#endif + if (ns[0] != '\0') + { + if (!start) + { + e = genxStartAttributeLiteral ( + s, + reinterpret_cast (xsi), + reinterpret_cast ("schemaLocation")); + + if (e != GENX_SUCCESS) + break; + + start = true; + } + else + { + e = genxAddCharacter (s, ' '); + + if (e != GENX_SUCCESS) + break; + } + + e = genxAddText (s, reinterpret_cast (ns)); + + if (e != GENX_SUCCESS) + break; + + e = genxAddCharacter (s, ' '); + + if (e != GENX_SUCCESS) + break; + + e = genxAddText (s, reinterpret_cast (l)); + + if (e != GENX_SUCCESS) + break; + } + } + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + if (start) + { + e = genxEndAttribute (s); + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + } + + // Now add the xsi:noNamespaceSchemaLocation attribute. + // + start = false; + + for (size_t k = 0; k < schemas_.size (); ++k) + { +#ifdef XSDE_STL + const char* l = schemas_[k].c_str (); + const char* ns = schema_namespaces_[k].c_str (); +#else + const char* l = schemas_[k]; + const char* ns = schema_namespaces_[k]; +#endif + if (ns[0] == '\0') + { + if (!start) + { + e = genxStartAttributeLiteral ( + s, + reinterpret_cast (xsi), + reinterpret_cast ("noNamespaceSchemaLocation")); + + if (e != GENX_SUCCESS) + break; + + start = true; + } + else + { + e = genxAddCharacter (s, ' '); + + if (e != GENX_SUCCESS) + break; + } + + e = genxAddText (s, reinterpret_cast (l)); + + if (e != GENX_SUCCESS) + break; + } + } + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + + if (start) + { + e = genxEndAttribute (s); + + if (e != GENX_SUCCESS) + { + filter_xml_error (e); + return; + } + } + } + + // Call the root type serializer to serialize the content. + // + context ctx (s); + +#if !defined (XSDE_SERIALIZER_VALIDATION) && defined (XSDE_EXCEPTIONS) + +#ifdef XSDE_POLYMORPHIC + // Set xsi:type if necessary. + // + if (dt != 0) + ctx.set_type (dt); +#endif + serializer_._pre_impl (ctx); + serializer_._serialize_attributes (); + serializer_._serialize_content (); + serializer_._post_impl (); + +#else // !defined (XSDE_SERIALIZER_VALIDATION) && defined (XSDE_EXCEPTIONS) + +#ifdef XSDE_POLYMORPHIC + // Set xsi:type if necessary. + // + if (dt != 0) + ctx.set_type (dt); + +#ifndef XSDE_EXCEPTIONS + if (!ctx.error_type ()) +#endif +#endif // XSDE_POLYMORPHIC + + serializer_._pre_impl (ctx); + + if (!ctx.error_type ()) + serializer_._serialize_attributes (); + + if (!ctx.error_type ()) + serializer_._serialize_content (); + + if (!ctx.error_type ()) + serializer_._post_impl (); + + if (context::error_type_t et = ctx.error_type ()) + { + switch (et) + { +#ifndef XSDE_EXCEPTIONS + case context::error_app: + { + error_ = error (ctx.app_error ()); + break; + } +#endif +#ifdef XSDE_SERIALIZER_VALIDATION + case context::error_schema: + { +#ifdef XSDE_EXCEPTIONS + throw schema (ctx.schema_error ()); +#else + error_ = error (ctx.schema_error ()); + break; +#endif + } +#endif +#ifndef XSDE_EXCEPTIONS + case context::error_xml: + { + filter_xml_error (ctx.xml_error ()); + break; + } + case context::error_sys: + { + error_ = error (ctx.sys_error ()); + break; + } +#endif + default: + break; + } + return; + } +#endif // !XSDE_SERIALIZER_VALIDATION && XSDE_EXCEPTIONS + + + e = genxEndElement (s); + + if (e != GENX_SUCCESS) + filter_xml_error (e); + } + + void document_simpl:: + filter_xml_error (genxStatus e) + { + switch (e) + { + case GENX_ALLOC_FAILED: + { +#ifdef XSDE_EXCEPTIONS + throw std::bad_alloc (); +#else + error_ = error (sys_error::no_memory); + break; +#endif + } + case GENX_IO_ERROR: + { +#ifdef XSDE_EXCEPTIONS + // This should never happen with consistent exception + // handling usage since the write/flush functions + // throw exceptions to indicate write failures. + // + throw xml (e); +#else + error_ = error (sys_error::write_failed); + break; +#endif + } + default: + { +#ifdef XSDE_EXCEPTIONS + throw xml (e); +#else + error_ = error (e); + break; +#endif + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/genx/document.hxx b/libxsde/xsde/cxx/serializer/genx/document.hxx new file mode 100644 index 0000000..19117d6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/genx/document.hxx @@ -0,0 +1,280 @@ +// file : xsde/cxx/serializer/genx/document.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_GENX_DOCUMENT_HXX +#define XSDE_CXX_SERIALIZER_GENX_DOCUMENT_HXX + +#include + +#include // size_t + +#include + +#ifdef XSDE_IOSTREAM +# include +#endif + +#include + +#ifdef XSDE_STL +# include +#else +# include +#endif + +#include + +#ifndef XSDE_EXCEPTIONS +# include +#endif + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace genx + { + // Simple auto pointer for genxWriter object. + // + struct serializer_auto_ptr + { + ~serializer_auto_ptr (); + + explicit + serializer_auto_ptr (genxWriter = 0); + + serializer_auto_ptr& + operator= (genxWriter); + + public: + operator genxWriter () + { + return serializer_; + } + + private: + serializer_auto_ptr (const serializer_auto_ptr&); + + serializer_auto_ptr& + operator= (const serializer_auto_ptr&); + + private: + genxWriter serializer_; + }; + + // Writer interface. + // + struct writer + { + virtual + ~writer (); + + // The first write function is called to write a '\0'-terminated + // string. Its default implementation calls the second versions: + // write (s, strlen (s)). If exceptions are enabled, throw to + // indicate a write failure. Otherwise return true if write was + // successful, false otherwise. + // +#ifdef XSDE_EXCEPTIONS + virtual void + write (const char* s); + + virtual void + write (const char* s, size_t n) = 0; + + virtual void + flush () = 0; +#else + virtual bool + write (const char* s); + + virtual bool + write (const char* s, size_t n) = 0; + + virtual bool + flush () = 0; +#endif + }; + + // + // + class document_simpl + { + public: + virtual + ~document_simpl (); + +#ifdef XSDE_POLYMORPHIC + // Note that the static_type string is not deep-copied. + // + document_simpl (serializer_base&, + const char* root_element_name, + bool polymorphic = false, + const char* root_static_type = 0); + + document_simpl (serializer_base&, + const char* root_element_namespace, + const char* root_element_name, + bool polymorphic = false, + const char* root_static_type = 0); + +#ifdef XSDE_STL + document_simpl (serializer_base&, + const std::string& root_element_name, + bool polymorphic = false, + const char* root_static_type = 0); + + document_simpl (serializer_base&, + const std::string& root_element_namespace, + const std::string& root_element_name, + bool polymorphic = false, + const char* root_static_type = 0); +#endif + +#else // XSDE_POLYMORPHIC + + document_simpl (serializer_base&, + const char* root_element_name); + + document_simpl (serializer_base&, + const char* root_element_namespace, + const char* root_element_name); + +#ifdef XSDE_STL + document_simpl (serializer_base&, + const std::string& root_element_name); + + document_simpl (serializer_base&, + const std::string& root_element_namespace, + const std::string& root_element_name); +#endif +#endif // XSDE_POLYMORPHIC + + public: + // Namespace and schema location. + // + void + add_prefix (const char* prefix, const char* namespace_); + + void + add_default_prefix (const char* namespace_); + + void + add_schema (const char* namespace_, const char* location); + + void + add_no_namespace_schema (const char* location); + +#ifdef XSDE_STL + void + add_prefix (const std::string& prefix, + const std::string& namespace_); + + void + add_default_prefix (const std::string& namespace_); + + void + add_schema (const std::string& namespace_, + const std::string& location); + + void + add_no_namespace_schema (const std::string& location); +#endif + + public: + void + reset (); + +#ifdef XSDE_IOSTREAM + public: + // Serialize to std::ostream. The std::ios_base::failure + // exception is used to report io errors (badbit and failbit) + // if XSDE_EXCEPTIONS is defined. Otherwise error codes are + // used. + // + void + serialize (std::ostream&); +#endif + + public: + // Serialize by calling writer::write() and writer::flush() to + // output XML. + // + void + serialize (writer&); + + // Serialize by calling the write and flush functions. If the + // unbounded write function is not provided, the bounded version + // is called: write_bound_func (s, strlen (s)). user_data is + // passed as a first argument to these functions. If exceptions + // are enabled, throw to indicate a write failure. Otherwise return + // true if write was successful, false otherwise. + // + +#ifdef XSDE_EXCEPTIONS + typedef void (*write_func) (void*, const char*); + typedef void (*write_bound_func) (void*, const char*, size_t); + typedef void (*flush_func) (void*); +#else + typedef bool (*write_func) (void*, const char*); + typedef bool (*write_bound_func) (void*, const char*, size_t); + typedef bool (*flush_func) (void*); +#endif + + void + serialize (write_bound_func, flush_func, void* user_data); + + void + serialize (write_func, write_bound_func, flush_func, void* user_data); + + public: + // Low-level, genx-specific serialization. With this method + // it is your responsibility to call genxStartDoc*() and + // genxEndDocument(). + // + void + serialize (genxWriter); + +#ifndef XSDE_EXCEPTIONS + public: + const error& + _error () const; +#endif + + protected: + void + filter_xml_error (genxStatus); + + protected: + serializer_auto_ptr xml_serializer_; + serializer_base& serializer_; + + string root_name_; + string root_ns_; + +#ifdef XSDE_POLYMORPHIC + const char* root_static_type_; +#endif + + string_sequence prefixes_; + string_sequence prefix_namespaces_; + + string_sequence schemas_; + string_sequence schema_namespaces_; + +#ifndef XSDE_EXCEPTIONS + error error_; +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_GENX_DOCUMENT_HXX diff --git a/libxsde/xsde/cxx/serializer/genx/document.ixx b/libxsde/xsde/cxx/serializer/genx/document.ixx new file mode 100644 index 0000000..7269fa6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/genx/document.ixx @@ -0,0 +1,84 @@ +// file : xsde/cxx/serializer/genx/document.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace genx + { + // serializer_auto_ptr + // + inline serializer_auto_ptr:: + ~serializer_auto_ptr () + { + if (serializer_ != 0) + genxDispose (serializer_); + } + + inline serializer_auto_ptr:: + serializer_auto_ptr (genxWriter serializer) + : serializer_ (serializer) + { + } + + inline serializer_auto_ptr& serializer_auto_ptr:: + operator= (genxWriter serializer) + { + if (serializer_ != 0) + genxDispose (serializer_); + + serializer_ = serializer; + return *this; + } + + // document_simpl + // + +#ifdef XSDE_STL + inline void document_simpl:: + add_prefix (const std::string& p, const std::string& ns) + { + add_prefix (p.c_str (), ns.c_str ()); + } + + inline void document_simpl:: + add_default_prefix (const std::string& ns) + { + add_default_prefix (ns.c_str ()); + } + + inline void document_simpl:: + add_schema (const std::string& ns, const std::string& l ) + { + add_schema (ns.c_str (), l.c_str ()); + } + + inline void document_simpl:: + add_no_namespace_schema (const std::string& l) + { + add_no_namespace_schema (l.c_str ()); + } +#endif + + inline void document_simpl:: + serialize (write_bound_func wb, flush_func f, void* user_data) + { + serialize (0, wb, f, user_data); + } + +#ifndef XSDE_EXCEPTIONS + inline const error& document_simpl:: + _error () const + { + return error_; + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/genx/xml-error.cxx b/libxsde/xsde/cxx/serializer/genx/xml-error.cxx new file mode 100644 index 0000000..8abc7a6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/genx/xml-error.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/serializer/genx/xml-error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace genx + { + static const char* const text_[] = + { + "no error", + "illegal UTF-8 character", + "illegal XML character", + "illegal name", + "out of memory", + "illegal namespace name", + "internal error", + "duplicate prefix", + "call out of sequence", + "mismatched end element call", + "output error", + "missing attribute value", + "malformed comment body", + "illegal character sequence in processing instruction", + "processing instruction target is XML", + "duplicate attribute", + "attribute in default namespace", + "different prefixes for the same namespace in the same element", + "default namespace in an unqualified element" + }; + + const char* + xml_error_text (xml_error e) + { + return text_[e]; + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/genx/xml-error.hxx b/libxsde/xsde/cxx/serializer/genx/xml-error.hxx new file mode 100644 index 0000000..6287952 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/genx/xml-error.hxx @@ -0,0 +1,28 @@ +// file : xsde/cxx/serializer/genx/xml-error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_GENX_XML_ERROR_HXX +#define XSDE_CXX_SERIALIZER_GENX_XML_ERROR_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace genx + { + typedef genxStatus xml_error; + + const char* + xml_error_text (xml_error); + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_GENX_XML_ERROR_HXX diff --git a/libxsde/xsde/cxx/serializer/map.cxx b/libxsde/xsde/cxx/serializer/map.cxx new file mode 100644 index 0000000..1ace4ac --- /dev/null +++ b/libxsde/xsde/cxx/serializer/map.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // serializer_map + // + serializer_map:: + ~serializer_map () + { + } + + // serializer_map_impl + // + void serializer_map_impl:: + reset () const + { + for (hashmap::const_iterator i (map_.begin ()), e (map_.end ()); + i != e; ++i) + { + serializer_base* s = *static_cast (*i); + s->_reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/map.hxx b/libxsde/xsde/cxx/serializer/map.hxx new file mode 100644 index 0000000..2cfc755 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/map.hxx @@ -0,0 +1,96 @@ +// file : xsde/cxx/serializer/map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_MAP_HXX +#define XSDE_CXX_SERIALIZER_MAP_HXX + +#include // size_t + +#include +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + // Serializer map. Used in the polymorphic document parsing. + // + class serializer_map + { + public: + // The type_id argument is the application-specific type id + // object (passed as opaque const void*) that was set by the + // callback in the context or 0 if no type id was provided. + // + virtual serializer_base* + find (const void* type_id) const = 0; + + // Reset the serializers this map contains. + // + virtual void + reset () const = 0; + + virtual + ~serializer_map (); + }; + + // Default serializer map implementation. It assumes that the + // type id is a C string (const char*). + // + class serializer_map_impl: public serializer_map + { + public: +#ifndef XSDE_EXCEPTIONS + enum error + { + error_none, + error_no_memory + }; + + error + _error () const; +#endif + + public: + serializer_map_impl (size_t buckets); + + // Note that the type_id string is not copied so it should + // be valid for the lifetime of the map. + // + void + insert (const char* type_id, serializer_base&); + + // This version of insert is a shortcut that uses the string + // returned by the serializer's _dynamic_type() function. + // + void + insert (serializer_base&); + + virtual serializer_base* + find (const void* type_id) const; + + virtual void + reset () const; + + private: + serializer_map_impl (const serializer_map_impl&); + + serializer_map_impl& + operator= (const serializer_map_impl&); + + private: + hashmap map_; + }; + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_MAP_HXX diff --git a/libxsde/xsde/cxx/serializer/map.ixx b/libxsde/xsde/cxx/serializer/map.ixx new file mode 100644 index 0000000..64eb19a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/map.ixx @@ -0,0 +1,51 @@ +// file : xsde/cxx/serializer/map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { +#ifndef XSDE_EXCEPTIONS + inline serializer_map_impl::error serializer_map_impl:: + _error () const + { + return map_._error () ? error_no_memory : error_none; + } +#endif + + inline serializer_map_impl:: + serializer_map_impl (size_t buckets) + : map_ (buckets, sizeof (serializer_base*)) + { + } + + inline void serializer_map_impl:: + insert (const char* type_id, serializer_base& s) + { + serializer_base* tmp = &s; + map_.insert (type_id, &tmp); + } + + inline void serializer_map_impl:: + insert (serializer_base& s) + { + insert (s._dynamic_type (), s); + } + + inline serializer_base* serializer_map_impl:: + find (const void* type_id) const + { + if (type_id) + { + const void* p = map_.find (static_cast (type_id)); + return p ? *static_cast (p) : 0; + } + return 0; + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/any-type.hxx b/libxsde/xsde/cxx/serializer/non-validating/any-type.hxx new file mode 100644 index 0000000..c01b54e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/any-type.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/any-type.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_ANY_TYPE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_ANY_TYPE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // any_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_type_simpl: virtual any_type_sskel +#else + struct any_type_simpl: any_type_sskel +#endif + { + }; + + // any_simple_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_simple_type_simpl: virtual any_simple_type_sskel +#else + struct any_simple_type_simpl: any_simple_type_sskel +#endif + { + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_ANY_TYPE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/base64-binary.cxx b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.cxx new file mode 100644 index 0000000..51d1b97 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.cxx @@ -0,0 +1,166 @@ +// file : xsde/cxx/serializer/non-validating/base64-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + base64_binary_simpl:: + ~base64_binary_simpl () + { + if (free_) + delete const_cast (value_); + } + + void base64_binary_simpl:: + pre (const buffer* value) + { + value_ = value; + } + + static const char base64_tab[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/', '\0' + }; + + inline void + split_1 (char b, unsigned char& b1, unsigned char& b2) + { + unsigned char ub = static_cast (b); + b1 = ub >> 2; + b2 = (ub & 0x3) << 4; + } + + inline void + split_2 (char b, unsigned char& b2, unsigned char& b3) + { + unsigned char ub = static_cast (b); + b2 |= ub >> 4; + b3 = (ub & 0x0F) << 2; + } + + inline void + split_3 (char b, unsigned char& b3, unsigned char& b4) + { + unsigned char ub = static_cast (b); + b3 |= ub >> 6; + b4 = ( ub & 0x3F ); + } + + void base64_binary_simpl:: + _serialize_content () + { + // Maximum 76 characters per line, 76/4 = 19 + // + const size_t quads_per_line = 19; + char buf[quads_per_line * 4 + 1]; + + if (size_t size = value_->size ()) + { + const char* data = value_->data (); + size_t quads = (size + 2) / 3; + + // Process all quadruplets except the last, one line at a time. + // + size_t i = 0; + size_t j = 0; + unsigned char b1, b2, b3, b4; + + for (; j < (quads - 1);) + { + for (; i < quads_per_line && j < (quads - 1); ++i, ++j) + { + split_1 (*data++, b1, b2); + split_2 (*data++, b2, b3); + split_3 (*data++, b3, b4); + + buf[i * 4] = base64_tab[b1]; + buf[i * 4 + 1] = base64_tab[b2]; + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = base64_tab[b4]; + } + + if (i == quads_per_line) + { + buf[i * 4] = '\n'; + +#ifdef XSDE_EXCEPTIONS + _characters (buf, i * 4 + 1); +#else + if (!_characters (buf, i * 4 + 1)) + break; +#endif + i = 0; + } + } + +#ifndef XSDE_EXCEPTIONS + if (j == (quads - 1)) + { +#endif + // Process last quadruplet. The first byte is always present. + // + split_1 (*data++, b1, b2); + buf[i * 4] = base64_tab[b1]; + + if (data != value_->end ()) + { + // Second byte is present. + // + split_2 (*data++, b2, b3); + buf[i * 4 + 1] = base64_tab[b2]; + + if(data != value_->end ()) + { + // Third byte is present. + // + split_3 (*data++, b3, b4); + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = base64_tab[b4]; + } + else + { + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = '='; + } + } + else + { + buf[i * 4 + 1] = base64_tab[b2]; + buf[i * 4 + 2] = '='; + buf[i * 4 + 3] = '='; + } + + i++; + + buf[i * 4] = '\n'; + _characters (buf, i * 4 + 1); + +#ifndef XSDE_EXCEPTIONS + } +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/base64-binary.hxx b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.hxx new file mode 100644 index 0000000..de4d914 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/base64-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_BASE64_BINARY_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_BASE64_BINARY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct base64_binary_simpl: virtual base64_binary_sskel +#else + struct base64_binary_simpl: base64_binary_sskel +#endif + { + virtual + ~base64_binary_simpl (); + + base64_binary_simpl (bool free = false); + + virtual void + pre (const buffer*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const buffer* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_BASE64_BINARY_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/base64-binary.ixx b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.ixx new file mode 100644 index 0000000..59a10d6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/base64-binary.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/base64-binary.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline base64_binary_simpl:: + base64_binary_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/boolean.cxx b/libxsde/xsde/cxx/serializer/non-validating/boolean.cxx new file mode 100644 index 0000000..d505d63 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/boolean.cxx @@ -0,0 +1,30 @@ +// file : xsde/cxx/serializer/non-validating/boolean.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void boolean_simpl:: + pre (bool value) + { + value_ = value; + } + + void boolean_simpl:: + _serialize_content () + { + _characters ((value_ ? "true" : "false"), (value_ ? 4 : 5)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/boolean.hxx b/libxsde/xsde/cxx/serializer/non-validating/boolean.hxx new file mode 100644 index 0000000..5edcdaa --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/boolean.hxx @@ -0,0 +1,39 @@ +// file : xsde/cxx/serializer/non-validating/boolean.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_BOOLEAN_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_BOOLEAN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct boolean_simpl: virtual boolean_sskel +#else + struct boolean_simpl: boolean_sskel +#endif + { + virtual void + pre (bool); + + virtual void + _serialize_content (); + + protected: + bool value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_BOOLEAN_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/byte.cxx b/libxsde/xsde/cxx/serializer/non-validating/byte.cxx new file mode 100644 index 0000000..200d4ab --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/byte.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void byte_simpl:: + pre (signed char value) + { + value_ = value; + } + + void byte_simpl:: + _serialize_content () + { + // We only need strlen("-128") + 1 characters to hold all + // representations of signed byte. + // + char str[5]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 5, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 5) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/byte.hxx b/libxsde/xsde/cxx/serializer/non-validating/byte.hxx new file mode 100644 index 0000000..093adb4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/byte.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_BYTE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_BYTE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 8-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct byte_simpl: virtual byte_sskel +#else + struct byte_simpl: byte_sskel +#endif + { + virtual void + pre (signed char); + + virtual void + _serialize_content (); + + protected: + signed char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_BYTE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/date-time.cxx b/libxsde/xsde/cxx/serializer/non-validating/date-time.cxx new file mode 100644 index 0000000..fe11566 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date-time.cxx @@ -0,0 +1,78 @@ +// file : xsde/cxx/serializer/non-validating/date-time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void date_time_simpl:: + pre (const date_time& value) + { + value_ = value; + } + + void date_time_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM-DDThh:mm:ss.ssssss-hh:mm") + // + 1 characters to hold all representations of date_time. We + // know that the seconds part (represented as double) has + // default precision of 6. + // + char str[40]; + + if (value_.month () <= 12 && + value_.day () <= 31 && + value_.hours () <= 24 && + value_.minutes () <= 59 && + value_.seconds () >= 0.0 && + value_.seconds () < 60.0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 34, "%.4d-%.2u-%.2uT%.2u:%.2u:%09f", + value_.year (), value_.month (), value_.day (), + value_.hours (), value_.minutes (), + value_.seconds ()); +#else + int n = sprintf (str, "%.4d-%.2u-%.2uT%.2u:%.2u:%09f", + value_.year (), value_.month (), value_.day (), + value_.hours (), value_.minutes (), + value_.seconds ()); +#endif + if (n > 0 && n < 34) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/date-time.hxx b/libxsde/xsde/cxx/serializer/non-validating/date-time.hxx new file mode 100644 index 0000000..e239564 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date-time.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/date-time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_TIME_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_TIME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_time_simpl: virtual date_time_sskel +#else + struct date_time_simpl: date_time_sskel +#endif + { + date_time_simpl (); + + virtual void + pre (const date_time&); + + virtual void + _serialize_content (); + + protected: + date_time value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_TIME_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/date-time.ixx b/libxsde/xsde/cxx/serializer/non-validating/date-time.ixx new file mode 100644 index 0000000..e300c03 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date-time.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/date-time.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline date_time_simpl:: + date_time_simpl () + : value_ (1, 0, 0, 0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/date.cxx b/libxsde/xsde/cxx/serializer/non-validating/date.cxx new file mode 100644 index 0000000..2fa6069 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date.cxx @@ -0,0 +1,59 @@ +// file : xsde/cxx/serializer/non-validating/date.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void date_simpl:: + pre (const date& value) + { + value_ = value; + } + + void date_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM-DD+hh:mm") + 1 characters to + // hold all representations of date. + // + char str[24]; + + if (value_.month () < 13 && value_.day () < 32) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 18, "%.4d-%.2u-%.2u", + value_.year (), value_.month (), value_.day ()); +#else + int n = sprintf (str, "%.4d-%.2u-%.2u", + value_.year (), value_.month (), value_.day ()); +#endif + if (n > 0 && n < 18) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/date.hxx b/libxsde/xsde/cxx/serializer/non-validating/date.hxx new file mode 100644 index 0000000..9fb0f40 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/date.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_simpl: virtual date_sskel +#else + struct date_simpl: date_sskel +#endif + { + date_simpl (); + + virtual void + pre (const date&); + + virtual void + _serialize_content (); + + protected: + date value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_DATE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/date.ixx b/libxsde/xsde/cxx/serializer/non-validating/date.ixx new file mode 100644 index 0000000..c89cea4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/date.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/date.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline date_simpl:: + date_simpl () + : value_ (1, 1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/decimal.cxx b/libxsde/xsde/cxx/serializer/non-validating/decimal.cxx new file mode 100644 index 0000000..dd55ab0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/decimal.cxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/serializer/non-validating/decimal.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void decimal_simpl:: + pre (double value) + { + value_ = value; + } + + void decimal_simpl:: + _serialize_content () + { + // Assume double values cannot be longer than 127 characters. + // + char str[128]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, "%.*f", + static_cast (precision_), value_); +#else + int n = sprintf (str, "%.*f", + static_cast (precision_), value_); +#endif + if (n > 0 && n < 128) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + _characters (str, static_cast (n)); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/decimal.hxx b/libxsde/xsde/cxx/serializer/non-validating/decimal.hxx new file mode 100644 index 0000000..b0155b3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/decimal.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/serializer/non-validating/decimal.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_DECIMAL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_DECIMAL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct decimal_simpl: virtual decimal_sskel +#else + struct decimal_simpl: decimal_sskel +#endif + { +#ifdef DBL_DIG + decimal_simpl (unsigned int precision = DBL_DIG); +#else + decimal_simpl (unsigned int precision = 15) +#endif + + virtual void + pre (double); + + virtual void + _serialize_content (); + + protected: + unsigned int precision_; + double value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_DECIMAL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/decimal.ixx b/libxsde/xsde/cxx/serializer/non-validating/decimal.ixx new file mode 100644 index 0000000..af3ab38 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/decimal.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/decimal.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline decimal_simpl:: + decimal_simpl (unsigned int p) + : precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/double.cxx b/libxsde/xsde/cxx/serializer/non-validating/double.cxx new file mode 100644 index 0000000..1f8f459 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/double.cxx @@ -0,0 +1,103 @@ +// file : xsde/cxx/serializer/non-validating/double.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void double_simpl:: + pre (double value) + { + value_ = value; + } + + void double_simpl:: + _serialize_content () + { + // Assume double values cannot be longer than 127 characters. + // + char str[128]; + + const char* fmt = 0; + + switch (notation_) + { + case notation_auto: + { + fmt = "%.*g"; + break; + } + case notation_fixed: + { + fmt = "%.*f"; + break; + } + case notation_scientific: + { + fmt = "%.*e"; + break; + } + } + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, fmt, precision_, value_); +#else + int n = sprintf (str, fmt, precision_, value_); +#endif + if (n > 0 && n < 128) + { + if (str[0] == '-') + { + if (str[1] == 'n' && str[2] == 'a' && str[3] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[1] == 'i' && str[2] == 'n' && str[3] == 'f') + { + _characters ("-INF", 4); + return; + } + } + else + { + if (str[0] == 'n' && str[1] == 'a' && str[2] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[0] == 'i' && str[1] == 'n' && str[2] == 'f') + { + _characters ("INF", 3); + return; + } + } + + if (notation_ == notation_fixed) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + } + + _characters (str, static_cast (n)); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/double.hxx b/libxsde/xsde/cxx/serializer/non-validating/double.hxx new file mode 100644 index 0000000..a79c144 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/double.hxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/serializer/non-validating/double.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_DOUBLE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_DOUBLE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct double_simpl: virtual double_sskel +#else + struct double_simpl: double_sskel +#endif + { + enum notation + { + notation_auto, + notation_fixed, + notation_scientific + }; + +#ifdef DBL_DIG + double_simpl (notation = notation_auto, + unsigned int precision = DBL_DIG); +#else + double_simpl (notation = notation_auto, + unsigned int precision = 15) +#endif + + virtual void + pre (double); + + virtual void + _serialize_content (); + + protected: + notation notation_; + unsigned int precision_; + double value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_DOUBLE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/double.ixx b/libxsde/xsde/cxx/serializer/non-validating/double.ixx new file mode 100644 index 0000000..36cc319 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/double.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/double.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline double_simpl:: + double_simpl (notation n, unsigned int p) + : notation_ (n), precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/duration.cxx b/libxsde/xsde/cxx/serializer/non-validating/duration.cxx new file mode 100644 index 0000000..1174af7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/duration.cxx @@ -0,0 +1,171 @@ +// file : xsde/cxx/serializer/non-validating/duration.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void duration_simpl:: + pre (const duration& value) + { + value_ = value; + } + + void duration_simpl:: + _serialize_content () + { + // duration := -PnYnMnDTnHnMnS + // + // The years, months, days, hours, and minutes components are + // represented as 32 unsigned integers with maximum string + // representation being strlen ("4294967295") = 10. + // + // We assume that the seconds part (double) cannot be longer + // than 128 chars. + // + // The total representation thus cannot exceed 10*5 + 128 + + // 9 + 1 = 188 characters. + // + char str[188]; + char* p = str; + + if (value_.negative ()) + *p++ = '-'; + + *p++ = 'P'; + + // years + // + // In case it is 0-duration, use the years field to handle + // this case. + // + if (value_.years () != 0 || + (value_.months () == 0 && + value_.days () == 0 && + value_.hours () == 0 && + value_.minutes () == 0 && + value_.seconds () == 0.0)) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.years ()); +#else + int n = sprintf (p, "%u", value_.years ()); +#endif + if (n < 0 || n >= 11) + return; + + p += n; + *p++ = 'Y'; + } + + // months + // + if (value_.months () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.months ()); +#else + int n = sprintf (p, "%u", value_.months ()); +#endif + if (n < 0 || n >= 11) + return; + + p += n; + *p++ = 'M'; + } + + // days + // + if (value_.days () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.days ()); +#else + int n = sprintf (p, "%u", value_.days ()); +#endif + if (n < 0 || n >= 11) + return; + + p += n; + *p++ = 'D'; + } + + // Figure out if we need the 'T' delimiter. + // + if (value_.hours () != 0 || + value_.minutes () != 0 || + value_.seconds () != 0.0) + *p++ = 'T'; + + // hours + // + if (value_.hours () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.hours ()); +#else + int n = sprintf (p, "%u", value_.hours ()); +#endif + if (n < 0 || n >= 11) + return; + + p += n; + *p++ = 'H'; + } + + // minutes + // + if (value_.minutes () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.minutes ()); +#else + int n = sprintf (p, "%u", value_.minutes ()); +#endif + if (n < 0 || n >= 11) + return; + + p += n; + *p++ = 'M'; + } + + // seconds + // + if (value_.seconds () > 0.0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 128, "%f", value_.seconds ()); +#else + int n = sprintf (p, "%f", value_.seconds ()); +#endif + if (n < 0 || n >= 128) + return; + + // Remove trailing '0' and '.' if necessary. + // + while (p[n - 1] == '0') + n--; + + if (p[n - 1] == '.') + n--; + + p += n; + *p++ = 'S'; + } + + _characters (str, static_cast (p - str)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/duration.hxx b/libxsde/xsde/cxx/serializer/non-validating/duration.hxx new file mode 100644 index 0000000..88530f4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/duration.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/duration.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_DURATION_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_DURATION_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct duration_simpl: virtual duration_sskel +#else + struct duration_simpl: duration_sskel +#endif + { + duration_simpl (); + + virtual void + pre (const duration&); + + virtual void + _serialize_content (); + + protected: + duration value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_DURATION_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/duration.ixx b/libxsde/xsde/cxx/serializer/non-validating/duration.ixx new file mode 100644 index 0000000..10d2287 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/duration.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/duration.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline duration_simpl:: + duration_simpl () + : value_ (false, 1, 0, 0, 0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/float.cxx b/libxsde/xsde/cxx/serializer/non-validating/float.cxx new file mode 100644 index 0000000..3af6e76 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/float.cxx @@ -0,0 +1,103 @@ +// file : xsde/cxx/serializer/non-validating/float.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void float_simpl:: + pre (float value) + { + value_ = value; + } + + void float_simpl:: + _serialize_content () + { + // Assume float values cannot be longer than 127 characters. + // + char str[128]; + + const char* fmt = 0; + + switch (notation_) + { + case notation_auto: + { + fmt = "%.*g"; + break; + } + case notation_fixed: + { + fmt = "%.*f"; + break; + } + case notation_scientific: + { + fmt = "%.*e"; + break; + } + } + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, fmt, precision_, value_); +#else + int n = sprintf (str, fmt, precision_, value_); +#endif + if (n > 0 && n < 128) + { + if (str[0] == '-') + { + if (str[1] == 'n' && str[2] == 'a' && str[3] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[1] == 'i' && str[2] == 'n' && str[3] == 'f') + { + _characters ("-INF", 4); + return; + } + } + else + { + if (str[0] == 'n' && str[1] == 'a' && str[2] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[0] == 'i' && str[1] == 'n' && str[2] == 'f') + { + _characters ("INF", 3); + return; + } + } + + if (notation_ == notation_fixed) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + } + + _characters (str, static_cast (n)); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/float.hxx b/libxsde/xsde/cxx/serializer/non-validating/float.hxx new file mode 100644 index 0000000..d3da48f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/float.hxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/serializer/non-validating/float.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_FLOAT_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_FLOAT_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct float_simpl: virtual float_sskel +#else + struct float_simpl: float_sskel +#endif + { + enum notation + { + notation_auto, + notation_fixed, + notation_scientific + }; + +#ifdef FLT_DIG + float_simpl (notation = notation_auto, + unsigned int precision = FLT_DIG); +#else + float_simpl (notation = notation_auto, + unsigned int precision = 6) +#endif + + virtual void + pre (float); + + virtual void + _serialize_content (); + + protected: + notation notation_; + unsigned int precision_; + float value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_FLOAT_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/float.ixx b/libxsde/xsde/cxx/serializer/non-validating/float.ixx new file mode 100644 index 0000000..192027e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/float.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/float.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline float_simpl:: + float_simpl (notation n, unsigned int p) + : notation_ (n), precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gday.cxx b/libxsde/xsde/cxx/serializer/non-validating/gday.cxx new file mode 100644 index 0000000..5d3a0a3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gday.cxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/serializer/non-validating/gday.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void gday_simpl:: + pre (const gday& value) + { + value_ = value; + } + + void gday_simpl:: + _serialize_content () + { + // We only need strlen("---DD+hh:mm") + 1 characters to hold all + // representations of gDay. + // + char str[12]; + + if (value_.day () < 32) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 6, "---%.2u", value_.day ()); +#else + int n = sprintf (str, "---%.2u", value_.day ()); +#endif + if (n > 0 && n < 6) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gday.hxx b/libxsde/xsde/cxx/serializer/non-validating/gday.hxx new file mode 100644 index 0000000..1442664 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gday.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/gday.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_GDAY_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_GDAY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gday_simpl: virtual gday_sskel +#else + struct gday_simpl: gday_sskel +#endif + { + gday_simpl (); + + virtual void + pre (const gday&); + + virtual void + _serialize_content (); + + protected: + gday value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_GDAY_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/gday.ixx b/libxsde/xsde/cxx/serializer/non-validating/gday.ixx new file mode 100644 index 0000000..ba322f6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gday.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/gday.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline gday_simpl:: + gday_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.cxx b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.cxx new file mode 100644 index 0000000..cb0bb4f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.cxx @@ -0,0 +1,59 @@ +// file : xsde/cxx/serializer/non-validating/gmonth-day.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void gmonth_day_simpl:: + pre (const gmonth_day& value) + { + value_ = value; + } + + void gmonth_day_simpl:: + _serialize_content () + { + // We only need strlen("--MM-DD+hh:mm") + 1 characters to hold all + // representations of gMonthDay. + // + char str[14]; + + if (value_.month () < 13 && value_.day () < 32) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 8, "--%.2u-%.2u", + value_.month (), value_.day ()); +#else + int n = sprintf (str, "--%.2u-%.2u", + value_.month (), value_.day ()); +#endif + if (n > 0 && n < 8) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.hxx b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.hxx new file mode 100644 index 0000000..6ba2ccf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/gmonth-day.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_DAY_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_DAY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_day_simpl: virtual gmonth_day_sskel +#else + struct gmonth_day_simpl: gmonth_day_sskel +#endif + { + gmonth_day_simpl (); + + virtual void + pre (const gmonth_day&); + + virtual void + _serialize_content (); + + protected: + gmonth_day value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_DAY_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.ixx b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.ixx new file mode 100644 index 0000000..864f56c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth-day.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/gmonth-day.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline gmonth_day_simpl:: + gmonth_day_simpl () + : value_ (1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth.cxx b/libxsde/xsde/cxx/serializer/non-validating/gmonth.cxx new file mode 100644 index 0000000..09c9739 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth.cxx @@ -0,0 +1,57 @@ +// file : xsde/cxx/serializer/non-validating/gmonth.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void gmonth_simpl:: + pre (const gmonth& value) + { + value_ = value; + } + + void gmonth_simpl:: + _serialize_content () + { + // We only need strlen("--MM+hh:mm") + 1 characters to hold all + // representations of gMonth. + // + char str[11]; + + if (value_.month () < 13) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 5, "--%.2u", value_.month ()); +#else + int n = sprintf (str, "--%.2u", value_.month ()); +#endif + if (n > 0 && n < 5) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth.hxx b/libxsde/xsde/cxx/serializer/non-validating/gmonth.hxx new file mode 100644 index 0000000..5ed6310 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/gmonth.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_simpl: virtual gmonth_sskel +#else + struct gmonth_simpl: gmonth_sskel +#endif + { + gmonth_simpl (); + + virtual void + pre (const gmonth&); + + virtual void + _serialize_content (); + + protected: + gmonth value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_GMONTH_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/gmonth.ixx b/libxsde/xsde/cxx/serializer/non-validating/gmonth.ixx new file mode 100644 index 0000000..c0b98f3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gmonth.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/gmonth.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline gmonth_simpl:: + gmonth_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear-month.cxx b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.cxx new file mode 100644 index 0000000..bbb2794 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.cxx @@ -0,0 +1,59 @@ +// file : xsde/cxx/serializer/non-validating/gyear-month.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void gyear_month_simpl:: + pre (const gyear_month& value) + { + value_ = value; + } + + void gyear_month_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM+hh:mm") + 1 characters to + // hold all representations of gYearMonth. + // + char str[21]; + + if (value_.month () < 13) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 15, "%.4d-%.2u", + value_.year (), value_.month ()); +#else + int n = sprintf (str, "%.4d-%.2u", + value_.year (), value_.month ()); +#endif + if (n > 0 && n < 15) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear-month.hxx b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.hxx new file mode 100644 index 0000000..32ee339 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/gyear-month.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_MONTH_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_MONTH_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_month_simpl: virtual gyear_month_sskel +#else + struct gyear_month_simpl: gyear_month_sskel +#endif + { + gyear_month_simpl (); + + virtual void + pre (const gyear_month&); + + virtual void + _serialize_content (); + + protected: + gyear_month value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_MONTH_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear-month.ixx b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.ixx new file mode 100644 index 0000000..f33b7b6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear-month.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/gyear-month.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline gyear_month_simpl:: + gyear_month_simpl () + : value_ (1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear.cxx b/libxsde/xsde/cxx/serializer/non-validating/gyear.cxx new file mode 100644 index 0000000..4d7a796 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear.cxx @@ -0,0 +1,54 @@ +// file : xsde/cxx/serializer/non-validating/gyear.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void gyear_simpl:: + pre (const gyear& value) + { + value_ = value; + } + + void gyear_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649+hh:mm") + 1 characters to + // hold all representations of gYear. + // + char str[18]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 12, "%.4d", value_.year ()); +#else + int n = sprintf (str, "%.4d", value_.year ()); +#endif + if (n > 0 && n < 12) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear.hxx b/libxsde/xsde/cxx/serializer/non-validating/gyear.hxx new file mode 100644 index 0000000..ea38751 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/gyear.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_simpl: virtual gyear_sskel +#else + struct gyear_simpl: gyear_sskel +#endif + { + gyear_simpl (); + + virtual void + pre (const gyear&); + + virtual void + _serialize_content (); + + protected: + gyear value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_GYEAR_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/gyear.ixx b/libxsde/xsde/cxx/serializer/non-validating/gyear.ixx new file mode 100644 index 0000000..f1db195 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/gyear.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/gyear.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline gyear_simpl:: + gyear_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/hex-binary.cxx b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.cxx new file mode 100644 index 0000000..f341ff2 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.cxx @@ -0,0 +1,70 @@ +// file : xsde/cxx/serializer/non-validating/hex-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + hex_binary_simpl:: + ~hex_binary_simpl () + { + if (free_) + delete const_cast (value_); + } + + void hex_binary_simpl:: + pre (const buffer* value) + { + value_ = value; + } + + static const char hex_tab[] = "0123456789ABCDEF"; + + void hex_binary_simpl:: + _serialize_content () + { + char buf[512]; + + size_t size = value_->size (); + const char* data = value_->data (); + + // Covert the data in 256-byte chunks. + // + for (size_t j = 0; j < size;) + { + size_t i = 0; + + for (; i < 512 && j < size; ++j) + { + unsigned char byte = static_cast (data[j]); + + buf[i++] = hex_tab[byte >> 4]; + buf[i++] = hex_tab[byte & 0x0F]; + } + +#ifdef XSDE_EXCEPTIONS + _characters (buf, i); +#else + if (!_characters (buf, i)) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/hex-binary.hxx b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.hxx new file mode 100644 index 0000000..eb10879 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/hex-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_HEX_BINARY_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_HEX_BINARY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct hex_binary_simpl: virtual hex_binary_sskel +#else + struct hex_binary_simpl: hex_binary_sskel +#endif + { + virtual + ~hex_binary_simpl (); + + hex_binary_simpl (bool free = false); + + virtual void + pre (const buffer*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const buffer* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_HEX_BINARY_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/hex-binary.ixx b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.ixx new file mode 100644 index 0000000..3305b15 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/hex-binary.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/hex-binary.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline hex_binary_simpl:: + hex_binary_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/id-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/id-stl.cxx new file mode 100644 index 0000000..ed63192 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/id-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/id-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void id_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void id_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/id-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/id-stl.hxx new file mode 100644 index 0000000..a615151 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/id-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/id-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_simpl: virtual id_sskel +#else + struct id_simpl: id_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/id.cxx b/libxsde/xsde/cxx/serializer/non-validating/id.cxx new file mode 100644 index 0000000..ab75ad5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/id.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/id.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + id_simpl:: + ~id_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void id_simpl:: + pre (const char* value) + { + value_ = value; + } + + void id_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/id.hxx b/libxsde/xsde/cxx/serializer/non-validating/id.hxx new file mode 100644 index 0000000..2c0563c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/id.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/id.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_simpl: virtual id_sskel +#else + struct id_simpl: id_sskel +#endif + { + virtual + ~id_simpl (); + + id_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_ID_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/id.ixx b/libxsde/xsde/cxx/serializer/non-validating/id.ixx new file mode 100644 index 0000000..22e4201 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/id.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/id.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline id_simpl:: + id_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idref-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/idref-stl.cxx new file mode 100644 index 0000000..2b128e7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idref-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/idref-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void idref_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void idref_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idref-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/idref-stl.hxx new file mode 100644 index 0000000..1fc6d08 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idref-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/idref-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_simpl: virtual idref_sskel +#else + struct idref_simpl: idref_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/idref.cxx b/libxsde/xsde/cxx/serializer/non-validating/idref.cxx new file mode 100644 index 0000000..527beb5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idref.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/idref.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + idref_simpl:: + ~idref_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void idref_simpl:: + pre (const char* value) + { + value_ = value; + } + + void idref_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idref.hxx b/libxsde/xsde/cxx/serializer/non-validating/idref.hxx new file mode 100644 index 0000000..295c701 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idref.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/idref.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_simpl: virtual idref_sskel +#else + struct idref_simpl: idref_sskel +#endif + { + virtual + ~idref_simpl (); + + idref_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREF_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/idref.ixx b/libxsde/xsde/cxx/serializer/non-validating/idref.ixx new file mode 100644 index 0000000..e558f2f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idref.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/idref.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline idref_simpl:: + idref_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.cxx new file mode 100644 index 0000000..75db514 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.cxx @@ -0,0 +1,108 @@ +// file : xsde/cxx/serializer/non-validating/idrefs-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + idrefs_simpl:: + ~idrefs_simpl () + { + if (free_) + delete const_cast (value_); + } + + void idrefs_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void idrefs_simpl:: + _serialize_content () + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { +#ifdef XSDE_EXCEPTIONS + serializer_.pre (*i); + + if (!first) + _characters (" ", 1); + else + first = false; + + serializer_._pre_impl (ctx); + serializer_._serialize_content (); + serializer_._post_impl (); + serializer_.post (); +#else + serializer_.pre (*i); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; + + if (!first) + { + if (!_characters (" ", 1)) + break; + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void idrefs_simpl:: + _reset () + { + idrefs_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.hxx new file mode 100644 index 0000000..bb88871 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/non-validating/idrefs-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_simpl: virtual idrefs_sskel +#else + struct idrefs_simpl: idrefs_sskel +#endif + { + virtual + ~idrefs_simpl (); + + idrefs_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + idref_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.ixx b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.ixx new file mode 100644 index 0000000..ff15241 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/idrefs-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline idrefs_simpl:: + idrefs_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs.cxx b/libxsde/xsde/cxx/serializer/non-validating/idrefs.cxx new file mode 100644 index 0000000..a795453 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs.cxx @@ -0,0 +1,109 @@ +// file : xsde/cxx/serializer/non-validating/idrefs.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + idrefs_simpl:: + ~idrefs_simpl () + { + if (free_) + delete const_cast (value_); + } + + void idrefs_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void idrefs_simpl:: + _serialize_content () + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { +#ifdef XSDE_EXCEPTIONS + serializer_.pre (*i); + + if (!first) + _characters (" ", 1); + else + first = false; + + serializer_._pre_impl (ctx); + serializer_._serialize_content (); + serializer_._post_impl (); + serializer_.post (); +#else + serializer_.pre (*i); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; + + if (!first) + { + if (!_characters (" ", 1)) + break; + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void idrefs_simpl:: + _reset () + { + idrefs_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs.hxx b/libxsde/xsde/cxx/serializer/non-validating/idrefs.hxx new file mode 100644 index 0000000..2eb7a9e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/non-validating/idrefs.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_simpl: virtual idrefs_sskel +#else + struct idrefs_simpl: idrefs_sskel +#endif + { + virtual + ~idrefs_simpl (); + + idrefs_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + idref_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_IDREFS_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/idrefs.ixx b/libxsde/xsde/cxx/serializer/non-validating/idrefs.ixx new file mode 100644 index 0000000..773270e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/idrefs.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/idrefs.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline idrefs_simpl:: + idrefs_simpl (bool free) + : free_ (free), value_ (0), serializer_ (false) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/int.cxx b/libxsde/xsde/cxx/serializer/non-validating/int.cxx new file mode 100644 index 0000000..ab318bc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/int.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void int_simpl:: + pre (int value) + { + value_ = value; + } + + void int_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649") + 1 characters to hold all + // representations of int. + // + char str[12]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 12, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 12) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/int.hxx b/libxsde/xsde/cxx/serializer/non-validating/int.hxx new file mode 100644 index 0000000..a4712ac --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/int.hxx @@ -0,0 +1,39 @@ +// file : xsde/cxx/serializer/non-validating/int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_INT_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_INT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct int_simpl: virtual int_sskel +#else + struct int_simpl: int_sskel +#endif + { + virtual void + pre (int); + + virtual void + _serialize_content (); + + protected: + int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_INT_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/integer.cxx b/libxsde/xsde/cxx/serializer/non-validating/integer.cxx new file mode 100644 index 0000000..a9928fd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/integer.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void integer_simpl:: + pre (long value) + { + value_ = value; + } + + void integer_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/integer.hxx b/libxsde/xsde/cxx/serializer/non-validating/integer.hxx new file mode 100644 index 0000000..da83119 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Arbitrary-length integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct integer_simpl: virtual integer_sskel +#else + struct integer_simpl: integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/language-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/language-stl.cxx new file mode 100644 index 0000000..ba60bdc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/language-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/language-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void language_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void language_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/language-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/language-stl.hxx new file mode 100644 index 0000000..b141c16 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/language-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/language-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_simpl: virtual language_sskel +#else + struct language_simpl: language_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/language.cxx b/libxsde/xsde/cxx/serializer/non-validating/language.cxx new file mode 100644 index 0000000..558edae --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/language.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/language.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + language_simpl:: + ~language_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void language_simpl:: + pre (const char* value) + { + value_ = value; + } + + void language_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/language.hxx b/libxsde/xsde/cxx/serializer/non-validating/language.hxx new file mode 100644 index 0000000..56ed635 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/language.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/language.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_simpl: virtual language_sskel +#else + struct language_simpl: language_sskel +#endif + { + virtual + ~language_simpl (); + + language_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_LANGUAGE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/language.ixx b/libxsde/xsde/cxx/serializer/non-validating/language.ixx new file mode 100644 index 0000000..3b51aad --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/language.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/language.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline language_simpl:: + language_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/long-long.cxx b/libxsde/xsde/cxx/serializer/non-validating/long-long.cxx new file mode 100644 index 0000000..364a71d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/long-long.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void long_simpl:: + pre (long long value) + { + value_ = value; + } + + void long_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of long long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lld", value_); +#else + int n = sprintf (str, "%lld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/long-long.hxx b/libxsde/xsde/cxx/serializer/non-validating/long-long.hxx new file mode 100644 index 0000000..545bb80 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/long-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_LONG_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 64-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_simpl: virtual long_sskel +#else + struct long_simpl: long_sskel +#endif + { + virtual void + pre (long long); + + virtual void + _serialize_content (); + + protected: + long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/long.cxx b/libxsde/xsde/cxx/serializer/non-validating/long.cxx new file mode 100644 index 0000000..7a9c121 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/long.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void long_simpl:: + pre (long value) + { + value_ = value; + } + + void long_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/long.hxx b/libxsde/xsde/cxx/serializer/non-validating/long.hxx new file mode 100644 index 0000000..a4c63e7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_simpl: virtual long_sskel +#else + struct long_simpl: long_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/name-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/name-stl.cxx new file mode 100644 index 0000000..d84fd65 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/name-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/name-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void name_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void name_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/name-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/name-stl.hxx new file mode 100644 index 0000000..f06b279 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/name-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/name-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_simpl: virtual name_sskel +#else + struct name_simpl: name_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/name.cxx b/libxsde/xsde/cxx/serializer/non-validating/name.cxx new file mode 100644 index 0000000..70cb5c3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/name.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/name.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + name_simpl:: + ~name_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void name_simpl:: + pre (const char* value) + { + value_ = value; + } + + void name_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/name.hxx b/libxsde/xsde/cxx/serializer/non-validating/name.hxx new file mode 100644 index 0000000..8a36591 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/name.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/name.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_simpl: virtual name_sskel +#else + struct name_simpl: name_sskel +#endif + { + virtual + ~name_simpl (); + + name_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NAME_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/name.ixx b/libxsde/xsde/cxx/serializer/non-validating/name.ixx new file mode 100644 index 0000000..f927928 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/name.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/name.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline name_simpl:: + name_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.cxx new file mode 100644 index 0000000..3e31290 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/ncname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void ncname_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void ncname_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.hxx new file mode 100644 index 0000000..781b513 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/ncname-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/ncname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_simpl: virtual ncname_sskel +#else + struct ncname_simpl: ncname_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/ncname.cxx b/libxsde/xsde/cxx/serializer/non-validating/ncname.cxx new file mode 100644 index 0000000..ba39a06 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/ncname.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/ncname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + ncname_simpl:: + ~ncname_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void ncname_simpl:: + pre (const char* value) + { + value_ = value; + } + + void ncname_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/ncname.hxx b/libxsde/xsde/cxx/serializer/non-validating/ncname.hxx new file mode 100644 index 0000000..93a85c5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/ncname.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/ncname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_simpl: virtual ncname_sskel +#else + struct ncname_simpl: ncname_sskel +#endif + { + virtual + ~ncname_simpl (); + + ncname_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NCNAME_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/ncname.ixx b/libxsde/xsde/cxx/serializer/non-validating/ncname.ixx new file mode 100644 index 0000000..36785d6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/ncname.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/ncname.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline ncname_simpl:: + ncname_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/negative-integer.cxx b/libxsde/xsde/cxx/serializer/non-validating/negative-integer.cxx new file mode 100644 index 0000000..713968d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/negative-integer.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void negative_integer_simpl:: + pre (long value) + { + value_ = value; + } + + void negative_integer_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/negative-integer.hxx b/libxsde/xsde/cxx/serializer/non-validating/negative-integer.hxx new file mode 100644 index 0000000..d8d7367 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/negative-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NEGATIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Arbitrary-length negative integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct negative_integer_simpl: virtual negative_integer_sskel +#else + struct negative_integer_simpl: negative_integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.cxx new file mode 100644 index 0000000..a23aa22 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/nmtoken-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void nmtoken_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void nmtoken_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.hxx new file mode 100644 index 0000000..e5b56b4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/nmtoken-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_simpl: virtual nmtoken_sskel +#else + struct nmtoken_simpl: nmtoken_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtoken.cxx b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.cxx new file mode 100644 index 0000000..45132f1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/nmtoken.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + nmtoken_simpl:: + ~nmtoken_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void nmtoken_simpl:: + pre (const char* value) + { + value_ = value; + } + + void nmtoken_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtoken.hxx b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.hxx new file mode 100644 index 0000000..14642c9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/nmtoken.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_simpl: virtual nmtoken_sskel +#else + struct nmtoken_simpl: nmtoken_sskel +#endif + { + virtual + ~nmtoken_simpl (); + + nmtoken_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKEN_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtoken.ixx b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.ixx new file mode 100644 index 0000000..68ebd47 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtoken.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/nmtoken.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline nmtoken_simpl:: + nmtoken_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.cxx new file mode 100644 index 0000000..afa663f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.cxx @@ -0,0 +1,108 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + nmtokens_simpl:: + ~nmtokens_simpl () + { + if (free_) + delete const_cast (value_); + } + + void nmtokens_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void nmtokens_simpl:: + _serialize_content () + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { +#ifdef XSDE_EXCEPTIONS + serializer_.pre (*i); + + if (!first) + _characters (" ", 1); + else + first = false; + + serializer_._pre_impl (ctx); + serializer_._serialize_content (); + serializer_._post_impl (); + serializer_.post (); +#else + serializer_.pre (*i); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; + + if (!first) + { + if (!_characters (" ", 1)) + break; + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void nmtokens_simpl:: + _reset () + { + nmtokens_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.hxx new file mode 100644 index 0000000..da6ec57 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_simpl: virtual nmtokens_sskel +#else + struct nmtokens_simpl: nmtokens_sskel +#endif + { + virtual + ~nmtokens_simpl (); + + nmtokens_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + nmtoken_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.ixx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.ixx new file mode 100644 index 0000000..b0236d8 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline nmtokens_simpl:: + nmtokens_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens.cxx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.cxx new file mode 100644 index 0000000..f430bda --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.cxx @@ -0,0 +1,109 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + nmtokens_simpl:: + ~nmtokens_simpl () + { + if (free_) + delete const_cast (value_); + } + + void nmtokens_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void nmtokens_simpl:: + _serialize_content () + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { +#ifdef XSDE_EXCEPTIONS + serializer_.pre (*i); + + if (!first) + _characters (" ", 1); + else + first = false; + + serializer_._pre_impl (ctx); + serializer_._serialize_content (); + serializer_._post_impl (); + serializer_.post (); +#else + serializer_.pre (*i); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; + + if (!first) + { + if (!_characters (" ", 1)) + break; + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void nmtokens_simpl:: + _reset () + { + nmtokens_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens.hxx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.hxx new file mode 100644 index 0000000..8a0f651 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_simpl: virtual nmtokens_sskel +#else + struct nmtokens_simpl: nmtokens_sskel +#endif + { + virtual + ~nmtokens_simpl (); + + nmtokens_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + nmtoken_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NMTOKENS_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/nmtokens.ixx b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.ixx new file mode 100644 index 0000000..43af4b2 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/nmtokens.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/nmtokens.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline nmtokens_simpl:: + nmtokens_simpl (bool free) + : free_ (free), value_ (0), serializer_ (false) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.cxx b/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.cxx new file mode 100644 index 0000000..8a3ee77 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/non-negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void non_negative_integer_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void non_negative_integer_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.hxx b/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.hxx new file mode 100644 index 0000000..ba9e1f3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/non-negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Arbitrary-length non-negative integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_negative_integer_simpl: virtual non_negative_integer_sskel +#else + struct non_negative_integer_simpl: non_negative_integer_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.cxx b/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.cxx new file mode 100644 index 0000000..4aa51d0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/non-positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void non_positive_integer_simpl:: + pre (long value) + { + value_ = value; + } + + void non_positive_integer_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.hxx b/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.hxx new file mode 100644 index 0000000..5e8c212 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/non-positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Arbitrary-length non-positive integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_positive_integer_simpl: virtual non_positive_integer_sskel +#else + struct non_positive_integer_simpl: non_positive_integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NON_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.cxx new file mode 100644 index 0000000..c96c9cf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.cxx @@ -0,0 +1,36 @@ +// file : xsde/cxx/serializer/non-validating/normalized-string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void normalized_string_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void normalized_string_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.hxx new file mode 100644 index 0000000..65da3b6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/normalized-string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_simpl: virtual normalized_string_sskel +#else + struct normalized_string_simpl: normalized_string_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/normalized-string.cxx b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.cxx new file mode 100644 index 0000000..fd69cec --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.cxx @@ -0,0 +1,44 @@ +// file : xsde/cxx/serializer/non-validating/normalized-string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + normalized_string_simpl:: + ~normalized_string_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void normalized_string_simpl:: + pre (const char* value) + { + value_ = value; + } + + void normalized_string_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/non-validating/normalized-string.hxx b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.hxx new file mode 100644 index 0000000..1ae4270 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/normalized-string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_simpl: virtual normalized_string_sskel +#else + struct normalized_string_simpl: normalized_string_sskel +#endif + { + virtual + ~normalized_string_simpl (); + + normalized_string_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_NORMALIZED_STRING_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/normalized-string.ixx b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.ixx new file mode 100644 index 0000000..627b93a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/normalized-string.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/normalized-string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline normalized_string_simpl:: + normalized_string_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/positive-integer.cxx b/libxsde/xsde/cxx/serializer/non-validating/positive-integer.cxx new file mode 100644 index 0000000..193499e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/positive-integer.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void positive_integer_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void positive_integer_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/positive-integer.hxx b/libxsde/xsde/cxx/serializer/non-validating/positive-integer.hxx new file mode 100644 index 0000000..397e904 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/positive-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_POSITIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_POSITIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Arbitrary-length positive integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct positive_integer_simpl: virtual positive_integer_sskel +#else + struct positive_integer_simpl: positive_integer_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.cxx new file mode 100644 index 0000000..92c0b57 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.cxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/serializer/non-validating/qname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void qname_simpl:: + pre (const qname& value) + { + value_ = value; + } + + void qname_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the qname. + // + qname tmp ("a"); + tmp.swap (value_); + + if (!tmp.prefix ().empty ()) + { +#ifdef XSDE_EXCEPTIONS + _characters (tmp.prefix ().c_str (), tmp.prefix ().size ()); + _characters (":", 1); + _characters (tmp.name ().c_str (), tmp.name ().size ()); +#else + if (_characters (tmp.prefix ().c_str (), tmp.prefix ().size ())) + { + if (_characters (":", 1)) + _characters (tmp.name ().c_str (), tmp.name ().size ()); + } +#endif + } + else + _characters (tmp.name ().c_str (), tmp.name ().size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.hxx new file mode 100644 index 0000000..9163de5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/qname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_STL_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_simpl: virtual qname_sskel +#else + struct qname_simpl: qname_sskel +#endif + { + qname_simpl (); + + virtual void + pre (const qname&); + + virtual void + _serialize_content (); + + protected: + qname value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname-stl.ixx b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.ixx new file mode 100644 index 0000000..d4bff2d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/qname-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline qname_simpl:: + qname_simpl () + : value_ ("a") + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname.cxx b/libxsde/xsde/cxx/serializer/non-validating/qname.cxx new file mode 100644 index 0000000..d2e41ff --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname.cxx @@ -0,0 +1,62 @@ +// file : xsde/cxx/serializer/non-validating/qname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + qname_simpl:: + ~qname_simpl () + { + if (free_) + delete const_cast (value_); + } + + void qname_simpl:: + pre (const qname* value) + { + value_ = value; + } + + void qname_simpl:: + _serialize_content () + { + const char* p = value_->prefix (); + + if (p != 0 && *p != '\0') + { +#ifdef XSDE_EXCEPTIONS + _characters (p); + _characters (":", 1); + _characters (value_->name ()); +#else + if (_characters (p)) + { + if (_characters (":", 1)) + _characters (value_->name ()); + } +#endif + } + else + { + _characters (value_->name ()); + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname.hxx b/libxsde/xsde/cxx/serializer/non-validating/qname.hxx new file mode 100644 index 0000000..4916726 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/qname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_simpl: virtual qname_sskel +#else + struct qname_simpl: qname_sskel +#endif + { + virtual + ~qname_simpl (); + + qname_simpl (bool free = false); + + virtual void + pre (const qname*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const qname* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_QNAME_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/qname.ixx b/libxsde/xsde/cxx/serializer/non-validating/qname.ixx new file mode 100644 index 0000000..e89b8b9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/qname.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/qname.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline qname_simpl:: + qname_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/serializer.cxx b/libxsde/xsde/cxx/serializer/non-validating/serializer.cxx new file mode 100644 index 0000000..7da8599 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/serializer.cxx @@ -0,0 +1,29 @@ +// file : xsde/cxx/serializer/non-validating/serializer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + void simple_content:: + _serialize_content () + { + if (impl_) + impl_->_serialize_content (); + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/serializer.hxx b/libxsde/xsde/cxx/serializer/non-validating/serializer.hxx new file mode 100644 index 0000000..c01476b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/serializer.hxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/serializer/non-validating/serializer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_SERIALIZER_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_SERIALIZER_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + struct empty_content: serializer_base + { +#ifdef XSDE_REUSE_STYLE_TIEIN + empty_content (); + empty_content (empty_content* impl, void*); +#endif + }; + + // + // + struct simple_content: empty_content + { +#ifdef XSDE_REUSE_STYLE_TIEIN + virtual void + _serialize_content (); + + simple_content (); + simple_content (simple_content* impl, void*); +#endif + }; + + // + // + struct complex_content: empty_content + { +#ifdef XSDE_REUSE_STYLE_TIEIN + complex_content (); + complex_content (complex_content* impl, void*); +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_SERIALIZER_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/serializer.ixx b/libxsde/xsde/cxx/serializer/non-validating/serializer.ixx new file mode 100644 index 0000000..b8eacee --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/serializer.ixx @@ -0,0 +1,61 @@ +// file : xsde/cxx/serializer/non-validating/serializer.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // empty_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline empty_content:: + empty_content () + { + } + + inline empty_content:: + empty_content (empty_content* impl, void*) + : serializer_base (impl, 0) + { + } +#endif + + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline simple_content:: + simple_content () + { + } + + inline simple_content:: + simple_content (simple_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + + // complex_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline complex_content:: + complex_content () + { + } + + inline complex_content:: + complex_content (complex_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/short.cxx b/libxsde/xsde/cxx/serializer/non-validating/short.cxx new file mode 100644 index 0000000..ad14306 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/short.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void short_simpl:: + pre (short value) + { + value_ = value; + } + + void short_simpl:: + _serialize_content () + { + // We only need strlen("-32768") + 1 characters to hold all + // representations of short. + // + char str[7]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 7, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 7) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/short.hxx b/libxsde/xsde/cxx/serializer/non-validating/short.hxx new file mode 100644 index 0000000..fb763e7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/short.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_SHORT_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_SHORT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 16-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct short_simpl: virtual short_sskel +#else + struct short_simpl: short_sskel +#endif + { + virtual void + pre (short); + + virtual void + _serialize_content (); + + protected: + short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_SHORT_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/string-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/string-stl.cxx new file mode 100644 index 0000000..28ba3e9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/string-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void string_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void string_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/string-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/string-stl.hxx new file mode 100644 index 0000000..0aee653 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/string-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_simpl: virtual string_sskel +#else + struct string_simpl: string_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/string.cxx b/libxsde/xsde/cxx/serializer/non-validating/string.cxx new file mode 100644 index 0000000..a56b3fa --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/string.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + string_simpl:: + ~string_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void string_simpl:: + pre (const char* value) + { + value_ = value; + } + + void string_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/string.hxx b/libxsde/xsde/cxx/serializer/non-validating/string.hxx new file mode 100644 index 0000000..913e2de --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/string.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_simpl: virtual string_sskel +#else + struct string_simpl: string_sskel +#endif + { + virtual + ~string_simpl (); + + string_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_STRING_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/string.ixx b/libxsde/xsde/cxx/serializer/non-validating/string.ixx new file mode 100644 index 0000000..b620835 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/string.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline string_simpl:: + string_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/time-zone.cxx b/libxsde/xsde/cxx/serializer/non-validating/time-zone.cxx new file mode 100644 index 0000000..8f374cf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/time-zone.cxx @@ -0,0 +1,65 @@ +// file : xsde/cxx/serializer/non-validating/time-zone.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + namespace bits + { + int + serialize_time_zone (char* s, const time_zone& z) + { + // time-zone := Z|(+|-)HH:MM + // + + short h = z.zone_hours (); + short m = z.zone_minutes (); + + if (h == 0 && m == 0) + { + *s = 'Z'; + return 1; + } + else + { + const char* fmt = "+%.2u:%.2u"; + + if (h < 0 || m < 0) + { + fmt = "-%.2u:%.2u"; + h = -h; + m = -m; + } + + if (h >= 0 && h <= 14 && m >= 0 && m <= 59) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (s, 7, fmt, h, m); +#else + int n = sprintf (s, fmt, h, m); +#endif + if (n > 0 && n < 7) + return n; + } + + return 0; + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/time-zone.hxx b/libxsde/xsde/cxx/serializer/non-validating/time-zone.hxx new file mode 100644 index 0000000..3a342b4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/time-zone.hxx @@ -0,0 +1,33 @@ +// file : xsde/cxx/serializer/non-validating/time-zone.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_ZONE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_ZONE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + namespace bits + { + // Returns 0 in case of a failure and the number of + // characters written otherwise. The buffer should + // have space for at least 7 characters. + // + int + serialize_time_zone (char* s, const time_zone&); + } + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_ZONE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/time.cxx b/libxsde/xsde/cxx/serializer/non-validating/time.cxx new file mode 100644 index 0000000..7643d12 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/time.cxx @@ -0,0 +1,73 @@ +// file : xsde/cxx/serializer/non-validating/time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void time_simpl:: + pre (const time& value) + { + value_ = value; + } + + void time_simpl:: + _serialize_content () + { + // We only need strlen("hh:mm:ss.ssssss-hh:mm") + 1 characters to + // hold all representations of time. We know that the seconds + // part (represented as double) has default precision of 6. + // + char str[22]; + + if (value_.hours () <= 24 && + value_.minutes () <= 59 && + value_.seconds () >= 0.0 && + value_.seconds () < 60.0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 16, "%.2u:%.2u:%09f", + value_.hours (), value_.minutes (), + value_.seconds ()); +#else + int n = sprintf (str, "%.2u:%.2u:%09f", + value_.hours (), value_.minutes (), + value_.seconds ()); +#endif + if (n > 0 && n < 16) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + return; + } + + _characters (str, static_cast (n)); + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/time.hxx b/libxsde/xsde/cxx/serializer/non-validating/time.hxx new file mode 100644 index 0000000..69680c5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/time.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct time_simpl: virtual time_sskel +#else + struct time_simpl: time_sskel +#endif + { + time_simpl (); + + virtual void + pre (const time&); + + virtual void + _serialize_content (); + + protected: + time value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_TIME_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/time.ixx b/libxsde/xsde/cxx/serializer/non-validating/time.ixx new file mode 100644 index 0000000..9a99cb6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/time.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/time.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline time_simpl:: + time_simpl () + : value_ (0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/token-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/token-stl.cxx new file mode 100644 index 0000000..baf257a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/token-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/token-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void token_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void token_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/token-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/token-stl.hxx new file mode 100644 index 0000000..458cb6d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/token-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/token-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_simpl: virtual token_sskel +#else + struct token_simpl: token_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/token.cxx b/libxsde/xsde/cxx/serializer/non-validating/token.cxx new file mode 100644 index 0000000..e2bfd0e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/token.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/token.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + token_simpl:: + ~token_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void token_simpl:: + pre (const char* value) + { + value_ = value; + } + + void token_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/token.hxx b/libxsde/xsde/cxx/serializer/non-validating/token.hxx new file mode 100644 index 0000000..0133fd5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/token.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/token.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_simpl: virtual token_sskel +#else + struct token_simpl: token_sskel +#endif + { + virtual + ~token_simpl (); + + token_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_TOKEN_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/token.ixx b/libxsde/xsde/cxx/serializer/non-validating/token.ixx new file mode 100644 index 0000000..9cb8594 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/token.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/token.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline token_simpl:: + token_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.cxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.cxx new file mode 100644 index 0000000..3d39100 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void unsigned_byte_simpl:: + pre (unsigned char value) + { + value_ = value; + } + + void unsigned_byte_simpl:: + _serialize_content () + { + // We only need strlen("256") + 1 characters to hold all + // representations of unsigned byte. + // + char str[4]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 4, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 4) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.hxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.hxx new file mode 100644 index 0000000..9c4f45e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_BYTE_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_BYTE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 8-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_byte_simpl: virtual unsigned_byte_sskel +#else + struct unsigned_byte_simpl: unsigned_byte_sskel +#endif + { + virtual void + pre (unsigned char); + + virtual void + _serialize_content (); + + protected: + unsigned char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_BYTE_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.cxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.cxx new file mode 100644 index 0000000..5f9f73a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void unsigned_int_simpl:: + pre (unsigned int value) + { + value_ = value; + } + + void unsigned_int_simpl:: + _serialize_content () + { + // We only need strlen("4294967295") + 1 characters to hold all + // representations of unsigned int. + // + char str[11]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 11, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 11) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.hxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.hxx new file mode 100644 index 0000000..66e88d0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-int.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_INT_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_INT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 32-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_int_simpl: virtual unsigned_int_sskel +#else + struct unsigned_int_simpl: unsigned_int_sskel +#endif + { + virtual void + pre (unsigned int); + + virtual void + _serialize_content (); + + protected: + unsigned int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_INT_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.cxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.cxx new file mode 100644 index 0000000..6e62f87 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void unsigned_long_simpl:: + pre (unsigned long long value) + { + value_ = value; + } + + void unsigned_long_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of unsigned long long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%llu", value_); +#else + int n = sprintf (str, "%llu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.hxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.hxx new file mode 100644 index 0000000..34ea158 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 64-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_simpl: virtual unsigned_long_sskel +#else + struct unsigned_long_simpl: unsigned_long_sskel +#endif + { + virtual void + pre (unsigned long long); + + virtual void + _serialize_content (); + + protected: + unsigned long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.cxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.cxx new file mode 100644 index 0000000..fd70eaf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void unsigned_long_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void unsigned_long_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.hxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.hxx new file mode 100644 index 0000000..ba061d3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_simpl: virtual unsigned_long_sskel +#else + struct unsigned_long_simpl: unsigned_long_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.cxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.cxx new file mode 100644 index 0000000..ffe29e1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void unsigned_short_simpl:: + pre (unsigned short value) + { + value_ = value; + } + + void unsigned_short_simpl:: + _serialize_content () + { + // We only need strlen("65535") + 1 characters to hold all + // representations of short. + // + char str[6]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 6, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 6) + _characters (str, static_cast (n)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.hxx b/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.hxx new file mode 100644 index 0000000..ffde97c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/unsigned-short.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/unsigned-short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_SHORT_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_SHORT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // 16-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_short_simpl: virtual unsigned_short_sskel +#else + struct unsigned_short_simpl: unsigned_short_sskel +#endif + { + virtual void + pre (unsigned short); + + virtual void + _serialize_content (); + + protected: + unsigned short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_UNSIGNED_SHORT_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/uri-stl.cxx b/libxsde/xsde/cxx/serializer/non-validating/uri-stl.cxx new file mode 100644 index 0000000..c109227 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/uri-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/non-validating/uri-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + void uri_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void uri_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/uri-stl.hxx b/libxsde/xsde/cxx/serializer/non-validating/uri-stl.hxx new file mode 100644 index 0000000..38310e5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/uri-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/non-validating/uri-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_STL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_simpl: virtual uri_sskel +#else + struct uri_simpl: uri_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/uri.cxx b/libxsde/xsde/cxx/serializer/non-validating/uri.cxx new file mode 100644 index 0000000..372c88d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/uri.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/non-validating/uri.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + uri_simpl:: + ~uri_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void uri_simpl:: + pre (const char* value) + { + value_ = value; + } + + void uri_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/uri.hxx b/libxsde/xsde/cxx/serializer/non-validating/uri.hxx new file mode 100644 index 0000000..86a3c47 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/uri.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/non-validating/uri.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_simpl: virtual uri_sskel +#else + struct uri_simpl: uri_sskel +#endif + { + virtual + ~uri_simpl (); + + uri_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_URI_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/uri.ixx b/libxsde/xsde/cxx/serializer/non-validating/uri.ixx new file mode 100644 index 0000000..d9dcd79 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/uri.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/non-validating/uri.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + inline uri_simpl:: + uri_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx new file mode 100644 index 0000000..adda9fd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx @@ -0,0 +1,82 @@ +// file : xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SIMPL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SIMPL_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_LONGLONG +# include +# include +#else +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_STL +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SIMPL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx new file mode 100644 index 0000000..f9bb0b1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx @@ -0,0 +1,560 @@ +// file : xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // any_type_sskel + // + void any_type_sskel:: + pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_type_impl_) + any_type_impl_->pre (); +#endif + } + + // any_simple_type_sskel + // + void any_simple_type_sskel:: + pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_simple_type_impl_) + any_simple_type_impl_->pre (); +#endif + } + + // static/dynamic_type function implementations. + // +#ifdef XSDE_POLYMORPHIC + const char* any_type_sskel:: + _static_type () + { + return "anyType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_type_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* any_simple_type_sskel:: + _static_type () + { + return "anySimpleType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_simple_type_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* boolean_sskel:: + _static_type () + { + return "boolean http://www.w3.org/2001/XMLSchema"; + } + + const char* boolean_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* byte_sskel:: + _static_type () + { + return "byte http://www.w3.org/2001/XMLSchema"; + } + + const char* byte_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_byte_sskel:: + _static_type () + { + return "unsignedByte http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_byte_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* short_sskel:: + _static_type () + { + return "short http://www.w3.org/2001/XMLSchema"; + } + + const char* short_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_short_sskel:: + _static_type () + { + return "unsignedShort http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_short_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* int_sskel:: + _static_type () + { + return "int http://www.w3.org/2001/XMLSchema"; + } + + const char* int_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_int_sskel:: + _static_type () + { + return "unsignedInt http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_int_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* long_sskel:: + _static_type () + { + return "long http://www.w3.org/2001/XMLSchema"; + } + + const char* long_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_long_sskel:: + _static_type () + { + return "unsignedLong http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_long_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* integer_sskel:: + _static_type () + { + return "integer http://www.w3.org/2001/XMLSchema"; + } + + const char* integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* negative_integer_sskel:: + _static_type () + { + return "negativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* negative_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_positive_integer_sskel:: + _static_type () + { + return "nonPositiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_positive_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* positive_integer_sskel:: + _static_type () + { + return "positiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* positive_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_negative_integer_sskel:: + _static_type () + { + return "nonNegativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_negative_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* float_sskel:: + _static_type () + { + return "float http://www.w3.org/2001/XMLSchema"; + } + + const char* float_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* double_sskel:: + _static_type () + { + return "double http://www.w3.org/2001/XMLSchema"; + } + + const char* double_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* decimal_sskel:: + _static_type () + { + return "decimal http://www.w3.org/2001/XMLSchema"; + } + + const char* decimal_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* string_sskel:: + _static_type () + { + return "string http://www.w3.org/2001/XMLSchema"; + } + + const char* string_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* normalized_string_sskel:: + _static_type () + { + return "normalizedString http://www.w3.org/2001/XMLSchema"; + } + + const char* normalized_string_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* token_sskel:: + _static_type () + { + return "token http://www.w3.org/2001/XMLSchema"; + } + + const char* token_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* name_sskel:: + _static_type () + { + return "Name http://www.w3.org/2001/XMLSchema"; + } + + const char* name_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtoken_sskel:: + _static_type () + { + return "NMTOKEN http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtoken_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtokens_sskel:: + _static_type () + { + return "NMTOKENS http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtokens_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* ncname_sskel:: + _static_type () + { + return "NCName http://www.w3.org/2001/XMLSchema"; + } + + const char* ncname_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* id_sskel:: + _static_type () + { + return "ID http://www.w3.org/2001/XMLSchema"; + } + + const char* id_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idref_sskel:: + _static_type () + { + return "IDREF http://www.w3.org/2001/XMLSchema"; + } + + const char* idref_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idrefs_sskel:: + _static_type () + { + return "IDREFS http://www.w3.org/2001/XMLSchema"; + } + + const char* idrefs_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* language_sskel:: + _static_type () + { + return "language http://www.w3.org/2001/XMLSchema"; + } + + const char* language_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* uri_sskel:: + _static_type () + { + return "anyURI http://www.w3.org/2001/XMLSchema"; + } + + const char* uri_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* qname_sskel:: + _static_type () + { + return "QName http://www.w3.org/2001/XMLSchema"; + } + + const char* qname_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* base64_binary_sskel:: + _static_type () + { + return "base64Binary http://www.w3.org/2001/XMLSchema"; + } + + const char* base64_binary_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* hex_binary_sskel:: + _static_type () + { + return "hexBinary http://www.w3.org/2001/XMLSchema"; + } + + const char* hex_binary_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gday_sskel:: + _static_type () + { + return "gDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gday_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_sskel:: + _static_type () + { + return "gMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_sskel:: + _static_type () + { + return "gYear http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_day_sskel:: + _static_type () + { + return "gMonthDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_day_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_month_sskel:: + _static_type () + { + return "gYearMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_month_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_sskel:: + _static_type () + { + return "date http://www.w3.org/2001/XMLSchema"; + } + + const char* date_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* time_sskel:: + _static_type () + { + return "time http://www.w3.org/2001/XMLSchema"; + } + + const char* time_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_time_sskel:: + _static_type () + { + return "dateTime http://www.w3.org/2001/XMLSchema"; + } + + const char* date_time_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* duration_sskel:: + _static_type () + { + return "duration http://www.w3.org/2001/XMLSchema"; + } + + const char* duration_sskel:: + _dynamic_type () const + { + return _static_type (); + } +#endif // XSDE_POLYMORPHIC + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx new file mode 100644 index 0000000..9365f03 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx @@ -0,0 +1,1382 @@ +// file : xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SSKEL_HXX +#define XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SSKEL_HXX + +#include + +#ifdef XSDE_STL +# include +#endif + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // anyType and anySimpleType. + // + struct any_type_sskel: complex_content + { + virtual void + pre (); + + // Override the following two functions to implement + // your logic. + // + + // virtual void + // _serialize_attributes (); + + // virtual void + // _serialize_content (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_type_sskel (); + any_type_sskel (any_type_sskel* impl, void*); + + protected: + any_type_sskel* any_type_impl_; +#endif + }; + + struct any_simple_type_sskel: simple_content + { + virtual void + pre (); + + // Override the following function to implement your + // logic. + // + + // virtual void + // _serialize_content (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_simple_type_sskel (); + any_simple_type_sskel (any_simple_type_sskel* impl, void*); + + protected: + any_simple_type_sskel* any_simple_type_impl_; +#endif + }; + + // Boolean. + // + struct boolean_sskel: simple_content + { + virtual void + pre (bool) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + boolean_sskel (); + boolean_sskel (boolean_sskel* impl, void*); + + protected: + boolean_sskel* boolean_impl_; +#endif + }; + + // 8-bit + // + + struct byte_sskel: simple_content + { + virtual void + pre (signed char) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + byte_sskel (); + byte_sskel (byte_sskel* impl, void*); + + protected: + byte_sskel* byte_impl_; +#endif + }; + + struct unsigned_byte_sskel: simple_content + { + virtual void + pre (unsigned char) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_byte_sskel (); + unsigned_byte_sskel (unsigned_byte_sskel* impl, void*); + + protected: + unsigned_byte_sskel* unsigned_byte_impl_; +#endif + }; + + + // 16-bit + // + + struct short_sskel: simple_content + { + virtual void + pre (short) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + short_sskel (); + short_sskel (short_sskel* impl, void*); + + protected: + short_sskel* short_impl_; +#endif + }; + + struct unsigned_short_sskel: simple_content + { + virtual void + pre (unsigned short) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_short_sskel (); + unsigned_short_sskel (unsigned_short_sskel* impl, void*); + + protected: + unsigned_short_sskel* unsigned_short_impl_; +#endif + }; + + // 32-bit + // + + struct int_sskel: simple_content + { + virtual void + pre (int) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + int_sskel (); + int_sskel (int_sskel* impl, void*); + + protected: + int_sskel* int_impl_; +#endif + }; + + struct unsigned_int_sskel: simple_content + { + virtual void + pre (unsigned int) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_int_sskel (); + unsigned_int_sskel (unsigned_int_sskel* impl, void*); + + protected: + unsigned_int_sskel* unsigned_int_impl_; +#endif + }; + + // 64-bit + // + +#ifdef XSDE_LONGLONG + struct long_sskel: simple_content + { + virtual void + pre (long long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_sskel (); + long_sskel (long_sskel* impl, void*); + + protected: + long_sskel* long_impl_; +#endif + }; + + struct unsigned_long_sskel: simple_content + { + virtual void + pre (unsigned long long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_sskel (); + unsigned_long_sskel (unsigned_long_sskel* impl, void*); + + protected: + unsigned_long_sskel* unsigned_long_impl_; +#endif + }; +#else + struct long_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_sskel (); + long_sskel (long_sskel* impl, void*); + + protected: + long_sskel* long_impl_; +#endif + }; + + struct unsigned_long_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_sskel (); + unsigned_long_sskel (unsigned_long_sskel* impl, void*); + + protected: + unsigned_long_sskel* unsigned_long_impl_; +#endif + }; +#endif + + // Arbitrary-length integers. + // + + struct integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + integer_sskel (); + integer_sskel (integer_sskel* impl, void*); + + protected: + integer_sskel* integer_impl_; +#endif + }; + + struct negative_integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + negative_integer_sskel (); + negative_integer_sskel (negative_integer_sskel* impl, void*); + + protected: + negative_integer_sskel* negative_integer_impl_; +#endif + }; + + struct non_positive_integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_positive_integer_sskel (); + non_positive_integer_sskel (non_positive_integer_sskel* impl, void*); + + protected: + non_positive_integer_sskel* non_positive_integer_impl_; +#endif + }; + + struct positive_integer_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + positive_integer_sskel (); + positive_integer_sskel (positive_integer_sskel* impl, void*); + + protected: + positive_integer_sskel* positive_integer_impl_; +#endif + }; + + struct non_negative_integer_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_negative_integer_sskel (); + non_negative_integer_sskel (non_negative_integer_sskel* impl, void*); + + protected: + non_negative_integer_sskel* non_negative_integer_impl_; +#endif + }; + + // Floats. + // + + struct float_sskel: simple_content + { + virtual void + pre (float) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + float_sskel (); + float_sskel (float_sskel* impl, void*); + + protected: + float_sskel* float_impl_; +#endif + }; + + struct double_sskel: simple_content + { + virtual void + pre (double) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + double_sskel (); + double_sskel (double_sskel* impl, void*); + + protected: + double_sskel* double_impl_; +#endif + }; + + struct decimal_sskel: simple_content + { + virtual void + pre (double) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + decimal_sskel (); + decimal_sskel (decimal_sskel* impl, void*); + + protected: + decimal_sskel* decimal_impl_; +#endif + }; + + // String-based types. + // +#ifdef XSDE_STL + + struct string_sskel: simple_content + { + virtual void + pre (const std::string&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_sskel (); + string_sskel (string_sskel* impl, void*); + + protected: + string_sskel* string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_sskel: virtual string_sskel +#else + struct normalized_string_sskel: string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_sskel (); + normalized_string_sskel (normalized_string_sskel* impl, void*); + + protected: + normalized_string_sskel* normalized_string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_sskel: virtual normalized_string_sskel +#else + struct token_sskel: normalized_string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_sskel (); + token_sskel (token_sskel* impl, void*); + + protected: + token_sskel* token_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_sskel: virtual token_sskel +#else + struct name_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_sskel (); + name_sskel (name_sskel* impl, void*); + + protected: + name_sskel* name_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_sskel: virtual token_sskel +#else + struct nmtoken_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_sskel (); + nmtoken_sskel (nmtoken_sskel* impl, void*); + + protected: + nmtoken_sskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_sskel (); + nmtokens_sskel (nmtokens_sskel* impl, void*); + + protected: + nmtokens_sskel* nmtokens_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_sskel: virtual name_sskel +#else + struct ncname_sskel: name_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_sskel (); + ncname_sskel (ncname_sskel* impl, void*); + + protected: + ncname_sskel* ncname_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_sskel: virtual ncname_sskel +#else + struct id_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_sskel (); + id_sskel (id_sskel* impl, void*); + + protected: + id_sskel* id_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_sskel: virtual ncname_sskel +#else + struct idref_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_sskel (); + idref_sskel (idref_sskel* impl, void*); + + protected: + idref_sskel* idref_impl_; +#endif + }; + + struct idrefs_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_sskel (); + idrefs_sskel (idrefs_sskel* impl, void*); + + protected: + idrefs_sskel* idrefs_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_sskel: virtual token_sskel +#else + struct language_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_sskel (); + language_sskel (language_sskel* impl, void*); + + protected: + language_sskel* language_impl_; +#endif + }; + + struct uri_sskel: simple_content + { + virtual void + pre (const std::string&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_sskel (); + uri_sskel (uri_sskel* impl, void*); + + protected: + uri_sskel* uri_impl_; +#endif + }; + + struct qname_sskel: simple_content + { + virtual void + pre (const qname&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_sskel (); + qname_sskel (qname_sskel* impl, void*); + + protected: + qname_sskel* qname_impl_; +#endif + }; + +#else // XSDE_STL + + struct string_sskel: simple_content + { + virtual void + pre (const char*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_sskel (); + string_sskel (string_sskel* impl, void*); + + protected: + string_sskel* string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_sskel: virtual string_sskel +#else + struct normalized_string_sskel: string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_sskel (); + normalized_string_sskel (normalized_string_sskel* impl, void*); + + protected: + normalized_string_sskel* normalized_string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_sskel: virtual normalized_string_sskel +#else + struct token_sskel: normalized_string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_sskel (); + token_sskel (token_sskel* impl, void*); + + protected: + token_sskel* token_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_sskel: virtual token_sskel +#else + struct name_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_sskel (); + name_sskel (name_sskel* impl, void*); + + protected: + name_sskel* name_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_sskel: virtual token_sskel +#else + struct nmtoken_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_sskel (); + nmtoken_sskel (nmtoken_sskel* impl, void*); + + protected: + nmtoken_sskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_sskel (); + nmtokens_sskel (nmtokens_sskel* impl, void*); + + protected: + nmtokens_sskel* nmtokens_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_sskel: virtual name_sskel +#else + struct ncname_sskel: name_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_sskel (); + ncname_sskel (ncname_sskel* impl, void*); + + protected: + ncname_sskel* ncname_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_sskel: virtual ncname_sskel +#else + struct id_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_sskel (); + id_sskel (id_sskel* impl, void*); + + protected: + id_sskel* id_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_sskel: virtual ncname_sskel +#else + struct idref_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_sskel (); + idref_sskel (idref_sskel* impl, void*); + + protected: + idref_sskel* idref_impl_; +#endif + }; + + struct idrefs_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_sskel (); + idrefs_sskel (idrefs_sskel* impl, void*); + + protected: + idrefs_sskel* idrefs_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_sskel: virtual token_sskel +#else + struct language_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_sskel (); + language_sskel (language_sskel* impl, void*); + + protected: + language_sskel* language_impl_; +#endif + }; + + struct uri_sskel: simple_content + { + virtual void + pre (const char*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_sskel (); + uri_sskel (uri_sskel* impl, void*); + + protected: + uri_sskel* uri_impl_; +#endif + }; + + struct qname_sskel: simple_content + { + virtual void + pre (const qname*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_sskel (); + qname_sskel (qname_sskel* impl, void*); + + protected: + qname_sskel* qname_impl_; +#endif + }; + +#endif // XSDE_STL + + + // base64Binary + // + struct base64_binary_sskel: simple_content + { + virtual void + pre (const buffer*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + base64_binary_sskel (); + base64_binary_sskel (base64_binary_sskel* impl, void*); + + protected: + base64_binary_sskel* base64_binary_impl_; +#endif + }; + + // hexBinary + // + struct hex_binary_sskel: simple_content + { + virtual void + pre (const buffer*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + hex_binary_sskel (); + hex_binary_sskel (hex_binary_sskel* impl, void*); + + protected: + hex_binary_sskel* hex_binary_impl_; +#endif + }; + + // Time and date types. + // + struct gday_sskel: simple_content + { + virtual void + pre (const gday&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gday_sskel (); + gday_sskel (gday_sskel* impl, void*); + + protected: + gday_sskel* gday_impl_; +#endif + }; + + struct gmonth_sskel: simple_content + { + virtual void + pre (const gmonth&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_sskel (); + gmonth_sskel (gmonth_sskel* impl, void*); + + protected: + gmonth_sskel* gmonth_impl_; +#endif + }; + + struct gyear_sskel: simple_content + { + virtual void + pre (const gyear&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_sskel (); + gyear_sskel (gyear_sskel* impl, void*); + + protected: + gyear_sskel* gyear_impl_; +#endif + }; + + struct gmonth_day_sskel: simple_content + { + virtual void + pre (const gmonth_day&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_day_sskel (); + gmonth_day_sskel (gmonth_day_sskel* impl, void*); + + protected: + gmonth_day_sskel* gmonth_day_impl_; +#endif + }; + + struct gyear_month_sskel: simple_content + { + virtual void + pre (const gyear_month&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_month_sskel (); + gyear_month_sskel (gyear_month_sskel* impl, void*); + + protected: + gyear_month_sskel* gyear_month_impl_; +#endif + }; + + struct date_sskel: simple_content + { + virtual void + pre (const date&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_sskel (); + date_sskel (date_sskel* impl, void*); + + protected: + date_sskel* date_impl_; +#endif + }; + + struct time_sskel: simple_content + { + virtual void + pre (const time&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + time_sskel (); + time_sskel (time_sskel* impl, void*); + + protected: + time_sskel* time_impl_; +#endif + }; + + struct date_time_sskel: simple_content + { + virtual void + pre (const date_time&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_time_sskel (); + date_time_sskel (date_time_sskel* impl, void*); + + protected: + date_time_sskel* date_time_impl_; +#endif + }; + + struct duration_sskel: simple_content + { + virtual void + pre (const duration&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + duration_sskel (); + duration_sskel (duration_sskel* impl, void*); + + protected: + duration_sskel* duration_impl_; +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_NON_VALIDATING_XML_SCHEMA_SSKEL_HXX diff --git a/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx new file mode 100644 index 0000000..de78f5d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx @@ -0,0 +1,704 @@ +// file : xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace non_validating + { + // any_type_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_type_sskel:: + any_type_sskel () + : any_type_impl_ (0) + { + } + + inline any_type_sskel:: + any_type_sskel (any_type_sskel* impl, void*) + : complex_content (impl, 0), any_type_impl_ (impl) + { + } +#endif + + // any_simple_type_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_simple_type_sskel:: + any_simple_type_sskel () + : any_simple_type_impl_ (0) + { + } + + inline any_simple_type_sskel:: + any_simple_type_sskel (any_simple_type_sskel* impl, void*) + : simple_content (impl, 0), any_simple_type_impl_ (impl) + { + } +#endif + + // boolean_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline boolean_sskel:: + boolean_sskel () + : boolean_impl_ (0) + { + } + + inline boolean_sskel:: + boolean_sskel (boolean_sskel* impl, void*) + : simple_content (impl, 0), boolean_impl_ (impl) + { + } +#endif + + // byte_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline byte_sskel:: + byte_sskel () + : byte_impl_ (0) + { + } + + inline byte_sskel:: + byte_sskel (byte_sskel* impl, void*) + : simple_content (impl, 0), byte_impl_ (impl) + { + } +#endif + + // unsigned_byte_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_byte_sskel:: + unsigned_byte_sskel () + : unsigned_byte_impl_ (0) + { + } + + inline unsigned_byte_sskel:: + unsigned_byte_sskel (unsigned_byte_sskel* impl, void*) + : simple_content (impl, 0), unsigned_byte_impl_ (impl) + { + } +#endif + + // short_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline short_sskel:: + short_sskel () + : short_impl_ (0) + { + } + + inline short_sskel:: + short_sskel (short_sskel* impl, void*) + : simple_content (impl, 0), short_impl_ (impl) + { + } +#endif + + // unsigned_short_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_short_sskel:: + unsigned_short_sskel () + : unsigned_short_impl_ (0) + { + } + + inline unsigned_short_sskel:: + unsigned_short_sskel (unsigned_short_sskel* impl, void*) + : simple_content (impl, 0), unsigned_short_impl_ (impl) + { + } +#endif + + // int_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline int_sskel:: + int_sskel () + : int_impl_ (0) + { + } + + inline int_sskel:: + int_sskel (int_sskel* impl, void*) + : simple_content (impl, 0), int_impl_ (impl) + { + } +#endif + + // unsigned_int_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_int_sskel:: + unsigned_int_sskel () + : unsigned_int_impl_ (0) + { + } + + inline unsigned_int_sskel:: + unsigned_int_sskel (unsigned_int_sskel* impl, void*) + : simple_content (impl, 0), unsigned_int_impl_ (impl) + { + } +#endif + + // long_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline long_sskel:: + long_sskel () + : long_impl_ (0) + { + } + + inline long_sskel:: + long_sskel (long_sskel* impl, void*) + : simple_content (impl, 0), long_impl_ (impl) + { + } +#endif + + // unsigned_long_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_long_sskel:: + unsigned_long_sskel () + : unsigned_long_impl_ (0) + { + } + + inline unsigned_long_sskel:: + unsigned_long_sskel (unsigned_long_sskel* impl, void*) + : simple_content (impl, 0), unsigned_long_impl_ (impl) + { + } +#endif + + // integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline integer_sskel:: + integer_sskel () + : integer_impl_ (0) + { + } + + inline integer_sskel:: + integer_sskel (integer_sskel* impl, void*) + : simple_content (impl, 0), integer_impl_ (impl) + { + } +#endif + + // negative_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline negative_integer_sskel:: + negative_integer_sskel () + : negative_integer_impl_ (0) + { + } + + inline negative_integer_sskel:: + negative_integer_sskel (negative_integer_sskel* impl, void*) + : simple_content (impl, 0), negative_integer_impl_ (impl) + { + } +#endif + + // non_positive_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_positive_integer_sskel:: + non_positive_integer_sskel () + : non_positive_integer_impl_ (0) + { + } + + inline non_positive_integer_sskel:: + non_positive_integer_sskel (non_positive_integer_sskel* impl, void*) + : simple_content (impl, 0), non_positive_integer_impl_ (impl) + { + } +#endif + + // positive_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline positive_integer_sskel:: + positive_integer_sskel () + : positive_integer_impl_ (0) + { + } + + inline positive_integer_sskel:: + positive_integer_sskel (positive_integer_sskel* impl, void*) + : simple_content (impl, 0), positive_integer_impl_ (impl) + { + } +#endif + + // non_negative_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_negative_integer_sskel:: + non_negative_integer_sskel () + : non_negative_integer_impl_ (0) + { + } + + inline non_negative_integer_sskel:: + non_negative_integer_sskel (non_negative_integer_sskel* impl, void*) + : simple_content (impl, 0), non_negative_integer_impl_ (impl) + { + } +#endif + + // float_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline float_sskel:: + float_sskel () + : float_impl_ (0) + { + } + + inline float_sskel:: + float_sskel (float_sskel* impl, void*) + : simple_content (impl, 0), float_impl_ (impl) + { + } +#endif + + // double_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline double_sskel:: + double_sskel () + : double_impl_ (0) + { + } + + inline double_sskel:: + double_sskel (double_sskel* impl, void*) + : simple_content (impl, 0), double_impl_ (impl) + { + } +#endif + + // decimal_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline decimal_sskel:: + decimal_sskel () + : decimal_impl_ (0) + { + } + + inline decimal_sskel:: + decimal_sskel (decimal_sskel* impl, void*) + : simple_content (impl, 0), decimal_impl_ (impl) + { + } +#endif + + // string_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline string_sskel:: + string_sskel () + : string_impl_ (0) + { + } + + inline string_sskel:: + string_sskel (string_sskel* impl, void*) + : simple_content (impl, 0), string_impl_ (impl) + { + } +#endif + + // normalized_string_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline normalized_string_sskel:: + normalized_string_sskel () + : normalized_string_impl_ (0) + { + } + + inline normalized_string_sskel:: + normalized_string_sskel (normalized_string_sskel* impl, void*) + : string_sskel (impl, 0), normalized_string_impl_ (impl) + { + } +#endif + + // token_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline token_sskel:: + token_sskel () + : token_impl_ (0) + { + } + + inline token_sskel:: + token_sskel (token_sskel* impl, void*) + : normalized_string_sskel (impl, 0), token_impl_ (impl) + { + } +#endif + + // name_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline name_sskel:: + name_sskel () + : name_impl_ (0) + { + } + + inline name_sskel:: + name_sskel (name_sskel* impl, void*) + : token_sskel (impl, 0), name_impl_ (impl) + { + } +#endif + + // nmtoken_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtoken_sskel:: + nmtoken_sskel () + : nmtoken_impl_ (0) + { + } + + inline nmtoken_sskel:: + nmtoken_sskel (nmtoken_sskel* impl, void*) + : token_sskel (impl, 0), nmtoken_impl_ (impl) + { + } +#endif + + // nmtokens_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtokens_sskel:: + nmtokens_sskel () + : nmtokens_impl_ (0) + { + } + + inline nmtokens_sskel:: + nmtokens_sskel (nmtokens_sskel* impl, void*) + : simple_content (impl, 0), nmtokens_impl_ (impl) + { + } +#endif + + // ncname_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline ncname_sskel:: + ncname_sskel () + : ncname_impl_ (0) + { + } + + inline ncname_sskel:: + ncname_sskel (ncname_sskel* impl, void*) + : name_sskel (impl, 0), ncname_impl_ (impl) + { + } +#endif + + // id_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline id_sskel:: + id_sskel () + : id_impl_ (0) + { + } + + inline id_sskel:: + id_sskel (id_sskel* impl, void*) + : ncname_sskel (impl, 0), id_impl_ (impl) + { + } +#endif + + // idref_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idref_sskel:: + idref_sskel () + : idref_impl_ (0) + { + } + + inline idref_sskel:: + idref_sskel (idref_sskel* impl, void*) + : ncname_sskel (impl, 0), idref_impl_ (impl) + { + } +#endif + + // idrefs_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idrefs_sskel:: + idrefs_sskel () + : idrefs_impl_ (0) + { + } + + inline idrefs_sskel:: + idrefs_sskel (idrefs_sskel* impl, void*) + : simple_content (impl, 0), idrefs_impl_ (impl) + { + } +#endif + + // language_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline language_sskel:: + language_sskel () + : language_impl_ (0) + { + } + + inline language_sskel:: + language_sskel (language_sskel* impl, void*) + : token_sskel (impl, 0), language_impl_ (impl) + { + } +#endif + + // uri_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline uri_sskel:: + uri_sskel () + : uri_impl_ (0) + { + } + + inline uri_sskel:: + uri_sskel (uri_sskel* impl, void*) + : simple_content (impl, 0), uri_impl_ (impl) + { + } +#endif + + // qname_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline qname_sskel:: + qname_sskel () + : qname_impl_ (0) + { + } + + inline qname_sskel:: + qname_sskel (qname_sskel* impl, void*) + : simple_content (impl, 0), qname_impl_ (impl) + { + } +#endif + + // base64_binary_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline base64_binary_sskel:: + base64_binary_sskel () + : base64_binary_impl_ (0) + { + } + + inline base64_binary_sskel:: + base64_binary_sskel (base64_binary_sskel* impl, void*) + : simple_content (impl, 0), base64_binary_impl_ (impl) + { + } +#endif + + // hex_binary_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline hex_binary_sskel:: + hex_binary_sskel () + : hex_binary_impl_ (0) + { + } + + inline hex_binary_sskel:: + hex_binary_sskel (hex_binary_sskel* impl, void*) + : simple_content (impl, 0), hex_binary_impl_ (impl) + { + } +#endif + + // gday_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gday_sskel:: + gday_sskel () + : gday_impl_ (0) + { + } + + inline gday_sskel:: + gday_sskel (gday_sskel* impl, void*) + : simple_content (impl, 0), gday_impl_ (impl) + { + } +#endif + + // gmonth_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_sskel:: + gmonth_sskel () + : gmonth_impl_ (0) + { + } + + inline gmonth_sskel:: + gmonth_sskel (gmonth_sskel* impl, void*) + : simple_content (impl, 0), gmonth_impl_ (impl) + { + } +#endif + + // gyear_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_sskel:: + gyear_sskel () + : gyear_impl_ (0) + { + } + + inline gyear_sskel:: + gyear_sskel (gyear_sskel* impl, void*) + : simple_content (impl, 0), gyear_impl_ (impl) + { + } +#endif + + // gmonth_day_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_day_sskel:: + gmonth_day_sskel () + : gmonth_day_impl_ (0) + { + } + + inline gmonth_day_sskel:: + gmonth_day_sskel (gmonth_day_sskel* impl, void*) + : simple_content (impl, 0), gmonth_day_impl_ (impl) + { + } +#endif + + // gyear_month_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_month_sskel:: + gyear_month_sskel () + : gyear_month_impl_ (0) + { + } + + inline gyear_month_sskel:: + gyear_month_sskel (gyear_month_sskel* impl, void*) + : simple_content (impl, 0), gyear_month_impl_ (impl) + { + } +#endif + + // date_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_sskel:: + date_sskel () + : date_impl_ (0) + { + } + + inline date_sskel:: + date_sskel (date_sskel* impl, void*) + : simple_content (impl, 0), date_impl_ (impl) + { + } +#endif + + // time_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline time_sskel:: + time_sskel () + : time_impl_ (0) + { + } + + inline time_sskel:: + time_sskel (time_sskel* impl, void*) + : simple_content (impl, 0), time_impl_ (impl) + { + } +#endif + + // date_time_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_time_sskel:: + date_time_sskel () + : date_time_impl_ (0) + { + } + + inline date_time_sskel:: + date_time_sskel (date_time_sskel* impl, void*) + : simple_content (impl, 0), date_time_impl_ (impl) + { + } +#endif + + // duration_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline duration_sskel:: + duration_sskel () + : duration_impl_ (0) + { + } + + inline duration_sskel:: + duration_sskel (duration_sskel* impl, void*) + : simple_content (impl, 0), duration_impl_ (impl) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/substitution-map-load.hxx b/libxsde/xsde/cxx/serializer/substitution-map-load.hxx new file mode 100644 index 0000000..95083e2 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/substitution-map-load.hxx @@ -0,0 +1,40 @@ +// file : xsde/cxx/serializer/substitution-map-load.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_LOAD_HXX +#define XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_LOAD_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + size_t + serializer_smap_elements (); + + inline size_t + serializer_smap_buckets () + { + return XSDE_SERIALIZER_SMAP_BUCKETS; + } + + size_t + serializer_smap_bucket_elements (); + + inline size_t + serializer_smap_bucket_buckets () + { + return XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_LOAD_HXX diff --git a/libxsde/xsde/cxx/serializer/substitution-map.cxx b/libxsde/xsde/cxx/serializer/substitution-map.cxx new file mode 100644 index 0000000..e155882 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/substitution-map.cxx @@ -0,0 +1,248 @@ +// file : xsde/cxx/serializer/substitution-map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // strlen, strcmp, strncmp + +#ifndef XSDE_EXCEPTIONS +# include // assert +# include // exit +#endif + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + substitution_map* substitution_map_init::map = 0; + size_t substitution_map_init::count = 0; + + substitution_map:: + ~substitution_map () + { + for (const_iterator i (begin ()), e (end ()); i != e; ++i) + { + delete *static_cast (const_cast (*i)); + } + } + + void substitution_map:: + insert (const char* root, + const char* member_ns, + const char* member_name, + const char* member_type) + { + hashmap* m; + + if (const void* p = find (root)) + m = *static_cast (const_cast (p)); + else + { + m = new hashmap (XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS, + sizeof (value)); + +#ifndef XSDE_EXCEPTIONS + if (m == 0 || m->_error () != hashmap::error_none) + { + error_ = error_no_memory; + return; + } +#endif + hashmap::insert (root, &m); + +#ifndef XSDE_EXCEPTIONS + if (_error () != error_none) + return; +#endif + } + + value v; + v.ns_ = member_ns; + v.name_ = member_name; + m->insert (member_type, &v); + +#ifndef XSDE_EXCEPTIONS + if (m->_error () != hashmap::error_none) + error_ = error_no_memory; +#endif + } + + bool substitution_map:: + check_ (const char*& ns, + const char*& name, + const char* type) const + { + size_t h = hash (name); + + if (ns) + { + h = hash (h, " ", 1); + h = hash (h, ns); + } + + const bucket* p = find (h); + + if (p == 0) + return false; + + // Search for the entry in the bucket. + // + const size_t el_size = sizeof (element) + sizeof (hashmap*); + const char* b = reinterpret_cast (p) + sizeof (bucket); + const char* e = b + p->size_ * el_size; + + size_t nl = ns ? strlen (name) : 0; + + for (; b < e; b += el_size) + { + const element* e = reinterpret_cast (b); + + if (e->hash_ == h) + { + if (ns == 0) + { + if (strcmp (e->key_, name) == 0) + break; + } + else + { + if (strncmp (e->key_, name, nl) == 0 && + e->key_[nl] == ' ' && + strcmp (e->key_ + nl + 1, ns) == 0) + break; + } + } + } + + if (b == e) + return false; + + const hashmap* map = *reinterpret_cast ( + b + sizeof (element)); + + // See if we have a direct substitution. + // + if (const value* v = static_cast (map->find (type))) + { + ns = v->ns_; + name = v->name_; + return true; + } + + // Otherwise we have to iterate over possible substitutions and + // see if any of them can in turn be substituted with something + // that we can use. + // + for (const_iterator i (map->begin ()), end (map->end ()); + i != end; ++i) + { + const value* v = static_cast (*i); + + const char* tns = v->ns_; + const char* tn = v->name_; + + if (check_ (tns, tn, type)) + { + ns = tns; + name = tn; + return true; + } + } + + return false; + } + + // substitution_map_init + // + substitution_map_init:: + substitution_map_init () + { + if (count == 0) + { + map = new substitution_map (XSDE_SERIALIZER_SMAP_BUCKETS); + +#ifndef XSDE_EXCEPTIONS + if (map == 0 || map->_error () != substitution_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + ++count; + } + + substitution_map_init:: + ~substitution_map_init () + { + if (--count == 0) + delete map; + } + + // substitution_map_entry + // + substitution_map_entry:: + substitution_map_entry (const char* root, + const char* member_ns, + const char* member_name, + const char* member_type) + { + substitution_map& m = substitution_map_instance (); + m.insert (root, member_ns, member_name, member_type); + +#ifndef XSDE_EXCEPTIONS + if (m._error () != substitution_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + // + // + size_t + serializer_smap_elements () + { + return substitution_map_instance ().size (); + } + + size_t + serializer_smap_bucket_elements () + { + size_t r = 0; + + substitution_map& m = substitution_map_instance (); + + for (substitution_map::const_iterator i (m.begin ()), e (m.end ()); + i != e; ++i) + { + const hashmap* h = *static_cast (*i); + + if (h->size () > r) + r = h->size (); + } + + return r; + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/substitution-map.hxx b/libxsde/xsde/cxx/serializer/substitution-map.hxx new file mode 100644 index 0000000..601f255 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/substitution-map.hxx @@ -0,0 +1,88 @@ +// file : xsde/cxx/serializer/substitution-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_HXX +#define XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_HXX + +#include // size_t + +#include +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + struct substitution_map: hashmap + { + ~substitution_map (); + + substitution_map (size_t buckets); + + void + insert (const char* root, + const char* member_ns, + const char* member_name, + const char* member_type); + + // Check whether there is a substitution available for this + // root element with the specified type. If so, return true + // and override namespace and name (ns is 0 if there is no + // namespace). + // + bool + check (const char*& ns, + const char*& name, + const char* type) const; + + private: + bool + check_ (const char*& ns, + const char*& name, + const char* type) const; + + private: + struct value + { + const char* ns_; + const char* name_; + }; + }; + + + // Translation unit initializer. + // + struct substitution_map_init + { + static substitution_map* map; + static size_t count; + + substitution_map_init (); + ~substitution_map_init (); + }; + + substitution_map& + substitution_map_instance (); + + // Map entry initializer. + // + struct substitution_map_entry + { + substitution_map_entry (const char* root, + const char* member_ns, + const char* member_name, + const char* member_type); + }; + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_SUBSTITUTION_MAP_HXX + diff --git a/libxsde/xsde/cxx/serializer/substitution-map.ixx b/libxsde/xsde/cxx/serializer/substitution-map.ixx new file mode 100644 index 0000000..63a848a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/substitution-map.ixx @@ -0,0 +1,33 @@ +// file : xsde/cxx/serializer/substitution-map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + inline substitution_map:: + substitution_map (size_t buckets) + : hashmap (buckets, sizeof (hashmap*)) + { + } + + inline bool substitution_map:: + check (const char*& ns, + const char*& name, + const char* type) const + { + return empty () ? false : check_ (ns, name, type); + } + + inline substitution_map& + substitution_map_instance () + { + return *substitution_map_init::map; + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/any-type.hxx b/libxsde/xsde/cxx/serializer/validating/any-type.hxx new file mode 100644 index 0000000..ca80572 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/any-type.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/any-type.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_ANY_TYPE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_ANY_TYPE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // any_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_type_simpl: virtual any_type_sskel +#else + struct any_type_simpl: any_type_sskel +#endif + { + }; + + // any_simple_type + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct any_simple_type_simpl: virtual any_simple_type_sskel +#else + struct any_simple_type_simpl: any_simple_type_sskel +#endif + { + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_ANY_TYPE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/base64-binary.cxx b/libxsde/xsde/cxx/serializer/validating/base64-binary.cxx new file mode 100644 index 0000000..a649433 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/base64-binary.cxx @@ -0,0 +1,166 @@ +// file : xsde/cxx/serializer/validating/base64-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + base64_binary_simpl:: + ~base64_binary_simpl () + { + if (free_) + delete const_cast (value_); + } + + void base64_binary_simpl:: + pre (const buffer* value) + { + value_ = value; + } + + static const char base64_tab[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/', '\0' + }; + + inline void + split_1 (char b, unsigned char& b1, unsigned char& b2) + { + unsigned char ub = static_cast (b); + b1 = ub >> 2; + b2 = (ub & 0x3) << 4; + } + + inline void + split_2 (char b, unsigned char& b2, unsigned char& b3) + { + unsigned char ub = static_cast (b); + b2 |= ub >> 4; + b3 = (ub & 0x0F) << 2; + } + + inline void + split_3 (char b, unsigned char& b3, unsigned char& b4) + { + unsigned char ub = static_cast (b); + b3 |= ub >> 6; + b4 = ( ub & 0x3F ); + } + + void base64_binary_simpl:: + _serialize_content () + { + // Maximum 76 characters per line, 76/4 = 19 + // + const size_t quads_per_line = 19; + char buf[quads_per_line * 4 + 1]; + + if (size_t size = value_->size ()) + { + const char* data = value_->data (); + size_t quads = (size + 2) / 3; + + // Process all quadruplets except the last, one line at a time. + // + size_t i = 0; + size_t j = 0; + unsigned char b1, b2, b3, b4; + + for (; j < (quads - 1);) + { + for (; i < quads_per_line && j < (quads - 1); ++i, ++j) + { + split_1 (*data++, b1, b2); + split_2 (*data++, b2, b3); + split_3 (*data++, b3, b4); + + buf[i * 4] = base64_tab[b1]; + buf[i * 4 + 1] = base64_tab[b2]; + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = base64_tab[b4]; + } + + if (i == quads_per_line) + { + buf[i * 4] = '\n'; + +#ifdef XSDE_EXCEPTIONS + _characters (buf, i * 4 + 1); +#else + if (!_characters (buf, i * 4 + 1)) + break; +#endif + i = 0; + } + } + +#ifndef XSDE_EXCEPTIONS + if (j == (quads - 1)) + { +#endif + // Process last quadruplet. The first byte is always present. + // + split_1 (*data++, b1, b2); + buf[i * 4] = base64_tab[b1]; + + if (data != value_->end ()) + { + // Second byte is present. + // + split_2 (*data++, b2, b3); + buf[i * 4 + 1] = base64_tab[b2]; + + if(data != value_->end ()) + { + // Third byte is present. + // + split_3 (*data++, b3, b4); + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = base64_tab[b4]; + } + else + { + buf[i * 4 + 2] = base64_tab[b3]; + buf[i * 4 + 3] = '='; + } + } + else + { + buf[i * 4 + 1] = base64_tab[b2]; + buf[i * 4 + 2] = '='; + buf[i * 4 + 3] = '='; + } + + i++; + + buf[i * 4] = '\n'; + _characters (buf, i * 4 + 1); + +#ifndef XSDE_EXCEPTIONS + } +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/base64-binary.hxx b/libxsde/xsde/cxx/serializer/validating/base64-binary.hxx new file mode 100644 index 0000000..9b8b050 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/base64-binary.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/base64-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_BASE64_BINARY_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_BASE64_BINARY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct base64_binary_simpl: virtual base64_binary_sskel +#else + struct base64_binary_simpl: base64_binary_sskel +#endif + { + virtual + ~base64_binary_simpl (); + + base64_binary_simpl (bool free = false); + + virtual void + pre (const buffer*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const buffer* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_BASE64_BINARY_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/base64-binary.ixx b/libxsde/xsde/cxx/serializer/validating/base64-binary.ixx new file mode 100644 index 0000000..5da3828 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/base64-binary.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/base64-binary.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline base64_binary_simpl:: + base64_binary_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/boolean.cxx b/libxsde/xsde/cxx/serializer/validating/boolean.cxx new file mode 100644 index 0000000..82e8ed5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/boolean.cxx @@ -0,0 +1,30 @@ +// file : xsde/cxx/serializer/validating/boolean.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void boolean_simpl:: + pre (bool value) + { + value_ = value; + } + + void boolean_simpl:: + _serialize_content () + { + _characters ((value_ ? "true" : "false"), (value_ ? 4 : 5)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/boolean.hxx b/libxsde/xsde/cxx/serializer/validating/boolean.hxx new file mode 100644 index 0000000..d6b698a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/boolean.hxx @@ -0,0 +1,39 @@ +// file : xsde/cxx/serializer/validating/boolean.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_BOOLEAN_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_BOOLEAN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct boolean_simpl: virtual boolean_sskel +#else + struct boolean_simpl: boolean_sskel +#endif + { + virtual void + pre (bool); + + virtual void + _serialize_content (); + + protected: + bool value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_BOOLEAN_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/byte.cxx b/libxsde/xsde/cxx/serializer/validating/byte.cxx new file mode 100644 index 0000000..c5e5726 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/byte.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void byte_simpl:: + pre (signed char value) + { + value_ = value; + } + + void byte_simpl:: + _serialize_content () + { + // We only need strlen("-128") + 1 characters to hold all + // representations of signed byte. + // + char str[5]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 5, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 5) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_byte_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/byte.hxx b/libxsde/xsde/cxx/serializer/validating/byte.hxx new file mode 100644 index 0000000..be7e683 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/byte.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_BYTE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_BYTE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 8-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct byte_simpl: virtual byte_sskel +#else + struct byte_simpl: byte_sskel +#endif + { + virtual void + pre (signed char); + + virtual void + _serialize_content (); + + protected: + signed char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_BYTE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/date-time.cxx b/libxsde/xsde/cxx/serializer/validating/date-time.cxx new file mode 100644 index 0000000..cacc6ea --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date-time.cxx @@ -0,0 +1,87 @@ +// file : xsde/cxx/serializer/validating/date-time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void date_time_simpl:: + pre (const date_time& value) + { + value_ = value; + } + + void date_time_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM-DDThh:mm:ss.ssssss-hh:mm") + // + 1 characters to hold all representations of date_time. We + // know that the seconds part (represented as double) has + // default precision of 6. + // + char str[40]; + + int y = value_.year (); + unsigned short m = value_.month (); + unsigned short d = value_.day (); + + unsigned short h = value_.hours (); + unsigned short tm = value_.minutes (); + double s = value_.seconds (); + + if (y != 0 && m > 0 && m < 13 && d > 0 && d < 32 && + ((h < 24 && tm < 60 && s >= 0.0 && s < 60.0) || + (h == 24 && tm == 0 && s == 0.0)) && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 34, "%.4d-%.2u-%.2uT%.2u:%.2u:%09f", + y, m, d, h, tm, s); +#else + int n = sprintf (str, "%.4d-%.2u-%.2uT%.2u:%.2u:%09f", + y, m, d, h, tm, s); +#endif + if (n > 0 && n < 34) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_date_time_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_date_time_value); + } + else + _schema_error (schema_error::invalid_date_time_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/date-time.hxx b/libxsde/xsde/cxx/serializer/validating/date-time.hxx new file mode 100644 index 0000000..0cfcab1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date-time.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/date-time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_DATE_TIME_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_DATE_TIME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_time_simpl: virtual date_time_sskel +#else + struct date_time_simpl: date_time_sskel +#endif + { + date_time_simpl (); + + virtual void + pre (const date_time&); + + virtual void + _serialize_content (); + + protected: + date_time value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_DATE_TIME_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/date-time.ixx b/libxsde/xsde/cxx/serializer/validating/date-time.ixx new file mode 100644 index 0000000..e5e5813 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date-time.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/date-time.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline date_time_simpl:: + date_time_simpl () + : value_ (1, 0, 0, 0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/date.cxx b/libxsde/xsde/cxx/serializer/validating/date.cxx new file mode 100644 index 0000000..b374c1c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date.cxx @@ -0,0 +1,71 @@ +// file : xsde/cxx/serializer/validating/date.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void date_simpl:: + pre (const date& value) + { + value_ = value; + } + + void date_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM-DD+hh:mm") + 1 characters to + // hold all representations of date. + // + char str[24]; + + int y = value_.year (); + unsigned short m = value_.month (); + unsigned short d = value_.day (); + + if (y != 0 && m > 0 && m < 13 && d > 0 && d < 32 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 18, "%.4d-%.2u-%.2u", + value_.year (), value_.month (), value_.day ()); +#else + int n = sprintf (str, "%.4d-%.2u-%.2u", + value_.year (), value_.month (), value_.day ()); +#endif + if (n > 0 && n < 18) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_date_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_date_value); + } + else + _schema_error (schema_error::invalid_date_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/date.hxx b/libxsde/xsde/cxx/serializer/validating/date.hxx new file mode 100644 index 0000000..caaf4a5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/date.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_DATE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_DATE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct date_simpl: virtual date_sskel +#else + struct date_simpl: date_sskel +#endif + { + date_simpl (); + + virtual void + pre (const date&); + + virtual void + _serialize_content (); + + protected: + date value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_DATE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/date.ixx b/libxsde/xsde/cxx/serializer/validating/date.ixx new file mode 100644 index 0000000..f5c3706 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/date.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/date.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline date_simpl:: + date_simpl () + : value_ (1, 1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/decimal.cxx b/libxsde/xsde/cxx/serializer/validating/decimal.cxx new file mode 100644 index 0000000..7383025 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/decimal.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/serializer/validating/decimal.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void decimal_simpl:: + pre (double value) + { + value_ = value; + } + + void decimal_simpl:: + _serialize_content () + { + // Assume double values cannot be longer than 127 characters. + // + char str[128]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, "%.*f", + static_cast (precision_), value_); +#else + int n = sprintf (str, "%.*f", + static_cast (precision_), value_); +#endif + if (n > 0 && n < 128) + { + // For decimal, NaN and INF are not allowed. + // + int i = (str[0] == '-' ? 1 : 0); + if ((str[i] == 'i' && str[i + 1] == 'n' && str[i + 2] == 'f') || + (str[i] == 'n' && str[i + 1] == 'a' && str[i + 2] == 'n')) + { + _schema_error (schema_error::invalid_decimal_value); + return; + } + + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_decimal_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/decimal.hxx b/libxsde/xsde/cxx/serializer/validating/decimal.hxx new file mode 100644 index 0000000..af2c0f1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/decimal.hxx @@ -0,0 +1,50 @@ +// file : xsde/cxx/serializer/validating/decimal.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_DECIMAL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_DECIMAL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct decimal_simpl: virtual decimal_sskel +#else + struct decimal_simpl: decimal_sskel +#endif + { +#ifdef DBL_DIG + decimal_simpl (unsigned int precision = DBL_DIG); +#else + decimal_simpl (unsigned int precision = 15) +#endif + + virtual void + pre (double); + + virtual void + _serialize_content (); + + protected: + unsigned int precision_; + double value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_DECIMAL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/decimal.ixx b/libxsde/xsde/cxx/serializer/validating/decimal.ixx new file mode 100644 index 0000000..803253d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/decimal.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/decimal.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline decimal_simpl:: + decimal_simpl (unsigned int p) + : precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/double.cxx b/libxsde/xsde/cxx/serializer/validating/double.cxx new file mode 100644 index 0000000..526eba0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/double.cxx @@ -0,0 +1,105 @@ +// file : xsde/cxx/serializer/validating/double.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void double_simpl:: + pre (double value) + { + value_ = value; + } + + void double_simpl:: + _serialize_content () + { + // Assume double values cannot be longer than 127 characters. + // + char str[128]; + + const char* fmt = 0; + + switch (notation_) + { + case notation_auto: + { + fmt = "%.*g"; + break; + } + case notation_fixed: + { + fmt = "%.*f"; + break; + } + case notation_scientific: + { + fmt = "%.*e"; + break; + } + } + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, fmt, precision_, value_); +#else + int n = sprintf (str, fmt, precision_, value_); +#endif + if (n > 0 && n < 128) + { + if (str[0] == '-') + { + if (str[1] == 'n' && str[2] == 'a' && str[3] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[1] == 'i' && str[2] == 'n' && str[3] == 'f') + { + _characters ("-INF", 4); + return; + } + } + else + { + if (str[0] == 'n' && str[1] == 'a' && str[2] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[0] == 'i' && str[1] == 'n' && str[2] == 'f') + { + _characters ("INF", 3); + return; + } + } + + if (notation_ == notation_fixed) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_double_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/double.hxx b/libxsde/xsde/cxx/serializer/validating/double.hxx new file mode 100644 index 0000000..e7d1324 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/double.hxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/serializer/validating/double.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_DOUBLE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_DOUBLE_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct double_simpl: virtual double_sskel +#else + struct double_simpl: double_sskel +#endif + { + enum notation + { + notation_auto, + notation_fixed, + notation_scientific + }; + +#ifdef DBL_DIG + double_simpl (notation = notation_auto, + unsigned int precision = DBL_DIG); +#else + double_simpl (notation = notation_auto, + unsigned int precision = 15) +#endif + + virtual void + pre (double); + + virtual void + _serialize_content (); + + protected: + notation notation_; + unsigned int precision_; + double value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_DOUBLE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/double.ixx b/libxsde/xsde/cxx/serializer/validating/double.ixx new file mode 100644 index 0000000..8ae69e6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/double.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/double.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline double_simpl:: + double_simpl (notation n, unsigned int p) + : notation_ (n), precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/duration.cxx b/libxsde/xsde/cxx/serializer/validating/duration.cxx new file mode 100644 index 0000000..7187da5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/duration.cxx @@ -0,0 +1,195 @@ +// file : xsde/cxx/serializer/validating/duration.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void duration_simpl:: + pre (const duration& value) + { + value_ = value; + } + + void duration_simpl:: + _serialize_content () + { + if (value_.seconds () < 0.0) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + // duration := -PnYnMnDTnHnMnS + // + // The years, months, days, hours, and minutes components are + // represented as 32 unsigned integers with maximum string + // representation being strlen ("4294967295") = 10. + // + // We assume that the seconds part (double) cannot be longer + // than 128 chars. + // + // The total representation thus cannot exceed 10*5 + 128 + + // 9 + 1 = 188 characters. + // + char str[188]; + char* p = str; + + if (value_.negative ()) + *p++ = '-'; + + *p++ = 'P'; + + // years + // + // In case it is 0-duration, use the years field to handle + // this case. + // + if (value_.years () != 0 || + (value_.months () == 0 && + value_.days () == 0 && + value_.hours () == 0 && + value_.minutes () == 0 && + value_.seconds () == 0.0)) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.years ()); +#else + int n = sprintf (p, "%u", value_.years ()); +#endif + if (n < 0 || n >= 11) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + p += n; + *p++ = 'Y'; + } + + // months + // + if (value_.months () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.months ()); +#else + int n = sprintf (p, "%u", value_.months ()); +#endif + if (n < 0 || n >= 11) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + p += n; + *p++ = 'M'; + } + + // days + // + if (value_.days () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.days ()); +#else + int n = sprintf (p, "%u", value_.days ()); +#endif + if (n < 0 || n >= 11) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + p += n; + *p++ = 'D'; + } + + // Figure out if we need the 'T' delimiter. + // + if (value_.hours () != 0 || + value_.minutes () != 0 || + value_.seconds () != 0.0) + *p++ = 'T'; + + // hours + // + if (value_.hours () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.hours ()); +#else + int n = sprintf (p, "%u", value_.hours ()); +#endif + if (n < 0 || n >= 11) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + p += n; + *p++ = 'H'; + } + + // minutes + // + if (value_.minutes () != 0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 11, "%u", value_.minutes ()); +#else + int n = sprintf (p, "%u", value_.minutes ()); +#endif + if (n < 0 || n >= 11) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + p += n; + *p++ = 'M'; + } + + // seconds + // + if (value_.seconds () > 0.0) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (p, 128, "%f", value_.seconds ()); +#else + int n = sprintf (p, "%f", value_.seconds ()); +#endif + if (n < 0 || n >= 128) + { + _schema_error (schema_error::invalid_duration_value); + return; + } + + // Remove trailing '0' and '.' if necessary. + // + while (p[n - 1] == '0') + n--; + + if (p[n - 1] == '.') + n--; + + p += n; + *p++ = 'S'; + } + + _characters (str, static_cast (p - str)); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/duration.hxx b/libxsde/xsde/cxx/serializer/validating/duration.hxx new file mode 100644 index 0000000..edc5473 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/duration.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/duration.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_DURATION_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_DURATION_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct duration_simpl: virtual duration_sskel +#else + struct duration_simpl: duration_sskel +#endif + { + duration_simpl (); + + virtual void + pre (const duration&); + + virtual void + _serialize_content (); + + protected: + duration value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_DURATION_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/duration.ixx b/libxsde/xsde/cxx/serializer/validating/duration.ixx new file mode 100644 index 0000000..334a288 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/duration.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/duration.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline duration_simpl:: + duration_simpl () + : value_ (false, 1, 0, 0, 0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/float.cxx b/libxsde/xsde/cxx/serializer/validating/float.cxx new file mode 100644 index 0000000..d9ee49c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/float.cxx @@ -0,0 +1,105 @@ +// file : xsde/cxx/serializer/validating/float.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void float_simpl:: + pre (float value) + { + value_ = value; + } + + void float_simpl:: + _serialize_content () + { + // Assume float values cannot be longer than 127 characters. + // + char str[128]; + + const char* fmt = 0; + + switch (notation_) + { + case notation_auto: + { + fmt = "%.*g"; + break; + } + case notation_fixed: + { + fmt = "%.*f"; + break; + } + case notation_scientific: + { + fmt = "%.*e"; + break; + } + } + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 128, fmt, precision_, value_); +#else + int n = sprintf (str, fmt, precision_, value_); +#endif + if (n > 0 && n < 128) + { + if (str[0] == '-') + { + if (str[1] == 'n' && str[2] == 'a' && str[3] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[1] == 'i' && str[2] == 'n' && str[3] == 'f') + { + _characters ("-INF", 4); + return; + } + } + else + { + if (str[0] == 'n' && str[1] == 'a' && str[2] == 'n') + { + _characters ("NaN", 3); + return; + } + else if (str[0] == 'i' && str[1] == 'n' && str[2] == 'f') + { + _characters ("INF", 3); + return; + } + } + + if (notation_ == notation_fixed) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_float_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/float.hxx b/libxsde/xsde/cxx/serializer/validating/float.hxx new file mode 100644 index 0000000..6a9b9df --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/float.hxx @@ -0,0 +1,60 @@ +// file : xsde/cxx/serializer/validating/float.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_FLOAT_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_FLOAT_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct float_simpl: virtual float_sskel +#else + struct float_simpl: float_sskel +#endif + { + enum notation + { + notation_auto, + notation_fixed, + notation_scientific + }; + +#ifdef FLT_DIG + float_simpl (notation = notation_auto, + unsigned int precision = FLT_DIG); +#else + float_simpl (notation = notation_auto, + unsigned int precision = 6) +#endif + + virtual void + pre (float); + + virtual void + _serialize_content (); + + protected: + notation notation_; + unsigned int precision_; + float value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_FLOAT_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/float.ixx b/libxsde/xsde/cxx/serializer/validating/float.ixx new file mode 100644 index 0000000..b240b6e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/float.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/float.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline float_simpl:: + float_simpl (notation n, unsigned int p) + : notation_ (n), precision_ (p) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gday.cxx b/libxsde/xsde/cxx/serializer/validating/gday.cxx new file mode 100644 index 0000000..363757b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gday.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/serializer/validating/gday.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void gday_simpl:: + pre (const gday& value) + { + value_ = value; + } + + void gday_simpl:: + _serialize_content () + { + // We only need strlen("---DD+hh:mm") + 1 characters to hold all + // representations of gDay. + // + char str[12]; + + unsigned short d = value_.day (); + + if (d > 0 && d < 32 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 6, "---%.2u", d); +#else + int n = sprintf (str, "---%.2u", d); +#endif + if (n > 0 && n < 6) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_gday_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_gday_value); + } + else + _schema_error (schema_error::invalid_gday_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gday.hxx b/libxsde/xsde/cxx/serializer/validating/gday.hxx new file mode 100644 index 0000000..856229b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gday.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/gday.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_GDAY_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_GDAY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gday_simpl: virtual gday_sskel +#else + struct gday_simpl: gday_sskel +#endif + { + gday_simpl (); + + virtual void + pre (const gday&); + + virtual void + _serialize_content (); + + protected: + gday value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_GDAY_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/gday.ixx b/libxsde/xsde/cxx/serializer/validating/gday.ixx new file mode 100644 index 0000000..04e6261 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gday.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/gday.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline gday_simpl:: + gday_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx b/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx new file mode 100644 index 0000000..fd8f461 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx @@ -0,0 +1,68 @@ +// file : xsde/cxx/serializer/validating/gmonth-day.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void gmonth_day_simpl:: + pre (const gmonth_day& value) + { + value_ = value; + } + + void gmonth_day_simpl:: + _serialize_content () + { + // We only need strlen("--MM-DD+hh:mm") + 1 characters to hold all + // representations of gMonthDay. + // + char str[14]; + + unsigned short m = value_.month (); + unsigned short d = value_.day (); + + if (m > 0 && m < 13 && d > 0 && d < 32 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 8, "--%.2u-%.2u", m, d); +#else + int n = sprintf (str, "--%.2u-%.2u", m, d); +#endif + if (n > 0 && n < 8) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_gmonth_day_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_gmonth_day_value); + } + else + _schema_error (schema_error::invalid_gmonth_day_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth-day.hxx b/libxsde/xsde/cxx/serializer/validating/gmonth-day.hxx new file mode 100644 index 0000000..60d5d11 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth-day.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/gmonth-day.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_DAY_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_DAY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_day_simpl: virtual gmonth_day_sskel +#else + struct gmonth_day_simpl: gmonth_day_sskel +#endif + { + gmonth_day_simpl (); + + virtual void + pre (const gmonth_day&); + + virtual void + _serialize_content (); + + protected: + gmonth_day value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_DAY_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth-day.ixx b/libxsde/xsde/cxx/serializer/validating/gmonth-day.ixx new file mode 100644 index 0000000..23581ee --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth-day.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/gmonth-day.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline gmonth_day_simpl:: + gmonth_day_simpl () + : value_ (1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth.cxx b/libxsde/xsde/cxx/serializer/validating/gmonth.cxx new file mode 100644 index 0000000..ad5cf27 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/serializer/validating/gmonth.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void gmonth_simpl:: + pre (const gmonth& value) + { + value_ = value; + } + + void gmonth_simpl:: + _serialize_content () + { + // We only need strlen("--MM+hh:mm") + 1 characters to hold all + // representations of gMonth. + // + char str[11]; + + unsigned short m = value_.month (); + + if (m > 0 && m < 13 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 5, "--%.2u", m); +#else + int n = sprintf (str, "--%.2u", m); +#endif + if (n > 0 && n < 5) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_gmonth_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_gmonth_value); + } + else + _schema_error (schema_error::invalid_gmonth_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth.hxx b/libxsde/xsde/cxx/serializer/validating/gmonth.hxx new file mode 100644 index 0000000..10d9575 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/gmonth.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gmonth_simpl: virtual gmonth_sskel +#else + struct gmonth_simpl: gmonth_sskel +#endif + { + gmonth_simpl (); + + virtual void + pre (const gmonth&); + + virtual void + _serialize_content (); + + protected: + gmonth value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_GMONTH_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth.ixx b/libxsde/xsde/cxx/serializer/validating/gmonth.ixx new file mode 100644 index 0000000..ae0a8dc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gmonth.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/gmonth.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline gmonth_simpl:: + gmonth_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gyear-month.cxx b/libxsde/xsde/cxx/serializer/validating/gyear-month.cxx new file mode 100644 index 0000000..ab4ab15 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear-month.cxx @@ -0,0 +1,68 @@ +// file : xsde/cxx/serializer/validating/gyear-month.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void gyear_month_simpl:: + pre (const gyear_month& value) + { + value_ = value; + } + + void gyear_month_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649-MM+hh:mm") + 1 characters to + // hold all representations of gYearMonth. + // + char str[21]; + + int y = value_.year (); + unsigned short m = value_.month (); + + if (y != 0 && m > 0 && m < 13 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 15, "%.4d-%.2u", y, m); +#else + int n = sprintf (str, "%.4d-%.2u", y, m); +#endif + if (n > 0 && n < 15) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_gyear_month_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_gyear_month_value); + } + else + _schema_error (schema_error::invalid_gyear_month_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gyear-month.hxx b/libxsde/xsde/cxx/serializer/validating/gyear-month.hxx new file mode 100644 index 0000000..9a0107e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear-month.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/gyear-month.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_MONTH_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_MONTH_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_month_simpl: virtual gyear_month_sskel +#else + struct gyear_month_simpl: gyear_month_sskel +#endif + { + gyear_month_simpl (); + + virtual void + pre (const gyear_month&); + + virtual void + _serialize_content (); + + protected: + gyear_month value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_MONTH_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/gyear-month.ixx b/libxsde/xsde/cxx/serializer/validating/gyear-month.ixx new file mode 100644 index 0000000..5aea7eb --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear-month.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/gyear-month.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline gyear_month_simpl:: + gyear_month_simpl () + : value_ (1, 1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gyear.cxx b/libxsde/xsde/cxx/serializer/validating/gyear.cxx new file mode 100644 index 0000000..6b34506 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear.cxx @@ -0,0 +1,67 @@ +// file : xsde/cxx/serializer/validating/gyear.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void gyear_simpl:: + pre (const gyear& value) + { + value_ = value; + } + + void gyear_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649+hh:mm") + 1 characters to + // hold all representations of gYear. + // + char str[18]; + + int y = value_.year (); + + if (y != 0 && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 12, "%.4d", y); +#else + int n = sprintf (str, "%.4d", y); +#endif + if (n > 0 && n < 12) + { + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_gyear_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_gyear_value); + } + else + _schema_error (schema_error::invalid_gyear_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/gyear.hxx b/libxsde/xsde/cxx/serializer/validating/gyear.hxx new file mode 100644 index 0000000..0ae7e1a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/gyear.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct gyear_simpl: virtual gyear_sskel +#else + struct gyear_simpl: gyear_sskel +#endif + { + gyear_simpl (); + + virtual void + pre (const gyear&); + + virtual void + _serialize_content (); + + protected: + gyear value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_GYEAR_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/gyear.ixx b/libxsde/xsde/cxx/serializer/validating/gyear.ixx new file mode 100644 index 0000000..7502a6b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/gyear.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/gyear.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline gyear_simpl:: + gyear_simpl () + : value_ (1) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/hex-binary.cxx b/libxsde/xsde/cxx/serializer/validating/hex-binary.cxx new file mode 100644 index 0000000..0250e71 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/hex-binary.cxx @@ -0,0 +1,70 @@ +// file : xsde/cxx/serializer/validating/hex-binary.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + hex_binary_simpl:: + ~hex_binary_simpl () + { + if (free_) + delete const_cast (value_); + } + + void hex_binary_simpl:: + pre (const buffer* value) + { + value_ = value; + } + + static const char hex_tab[] = "0123456789ABCDEF"; + + void hex_binary_simpl:: + _serialize_content () + { + char buf[512]; + + size_t size = value_->size (); + const char* data = value_->data (); + + // Covert the data in 256-byte chunks. + // + for (size_t j = 0; j < size;) + { + size_t i = 0; + + for (; i < 512 && j < size; ++j) + { + unsigned char byte = static_cast (data[j]); + + buf[i++] = hex_tab[byte >> 4]; + buf[i++] = hex_tab[byte & 0x0F]; + } + +#ifdef XSDE_EXCEPTIONS + _characters (buf, i); +#else + if (!_characters (buf, i)) + break; +#endif + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/hex-binary.hxx b/libxsde/xsde/cxx/serializer/validating/hex-binary.hxx new file mode 100644 index 0000000..524d9a9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/hex-binary.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/hex-binary.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_HEX_BINARY_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_HEX_BINARY_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct hex_binary_simpl: virtual hex_binary_sskel +#else + struct hex_binary_simpl: hex_binary_sskel +#endif + { + virtual + ~hex_binary_simpl (); + + hex_binary_simpl (bool free = false); + + virtual void + pre (const buffer*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const buffer* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_HEX_BINARY_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/hex-binary.ixx b/libxsde/xsde/cxx/serializer/validating/hex-binary.ixx new file mode 100644 index 0000000..134d30a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/hex-binary.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/hex-binary.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline hex_binary_simpl:: + hex_binary_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/id-stl.cxx b/libxsde/xsde/cxx/serializer/validating/id-stl.cxx new file mode 100644 index 0000000..0166069 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/id-stl.cxx @@ -0,0 +1,38 @@ +// file : xsde/cxx/serializer/validating/id-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void id_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void id_simpl:: + _serialize_content () + { + std::string tmp; + tmp.swap (value_); + + if (xml::valid_ncname (tmp.c_str (), tmp.size ())) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_id_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/id-stl.hxx b/libxsde/xsde/cxx/serializer/validating/id-stl.hxx new file mode 100644 index 0000000..f804eac --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/id-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/id-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_ID_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_ID_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_simpl: virtual id_sskel +#else + struct id_simpl: id_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_ID_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/id.cxx b/libxsde/xsde/cxx/serializer/validating/id.cxx new file mode 100644 index 0000000..2926ffe --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/id.cxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/id.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + id_simpl:: + ~id_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void id_simpl:: + pre (const char* value) + { + value_ = value; + } + + void id_simpl:: + _serialize_content () + { + size_t n = strlen (value_); + + if (xml::valid_ncname (value_, n)) + _characters (value_, n); + else + _schema_error (schema_error::invalid_id_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/id.hxx b/libxsde/xsde/cxx/serializer/validating/id.hxx new file mode 100644 index 0000000..dac47f3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/id.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/id.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_ID_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_ID_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_simpl: virtual id_sskel +#else + struct id_simpl: id_sskel +#endif + { + virtual + ~id_simpl (); + + id_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_ID_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/id.ixx b/libxsde/xsde/cxx/serializer/validating/id.ixx new file mode 100644 index 0000000..d771919 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/id.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/id.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline id_simpl:: + id_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idref-stl.cxx b/libxsde/xsde/cxx/serializer/validating/idref-stl.cxx new file mode 100644 index 0000000..620b16f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idref-stl.cxx @@ -0,0 +1,38 @@ +// file : xsde/cxx/serializer/validating/idref-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void idref_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void idref_simpl:: + _serialize_content () + { + std::string tmp; + tmp.swap (value_); + + if (xml::valid_ncname (tmp.c_str (), tmp.size ())) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_idref_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idref-stl.hxx b/libxsde/xsde/cxx/serializer/validating/idref-stl.hxx new file mode 100644 index 0000000..e90443e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idref-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/idref-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_IDREF_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_IDREF_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_simpl: virtual idref_sskel +#else + struct idref_simpl: idref_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_IDREF_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/idref.cxx b/libxsde/xsde/cxx/serializer/validating/idref.cxx new file mode 100644 index 0000000..87d6c5c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idref.cxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/idref.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + idref_simpl:: + ~idref_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void idref_simpl:: + pre (const char* value) + { + value_ = value; + } + + void idref_simpl:: + _serialize_content () + { + size_t n = strlen (value_); + + if (xml::valid_ncname (value_, n)) + _characters (value_, n); + else + _schema_error (schema_error::invalid_idref_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idref.hxx b/libxsde/xsde/cxx/serializer/validating/idref.hxx new file mode 100644 index 0000000..b8d82ce --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idref.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/idref.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_IDREF_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_IDREF_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_simpl: virtual idref_sskel +#else + struct idref_simpl: idref_sskel +#endif + { + virtual + ~idref_simpl (); + + idref_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_IDREF_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/idref.ixx b/libxsde/xsde/cxx/serializer/validating/idref.ixx new file mode 100644 index 0000000..34a6838 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idref.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/idref.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline idref_simpl:: + idref_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs-stl.cxx b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.cxx new file mode 100644 index 0000000..bdcf937 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.cxx @@ -0,0 +1,109 @@ +// file : xsde/cxx/serializer/validating/idrefs-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + idrefs_simpl:: + ~idrefs_simpl () + { + if (free_) + delete const_cast (value_); + } + + void idrefs_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void idrefs_simpl:: + _serialize_content () + { + // Should have at least one element. + // + if (!value_->empty ()) + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { + serializer_.pre (*i); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + + if (!first) + { +#ifdef XSDE_EXCEPTIONS + _characters (" ", 1); +#else + if (!_characters (" ", 1)) + break; +#endif + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + } + else + _schema_error (schema_error::invalid_idrefs_value); + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void idrefs_simpl:: + _reset () + { + idrefs_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs-stl.hxx b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.hxx new file mode 100644 index 0000000..03cd1da --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/idrefs-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_simpl: virtual idrefs_sskel +#else + struct idrefs_simpl: idrefs_sskel +#endif + { + virtual + ~idrefs_simpl (); + + idrefs_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + idref_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs-stl.ixx b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.ixx new file mode 100644 index 0000000..9c6e46c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/idrefs-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline idrefs_simpl:: + idrefs_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs.cxx b/libxsde/xsde/cxx/serializer/validating/idrefs.cxx new file mode 100644 index 0000000..e6548c4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs.cxx @@ -0,0 +1,110 @@ +// file : xsde/cxx/serializer/validating/idrefs.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + idrefs_simpl:: + ~idrefs_simpl () + { + if (free_) + delete const_cast (value_); + } + + void idrefs_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void idrefs_simpl:: + _serialize_content () + { + // Should have at least one element. + // + if (!value_->empty ()) + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { + serializer_.pre (*i); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + + if (!first) + { +#ifdef XSDE_EXCEPTIONS + _characters (" ", 1); +#else + if (!_characters (" ", 1)) + break; +#endif + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + } + else + _schema_error (schema_error::invalid_idrefs_value); + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void idrefs_simpl:: + _reset () + { + idrefs_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs.hxx b/libxsde/xsde/cxx/serializer/validating/idrefs.hxx new file mode 100644 index 0000000..23386dd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/idrefs.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idrefs_simpl: virtual idrefs_sskel +#else + struct idrefs_simpl: idrefs_sskel +#endif + { + virtual + ~idrefs_simpl (); + + idrefs_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + idref_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_IDREFS_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/idrefs.ixx b/libxsde/xsde/cxx/serializer/validating/idrefs.ixx new file mode 100644 index 0000000..b077e58 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/idrefs.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/idrefs.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline idrefs_simpl:: + idrefs_simpl (bool free) + : free_ (free), value_ (0), serializer_ (false) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/inheritance-map-load.hxx b/libxsde/xsde/cxx/serializer/validating/inheritance-map-load.hxx new file mode 100644 index 0000000..abdcd43 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/inheritance-map-load.hxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/validating/inheritance-map-load.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_LOAD_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_LOAD_HXX + +#include // size_t + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + size_t + serializer_imap_elements (); + + inline size_t + serializer_imap_buckets () + { + return XSDE_SERIALIZER_IMAP_BUCKETS; + } + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_LOAD_HXX + diff --git a/libxsde/xsde/cxx/serializer/validating/inheritance-map.cxx b/libxsde/xsde/cxx/serializer/validating/inheritance-map.cxx new file mode 100644 index 0000000..94fdabc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/inheritance-map.cxx @@ -0,0 +1,111 @@ +// file : xsde/cxx/serializer/validating/inheritance-map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include // strcmp + +#ifndef XSDE_EXCEPTIONS +# include // assert +# include // exit +#endif + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inheritance_map* inheritance_map_init::map = 0; + size_t inheritance_map_init::count = 0; + + bool inheritance_map:: + check (const char* derived, const char* base) const + { + if (strcmp (derived, base) == 0) + return true; + + const void* p = find (derived); + + if (p) + { + const char* b = *static_cast (p); + return strcmp (base, b) == 0 ? true : check (b, base); + } + + return false; + } + + // inheritance_map_init + // + inheritance_map_init:: + inheritance_map_init () + { + if (count == 0) + { + map = new inheritance_map (XSDE_SERIALIZER_IMAP_BUCKETS); + +#ifndef XSDE_EXCEPTIONS + if (map == 0 || map->_error () != inheritance_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + ++count; + } + + inheritance_map_init:: + ~inheritance_map_init () + { + if (--count == 0) + delete map; + } + + // inheritance_map_entry + // + inheritance_map_entry:: + inheritance_map_entry (const char* derived, const char* base) + { + inheritance_map& m = inheritance_map_instance (); + m.insert (derived, base); + +#ifndef XSDE_EXCEPTIONS + if (m._error () != inheritance_map::error_none) + { + // This is static initialization so there is nothing we can do. + // The best thing is to fail fast. abort() would have probably + // been the better choice here but it is not available on some + // platforms (notably, WinCE). + // + assert (false); + exit (1); + } +#endif + } + + // + // + size_t + serializer_imap_elements () + { + return inheritance_map_instance ().size (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/inheritance-map.hxx b/libxsde/xsde/cxx/serializer/validating/inheritance-map.hxx new file mode 100644 index 0000000..051dbfc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/inheritance-map.hxx @@ -0,0 +1,63 @@ +// file : xsde/cxx/serializer/validating/inheritance-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_HXX + +#include // size_t + +#include +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + struct inheritance_map: hashmap + { + inheritance_map (size_t buckets); + + void + insert (const char* derived, const char* base); + + bool + check (const char* derived, const char* base) const; + }; + + + // Translation unit initializer. + // + struct inheritance_map_init + { + static inheritance_map* map; + static size_t count; + + inheritance_map_init (); + ~inheritance_map_init (); + }; + + inline inheritance_map& + inheritance_map_instance (); + + // Map entry initializer. + // + struct inheritance_map_entry + { + inheritance_map_entry (const char* derived, const char* base); + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_INHERITANCE_MAP_HXX + diff --git a/libxsde/xsde/cxx/serializer/validating/inheritance-map.ixx b/libxsde/xsde/cxx/serializer/validating/inheritance-map.ixx new file mode 100644 index 0000000..2ae6fcf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/inheritance-map.ixx @@ -0,0 +1,34 @@ +// file : xsde/cxx/serializer/validating/inheritance-map.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline inheritance_map:: + inheritance_map (size_t buckets) + : hashmap (buckets, sizeof (const char*)) + { + } + + inline void inheritance_map:: + insert (const char* derived, const char* base) + { + hashmap::insert (derived, &base); + } + + inline inheritance_map& + inheritance_map_instance () + { + return *inheritance_map_init::map; + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/int.cxx b/libxsde/xsde/cxx/serializer/validating/int.cxx new file mode 100644 index 0000000..780abbe --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/int.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void int_simpl:: + pre (int value) + { + value_ = value; + } + + void int_simpl:: + _serialize_content () + { + // We only need strlen("-2147483649") + 1 characters to hold all + // representations of int. + // + char str[12]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 12, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 12) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_int_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/int.hxx b/libxsde/xsde/cxx/serializer/validating/int.hxx new file mode 100644 index 0000000..6d798d6 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/int.hxx @@ -0,0 +1,39 @@ +// file : xsde/cxx/serializer/validating/int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_INT_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_INT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct int_simpl: virtual int_sskel +#else + struct int_simpl: int_sskel +#endif + { + virtual void + pre (int); + + virtual void + _serialize_content (); + + protected: + int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_INT_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/integer.cxx b/libxsde/xsde/cxx/serializer/validating/integer.cxx new file mode 100644 index 0000000..8df6c55 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/integer.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void integer_simpl:: + pre (long value) + { + value_ = value; + } + + void integer_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_integer_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/integer.hxx b/libxsde/xsde/cxx/serializer/validating/integer.hxx new file mode 100644 index 0000000..ada9796 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Arbitrary-length integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct integer_simpl: virtual integer_sskel +#else + struct integer_simpl: integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/language-stl.cxx b/libxsde/xsde/cxx/serializer/validating/language-stl.cxx new file mode 100644 index 0000000..cd4e1d2 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/language-stl.cxx @@ -0,0 +1,73 @@ +// file : xsde/cxx/serializer/validating/language-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void language_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void language_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + bool ok = true; + const char* s = tmp.c_str (); + + // language := ALPHA{1,8} *(-(ALPHA | DIGIT){1,8}) + // + for (size_t tag = 0; ; ++tag) + { + size_t n = 0; + + for (; *s != '\0' && n < 8; ++n, ++s) + { + char c = *s; + + if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (tag != 0 && c >= '0' && c <= '9'))) + break; + } + + if (n == 0) + { + ok = false; + break; + } + + if (*s == '\0') + break; + + if (*s++ != '-') + { + ok = false; + break; + } + } + + if (ok) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_language_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/language-stl.hxx b/libxsde/xsde/cxx/serializer/validating/language-stl.hxx new file mode 100644 index 0000000..2216bff --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/language-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/language-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_simpl: virtual language_sskel +#else + struct language_simpl: language_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/language.cxx b/libxsde/xsde/cxx/serializer/validating/language.cxx new file mode 100644 index 0000000..14f69fc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/language.cxx @@ -0,0 +1,81 @@ +// file : xsde/cxx/serializer/validating/language.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + language_simpl:: + ~language_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void language_simpl:: + pre (const char* value) + { + value_ = value; + } + + void language_simpl:: + _serialize_content () + { + bool ok = true; + const char* s = value_; + + // language := ALPHA{1,8} *(-(ALPHA | DIGIT){1,8}) + // + for (size_t tag = 0; ; ++tag) + { + size_t n = 0; + + for (; *s != '\0' && n < 8; ++n, ++s) + { + char c = *s; + + if (!((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (tag != 0 && c >= '0' && c <= '9'))) + break; + } + + if (n == 0) + { + ok = false; + break; + } + + if (*s == '\0') + break; + + if (*s++ != '-') + { + ok = false; + break; + } + } + + if (ok) + _characters (value_); + else + _schema_error (schema_error::invalid_language_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/language.hxx b/libxsde/xsde/cxx/serializer/validating/language.hxx new file mode 100644 index 0000000..708a5b0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/language.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/language.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_simpl: virtual language_sskel +#else + struct language_simpl: language_sskel +#endif + { + virtual + ~language_simpl (); + + language_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_LANGUAGE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/language.ixx b/libxsde/xsde/cxx/serializer/validating/language.ixx new file mode 100644 index 0000000..3385220 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/language.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/language.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline language_simpl:: + language_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/long-long.cxx b/libxsde/xsde/cxx/serializer/validating/long-long.cxx new file mode 100644 index 0000000..2773ec7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/long-long.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void long_simpl:: + pre (long long value) + { + value_ = value; + } + + void long_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of long long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lld", value_); +#else + int n = sprintf (str, "%lld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_long_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/long-long.hxx b/libxsde/xsde/cxx/serializer/validating/long-long.hxx new file mode 100644 index 0000000..97e14d1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/long-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_LONG_LONG_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_LONG_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 64-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_simpl: virtual long_sskel +#else + struct long_simpl: long_sskel +#endif + { + virtual void + pre (long long); + + virtual void + _serialize_content (); + + protected: + long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/long.cxx b/libxsde/xsde/cxx/serializer/validating/long.cxx new file mode 100644 index 0000000..574a22e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/long.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void long_simpl:: + pre (long value) + { + value_ = value; + } + + void long_simpl:: + _serialize_content () + { + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_long_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/long.hxx b/libxsde/xsde/cxx/serializer/validating/long.hxx new file mode 100644 index 0000000..7ffadc7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_LONG_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct long_simpl: virtual long_sskel +#else + struct long_simpl: long_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/name-stl.cxx b/libxsde/xsde/cxx/serializer/validating/name-stl.cxx new file mode 100644 index 0000000..e80bf9b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/name-stl.cxx @@ -0,0 +1,62 @@ +// file : xsde/cxx/serializer/validating/name-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void name_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void name_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + const char* s = tmp.c_str (); + bool ok = (*s != '\0'); + + // For now we are only checking the US-ASCII characters. + // + if (ok) + { + // First character. + // + unsigned char c = static_cast (*s); + + ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask); + + for (++s; ok && *s != '\0'; ++s) + { + c = static_cast (*s); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + ok = false; + } + } + + if (ok) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_name_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/name-stl.hxx b/libxsde/xsde/cxx/serializer/validating/name-stl.hxx new file mode 100644 index 0000000..8e67a28 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/name-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/name-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NAME_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_simpl: virtual name_sskel +#else + struct name_simpl: name_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/name.cxx b/libxsde/xsde/cxx/serializer/validating/name.cxx new file mode 100644 index 0000000..7c916d8 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/name.cxx @@ -0,0 +1,70 @@ +// file : xsde/cxx/serializer/validating/name.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + name_simpl:: + ~name_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void name_simpl:: + pre (const char* value) + { + value_ = value; + } + + void name_simpl:: + _serialize_content () + { + const char* s = value_; + bool ok = (*s != '\0'); + + // For now we are only checking the US-ASCII characters. + // + if (ok) + { + // First character. + // + unsigned char c = static_cast (*s); + + ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask); + + for (++s; ok && *s != '\0'; ++s) + { + c = static_cast (*s); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + ok = false; + } + } + + if (ok) + _characters (value_); + else + _schema_error (schema_error::invalid_name_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/name.hxx b/libxsde/xsde/cxx/serializer/validating/name.hxx new file mode 100644 index 0000000..3c4fe2e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/name.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/name.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NAME_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_simpl: virtual name_sskel +#else + struct name_simpl: name_sskel +#endif + { + virtual + ~name_simpl (); + + name_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NAME_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/name.ixx b/libxsde/xsde/cxx/serializer/validating/name.ixx new file mode 100644 index 0000000..84fbdf3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/name.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/name.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline name_simpl:: + name_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/ncname-stl.cxx b/libxsde/xsde/cxx/serializer/validating/ncname-stl.cxx new file mode 100644 index 0000000..4dec901 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/ncname-stl.cxx @@ -0,0 +1,38 @@ +// file : xsde/cxx/serializer/validating/ncname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void ncname_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void ncname_simpl:: + _serialize_content () + { + std::string tmp; + tmp.swap (value_); + + if (xml::valid_ncname (tmp.c_str (), tmp.size ())) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_ncname_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/ncname-stl.hxx b/libxsde/xsde/cxx/serializer/validating/ncname-stl.hxx new file mode 100644 index 0000000..f9bd61d --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/ncname-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/ncname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_simpl: virtual ncname_sskel +#else + struct ncname_simpl: ncname_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/ncname.cxx b/libxsde/xsde/cxx/serializer/validating/ncname.cxx new file mode 100644 index 0000000..9f74a59 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/ncname.cxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/ncname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + ncname_simpl:: + ~ncname_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void ncname_simpl:: + pre (const char* value) + { + value_ = value; + } + + void ncname_simpl:: + _serialize_content () + { + size_t n = strlen (value_); + + if (xml::valid_ncname (value_, n)) + _characters (value_, n); + else + _schema_error (schema_error::invalid_ncname_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/ncname.hxx b/libxsde/xsde/cxx/serializer/validating/ncname.hxx new file mode 100644 index 0000000..baafaa4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/ncname.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/ncname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_simpl: virtual ncname_sskel +#else + struct ncname_simpl: ncname_sskel +#endif + { + virtual + ~ncname_simpl (); + + ncname_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NCNAME_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/ncname.ixx b/libxsde/xsde/cxx/serializer/validating/ncname.ixx new file mode 100644 index 0000000..5d6bf02 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/ncname.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/ncname.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline ncname_simpl:: + ncname_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/negative-integer.cxx b/libxsde/xsde/cxx/serializer/validating/negative-integer.cxx new file mode 100644 index 0000000..bb41770 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/negative-integer.cxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/serializer/validating/negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void negative_integer_simpl:: + pre (long value) + { + value_ = value; + } + + void negative_integer_simpl:: + _serialize_content () + { + if (value_ >= 0) + { + _schema_error (schema_error::invalid_negative_integer_value); + return; + } + + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_negative_integer_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/negative-integer.hxx b/libxsde/xsde/cxx/serializer/validating/negative-integer.hxx new file mode 100644 index 0000000..40fcd80 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/negative-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NEGATIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Arbitrary-length negative integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct negative_integer_simpl: virtual negative_integer_sskel +#else + struct negative_integer_simpl: negative_integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.cxx b/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.cxx new file mode 100644 index 0000000..c0cf793 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.cxx @@ -0,0 +1,53 @@ +// file : xsde/cxx/serializer/validating/nmtoken-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void nmtoken_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void nmtoken_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + const char* s = tmp.c_str (); + bool ok = (*s != '\0'); + + // For now we are only checking the US-ASCII characters. + // + for (; ok && *s != '\0'; ++s) + { + unsigned char c = static_cast (*s); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + ok = false; + } + + if (ok) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_nmtoken_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.hxx b/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.hxx new file mode 100644 index 0000000..3de2784 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtoken-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/nmtoken-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_simpl: virtual nmtoken_sskel +#else + struct nmtoken_simpl: nmtoken_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/nmtoken.cxx b/libxsde/xsde/cxx/serializer/validating/nmtoken.cxx new file mode 100644 index 0000000..2563023 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtoken.cxx @@ -0,0 +1,61 @@ +// file : xsde/cxx/serializer/validating/nmtoken.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + nmtoken_simpl:: + ~nmtoken_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void nmtoken_simpl:: + pre (const char* value) + { + value_ = value; + } + + void nmtoken_simpl:: + _serialize_content () + { + const char* s = value_; + bool ok = (*s != '\0'); + + // For now we are only checking the US-ASCII characters. + // + for (; ok && *s != '\0'; ++s) + { + unsigned char c = static_cast (*s); + + if (c < 0x80 && !(xml::char_table[c] & xml::name_char_mask)) + ok = false; + } + + if (ok) + _characters (value_); + else + _schema_error (schema_error::invalid_nmtoken_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/nmtoken.hxx b/libxsde/xsde/cxx/serializer/validating/nmtoken.hxx new file mode 100644 index 0000000..7951384 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtoken.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/nmtoken.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_simpl: virtual nmtoken_sskel +#else + struct nmtoken_simpl: nmtoken_sskel +#endif + { + virtual + ~nmtoken_simpl (); + + nmtoken_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NMTOKEN_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/nmtoken.ixx b/libxsde/xsde/cxx/serializer/validating/nmtoken.ixx new file mode 100644 index 0000000..4559310 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtoken.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/nmtoken.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline nmtoken_simpl:: + nmtoken_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.cxx b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.cxx new file mode 100644 index 0000000..6607177 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.cxx @@ -0,0 +1,109 @@ +// file : xsde/cxx/serializer/validating/nmtokens-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + nmtokens_simpl:: + ~nmtokens_simpl () + { + if (free_) + delete const_cast (value_); + } + + void nmtokens_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void nmtokens_simpl:: + _serialize_content () + { + // Should have at least one element. + // + if (!value_->empty ()) + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { + serializer_.pre (*i); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + + if (!first) + { +#ifdef XSDE_EXCEPTIONS + _characters (" ", 1); +#else + if (!_characters (" ", 1)) + break; +#endif + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + } + else + _schema_error (schema_error::invalid_nmtokens_value); + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void nmtokens_simpl:: + _reset () + { + nmtokens_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.hxx b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.hxx new file mode 100644 index 0000000..aab3fae --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/nmtokens-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_STL_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_simpl: virtual nmtokens_sskel +#else + struct nmtokens_simpl: nmtokens_sskel +#endif + { + virtual + ~nmtokens_simpl (); + + nmtokens_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + nmtoken_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.ixx b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.ixx new file mode 100644 index 0000000..988c9cd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/nmtokens-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline nmtokens_simpl:: + nmtokens_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens.cxx b/libxsde/xsde/cxx/serializer/validating/nmtokens.cxx new file mode 100644 index 0000000..74e111b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens.cxx @@ -0,0 +1,110 @@ +// file : xsde/cxx/serializer/validating/nmtokens.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + nmtokens_simpl:: + ~nmtokens_simpl () + { + if (free_) + delete const_cast (value_); + } + + void nmtokens_simpl:: + pre (const string_sequence* value) + { + value_ = value; + } + + void nmtokens_simpl:: + _serialize_content () + { + // Should have at least one element. + // + if (!value_->empty ()) + { + bool first = true; + context& ctx = _context (); + + for (string_sequence::const_iterator i (value_->begin ()), + e (value_->end ()); i != e; ++i) + { + serializer_.pre (*i); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + + if (!first) + { +#ifdef XSDE_EXCEPTIONS + _characters (" ", 1); +#else + if (!_characters (" ", 1)) + break; +#endif + } + else + first = false; + + serializer_._pre_impl (ctx); + + if (ctx.error_type ()) + break; + + serializer_._serialize_content (); + + if (ctx.error_type ()) + break; + + serializer_._post_impl (); + + if (ctx.error_type ()) + break; + + serializer_.post (); + +#ifndef XSDE_EXCEPTIONS + if (serializer_._error_type ()) + serializer_._copy_error (ctx); + + if (ctx.error_type ()) + break; +#endif + } + } + else + _schema_error (schema_error::invalid_nmtokens_value); + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + + void nmtokens_simpl:: + _reset () + { + nmtokens_sskel::_reset (); + serializer_._reset (); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens.hxx b/libxsde/xsde/cxx/serializer/validating/nmtokens.hxx new file mode 100644 index 0000000..525ab13 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens.hxx @@ -0,0 +1,52 @@ +// file : xsde/cxx/serializer/validating/nmtokens.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_HXX + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtokens_simpl: virtual nmtokens_sskel +#else + struct nmtokens_simpl: nmtokens_sskel +#endif + { + virtual + ~nmtokens_simpl (); + + nmtokens_simpl (bool free = false); + + virtual void + pre (const string_sequence*); + + virtual void + _serialize_content (); + + virtual void + _reset (); + + protected: + bool free_; + const string_sequence* value_; + nmtoken_simpl serializer_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NMTOKENS_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/nmtokens.ixx b/libxsde/xsde/cxx/serializer/validating/nmtokens.ixx new file mode 100644 index 0000000..0526e30 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/nmtokens.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/nmtokens.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline nmtokens_simpl:: + nmtokens_simpl (bool free) + : free_ (free), value_ (0), serializer_ (false) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/non-negative-integer.cxx b/libxsde/xsde/cxx/serializer/validating/non-negative-integer.cxx new file mode 100644 index 0000000..87a6e22 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/non-negative-integer.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/non-negative-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void non_negative_integer_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void non_negative_integer_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_non_negative_integer_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/non-negative-integer.hxx b/libxsde/xsde/cxx/serializer/validating/non-negative-integer.hxx new file mode 100644 index 0000000..8d5b769 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/non-negative-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/non-negative-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NON_NEGATIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NON_NEGATIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Arbitrary-length non-negative integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_negative_integer_simpl: virtual non_negative_integer_sskel +#else + struct non_negative_integer_simpl: non_negative_integer_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NON_NEGATIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/non-positive-integer.cxx b/libxsde/xsde/cxx/serializer/validating/non-positive-integer.cxx new file mode 100644 index 0000000..bbd2854 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/non-positive-integer.cxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/serializer/validating/non-positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void non_positive_integer_simpl:: + pre (long value) + { + value_ = value; + } + + void non_positive_integer_simpl:: + _serialize_content () + { + if (value_ > 0) + { + _schema_error (schema_error::invalid_non_positive_integer_value); + return; + } + + // We only need strlen("-9223372036854775808") + 1 characters to + // hold all representations of (possibly 64-bit) long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%ld", value_); +#else + int n = sprintf (str, "%ld", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_non_positive_integer_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/non-positive-integer.hxx b/libxsde/xsde/cxx/serializer/validating/non-positive-integer.hxx new file mode 100644 index 0000000..9defbba --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/non-positive-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/non-positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NON_POSITIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NON_POSITIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Arbitrary-length non-positive integer. Mapped to long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct non_positive_integer_simpl: virtual non_positive_integer_sskel +#else + struct non_positive_integer_simpl: non_positive_integer_sskel +#endif + { + virtual void + pre (long); + + virtual void + _serialize_content (); + + protected: + long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NON_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.cxx b/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.cxx new file mode 100644 index 0000000..7c945da --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.cxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/normalized-string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void normalized_string_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void normalized_string_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + const char* s = tmp.c_str (); + + for (; *s != '\0'; ++s) + { + if (*s == 0x0A || *s == 0x0D || *s == 0x09) + break; + } + + if (*s == '\0') + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_normalized_string_value); + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.hxx b/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.hxx new file mode 100644 index 0000000..98ae359 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/normalized-string-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/normalized-string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_simpl: virtual normalized_string_sskel +#else + struct normalized_string_simpl: normalized_string_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/normalized-string.cxx b/libxsde/xsde/cxx/serializer/validating/normalized-string.cxx new file mode 100644 index 0000000..1e29376 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/normalized-string.cxx @@ -0,0 +1,55 @@ +// file : xsde/cxx/serializer/validating/normalized-string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + normalized_string_simpl:: + ~normalized_string_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void normalized_string_simpl:: + pre (const char* value) + { + value_ = value; + } + + void normalized_string_simpl:: + _serialize_content () + { + const char* s = value_; + + for (; *s != '\0'; ++s) + { + if (*s == 0x0A || *s == 0x0D || *s == 0x09) + break; + } + + if (*s == '\0') + _characters (value_); + else + _schema_error (schema_error::invalid_normalized_string_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} + diff --git a/libxsde/xsde/cxx/serializer/validating/normalized-string.hxx b/libxsde/xsde/cxx/serializer/validating/normalized-string.hxx new file mode 100644 index 0000000..6496ab9 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/normalized-string.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/normalized-string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_simpl: virtual normalized_string_sskel +#else + struct normalized_string_simpl: normalized_string_sskel +#endif + { + virtual + ~normalized_string_simpl (); + + normalized_string_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_NORMALIZED_STRING_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/normalized-string.ixx b/libxsde/xsde/cxx/serializer/validating/normalized-string.ixx new file mode 100644 index 0000000..dc9085f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/normalized-string.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/normalized-string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline normalized_string_simpl:: + normalized_string_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/positive-integer.cxx b/libxsde/xsde/cxx/serializer/validating/positive-integer.cxx new file mode 100644 index 0000000..dbb83cd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/positive-integer.cxx @@ -0,0 +1,51 @@ +// file : xsde/cxx/serializer/validating/positive-integer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void positive_integer_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void positive_integer_simpl:: + _serialize_content () + { + if (value_ == 0) + { + _schema_error (schema_error::invalid_positive_integer_value); + return; + } + + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_positive_integer_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/positive-integer.hxx b/libxsde/xsde/cxx/serializer/validating/positive-integer.hxx new file mode 100644 index 0000000..329145e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/positive-integer.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/positive-integer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_POSITIVE_INTEGER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_POSITIVE_INTEGER_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Arbitrary-length positive integer. Mapped to unsigned long. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct positive_integer_simpl: virtual positive_integer_sskel +#else + struct positive_integer_simpl: positive_integer_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_POSITIVE_INTEGER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/qname-stl.cxx b/libxsde/xsde/cxx/serializer/validating/qname-stl.cxx new file mode 100644 index 0000000..0e48748 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname-stl.cxx @@ -0,0 +1,68 @@ +// file : xsde/cxx/serializer/validating/qname-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void qname_simpl:: + pre (const qname& value) + { + value_ = value; + } + + void qname_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the qname. + // + qname tmp ("a"); + tmp.swap (value_); + + const char* ns = tmp.name ().c_str (); + size_t nn = tmp.name ().size (); + + if (!tmp.prefix ().empty ()) + { + const char* ps = tmp.prefix ().c_str (); + size_t pn = tmp.prefix ().size (); + + if (xml::valid_ncname (ps, pn) && xml::valid_ncname (ns, nn)) + { +#ifdef XSDE_EXCEPTIONS + _characters (ps, pn); + _characters (":", 1); + _characters (ns, nn); +#else + if (_characters (ps, pn)) + { + if (_characters (":", 1)) + _characters (ns, nn); + } +#endif + } + else + _schema_error (schema_error::invalid_qname_value); + } + else + { + if (xml::valid_ncname (ns, nn)) + _characters (ns, nn); + else + _schema_error (schema_error::invalid_qname_value); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/qname-stl.hxx b/libxsde/xsde/cxx/serializer/validating/qname-stl.hxx new file mode 100644 index 0000000..8d87a4b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname-stl.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/qname-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_QNAME_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_QNAME_STL_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_simpl: virtual qname_sskel +#else + struct qname_simpl: qname_sskel +#endif + { + qname_simpl (); + + virtual void + pre (const qname&); + + virtual void + _serialize_content (); + + protected: + qname value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_QNAME_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/qname-stl.ixx b/libxsde/xsde/cxx/serializer/validating/qname-stl.ixx new file mode 100644 index 0000000..99edfdd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname-stl.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/qname-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline qname_simpl:: + qname_simpl () + : value_ ("a") + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/qname.cxx b/libxsde/xsde/cxx/serializer/validating/qname.cxx new file mode 100644 index 0000000..b69eb54 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/serializer/validating/qname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + qname_simpl:: + ~qname_simpl () + { + if (free_) + delete const_cast (value_); + } + + void qname_simpl:: + pre (const qname* value) + { + value_ = value; + } + + void qname_simpl:: + _serialize_content () + { + const char* ns = value_->name (); + size_t nn = strlen (ns); + + const char* ps = value_->prefix (); + + if (ps != 0 && *ps != '\0') + { + size_t pn = strlen (ps); + + if (xml::valid_ncname (ps, pn) && xml::valid_ncname (ns, nn)) + { +#ifdef XSDE_EXCEPTIONS + _characters (ps, pn); + _characters (":", 1); + _characters (ns, nn); +#else + if (_characters (ps, pn)) + { + if (_characters (":", 1)) + _characters (ns, nn); + } +#endif + } + else + _schema_error (schema_error::invalid_qname_value); + } + else + { + if (xml::valid_ncname (ns, nn)) + _characters (ns, nn); + else + _schema_error (schema_error::invalid_qname_value); + } + + if (free_) + { + delete const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/qname.hxx b/libxsde/xsde/cxx/serializer/validating/qname.hxx new file mode 100644 index 0000000..e9790f5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/qname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_QNAME_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_QNAME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct qname_simpl: virtual qname_sskel +#else + struct qname_simpl: qname_sskel +#endif + { + virtual + ~qname_simpl (); + + qname_simpl (bool free = false); + + virtual void + pre (const qname*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const qname* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_QNAME_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/qname.ixx b/libxsde/xsde/cxx/serializer/validating/qname.ixx new file mode 100644 index 0000000..08d69d1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/qname.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/qname.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline qname_simpl:: + qname_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/serializer.cxx b/libxsde/xsde/cxx/serializer/validating/serializer.cxx new file mode 100644 index 0000000..280c09f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/serializer.cxx @@ -0,0 +1,29 @@ +// file : xsde/cxx/serializer/validating/serializer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + void simple_content:: + _serialize_content () + { + if (impl_) + impl_->_serialize_content (); + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/serializer.hxx b/libxsde/xsde/cxx/serializer/validating/serializer.hxx new file mode 100644 index 0000000..d8ba64c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/serializer.hxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/serializer/validating/serializer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_SERIALIZER_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_SERIALIZER_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + struct empty_content: serializer_base + { +#ifdef XSDE_REUSE_STYLE_TIEIN + empty_content (); + empty_content (empty_content* impl, void*); +#endif + }; + + // + // + struct simple_content: empty_content + { +#ifdef XSDE_REUSE_STYLE_TIEIN + virtual void + _serialize_content (); + + simple_content (); + simple_content (simple_content* impl, void*); +#endif + }; + + // + // + struct complex_content: empty_content + { +#ifdef XSDE_REUSE_STYLE_TIEIN + complex_content (); + complex_content (complex_content* impl, void*); +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_SERIALIZER_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/serializer.ixx b/libxsde/xsde/cxx/serializer/validating/serializer.ixx new file mode 100644 index 0000000..66b9ad7 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/serializer.ixx @@ -0,0 +1,61 @@ +// file : xsde/cxx/serializer/validating/serializer.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // empty_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline empty_content:: + empty_content () + { + } + + inline empty_content:: + empty_content (empty_content* impl, void*) + : serializer_base (impl, 0) + { + } +#endif + + // simple_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline simple_content:: + simple_content () + { + } + + inline simple_content:: + simple_content (simple_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + + // complex_content + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline complex_content:: + complex_content () + { + } + + inline complex_content:: + complex_content (complex_content* impl, void*) + : empty_content (impl, 0) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/short.cxx b/libxsde/xsde/cxx/serializer/validating/short.cxx new file mode 100644 index 0000000..61e7132 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/short.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void short_simpl:: + pre (short value) + { + value_ = value; + } + + void short_simpl:: + _serialize_content () + { + // We only need strlen("-32768") + 1 characters to hold all + // representations of short. + // + char str[7]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 7, "%d", value_); +#else + int n = sprintf (str, "%d", value_); +#endif + if (n > 0 && n < 7) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_short_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/short.hxx b/libxsde/xsde/cxx/serializer/validating/short.hxx new file mode 100644 index 0000000..51da86f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/short.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_SHORT_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_SHORT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 16-bit signed integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct short_simpl: virtual short_sskel +#else + struct short_simpl: short_sskel +#endif + { + virtual void + pre (short); + + virtual void + _serialize_content (); + + protected: + short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_SHORT_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/string-stl.cxx b/libxsde/xsde/cxx/serializer/validating/string-stl.cxx new file mode 100644 index 0000000..a70533f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/string-stl.cxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/serializer/validating/string-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void string_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void string_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/string-stl.hxx b/libxsde/xsde/cxx/serializer/validating/string-stl.hxx new file mode 100644 index 0000000..74f55cc --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/string-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/string-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_STRING_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_STRING_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_simpl: virtual string_sskel +#else + struct string_simpl: string_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_STRING_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/string.cxx b/libxsde/xsde/cxx/serializer/validating/string.cxx new file mode 100644 index 0000000..b8a4068 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/string.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + string_simpl:: + ~string_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void string_simpl:: + pre (const char* value) + { + value_ = value; + } + + void string_simpl:: + _serialize_content () + { + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/string.hxx b/libxsde/xsde/cxx/serializer/validating/string.hxx new file mode 100644 index 0000000..5385355 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/string.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_STRING_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_STRING_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct string_simpl: virtual string_sskel +#else + struct string_simpl: string_sskel +#endif + { + virtual + ~string_simpl (); + + string_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_STRING_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/string.ixx b/libxsde/xsde/cxx/serializer/validating/string.ixx new file mode 100644 index 0000000..a23e517 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/string.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline string_simpl:: + string_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/time-zone.cxx b/libxsde/xsde/cxx/serializer/validating/time-zone.cxx new file mode 100644 index 0000000..ae28d70 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time-zone.cxx @@ -0,0 +1,65 @@ +// file : xsde/cxx/serializer/validating/time-zone.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + namespace bits + { + int + serialize_time_zone (char* s, const time_zone& z) + { + // time-zone := Z|(+|-)HH:MM + // + + short h = z.zone_hours (); + short m = z.zone_minutes (); + + if (h == 0 && m == 0) + { + *s = 'Z'; + return 1; + } + else + { + const char* fmt = "+%.2u:%.2u"; + + if (h < 0) + { + fmt = "-%.2u:%.2u"; + h = -h; + m = -m; + } + + if (h >= 0 && h <= 14 && m >= 0 && m <= 59) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (s, 7, fmt, h, m); +#else + int n = sprintf (s, fmt, h, m); +#endif + if (n > 0 && n < 7) + return n; + } + + return 0; + } + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/time-zone.hxx b/libxsde/xsde/cxx/serializer/validating/time-zone.hxx new file mode 100644 index 0000000..27784cf --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time-zone.hxx @@ -0,0 +1,40 @@ +// file : xsde/cxx/serializer/validating/time-zone.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_TIME_ZONE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_TIME_ZONE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + namespace bits + { + bool + valid_time_zone (const time_zone&); + + // Returns 0 in case of a failure and the number of + // characters written otherwise. The buffer should + // have space for at least 7 characters. Note that + // this function expects that the time zone was + // verified by valid_time_zone() above. + // + int + serialize_time_zone (char* s, const time_zone&); + } + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_TIME_ZONE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/time-zone.ixx b/libxsde/xsde/cxx/serializer/validating/time-zone.ixx new file mode 100644 index 0000000..c6e80f4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time-zone.ixx @@ -0,0 +1,32 @@ +// file : xsde/cxx/serializer/validating/time-zone.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + namespace bits + { + inline bool + valid_time_zone (const time_zone& z) + { + short h = z.zone_hours (); + short m = z.zone_minutes (); + + unsigned short ah = h < 0 ? -h : h; + unsigned short am = m < 0 ? -m : m; + + return ((h <= 0 && m <= 0) || (h >= 0 && m >= 0)) && + ((ah < 14 && am < 60) || (ah == 14 && am == 0)); + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/time.cxx b/libxsde/xsde/cxx/serializer/validating/time.cxx new file mode 100644 index 0000000..5ab5c22 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time.cxx @@ -0,0 +1,79 @@ +// file : xsde/cxx/serializer/validating/time.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void time_simpl:: + pre (const time& value) + { + value_ = value; + } + + void time_simpl:: + _serialize_content () + { + // We only need strlen("hh:mm:ss.ssssss-hh:mm") + 1 characters to + // hold all representations of time. We know that the seconds + // part (represented as double) has default precision of 6. + // + char str[22]; + + unsigned short h = value_.hours (); + unsigned short m = value_.minutes (); + double s = value_.seconds (); + + if (((h < 24 && m < 60 && s >= 0.0 && s < 60.0) || + (h == 24 && m == 0 && s == 0.0)) && + (!value_.zone_present () || bits::valid_time_zone (value_))) + { +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 16, "%.2u:%.2u:%09f", h, m, s); +#else + int n = sprintf (str, "%.2u:%.2u:%09f", h, m, s); +#endif + if (n > 0 && n < 16) + { + // Remove trailing '0' and '.' if necessary. + // + while (str[n - 1] == '0') + n--; + + if (str[n - 1] == '.') + n--; + + if (value_.zone_present ()) + { + if (int z = bits::serialize_time_zone (str + n, value_)) + n += z; + else + { + _schema_error (schema_error::invalid_time_value); + return; + } + } + + _characters (str, static_cast (n)); + } + else + _schema_error (schema_error::invalid_time_value); + } + else + _schema_error (schema_error::invalid_time_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/time.hxx b/libxsde/xsde/cxx/serializer/validating/time.hxx new file mode 100644 index 0000000..1eedc7a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time.hxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/serializer/validating/time.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_TIME_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_TIME_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct time_simpl: virtual time_sskel +#else + struct time_simpl: time_sskel +#endif + { + time_simpl (); + + virtual void + pre (const time&); + + virtual void + _serialize_content (); + + protected: + time value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_TIME_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/time.ixx b/libxsde/xsde/cxx/serializer/validating/time.ixx new file mode 100644 index 0000000..5262419 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/time.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/time.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline time_simpl:: + time_simpl () + : value_ (0, 0, 0.0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/token-stl.cxx b/libxsde/xsde/cxx/serializer/validating/token-stl.cxx new file mode 100644 index 0000000..0de2a54 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/token-stl.cxx @@ -0,0 +1,58 @@ +// file : xsde/cxx/serializer/validating/token-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void token_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void token_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + bool ok = true; + const char* s = tmp.c_str (); + + // No leading whitespaces. + // + if (*s == 0x20) + ok = false; + + for (; ok && *s != '\0'; ++s) + { + if (*s == 0x0A || *s == 0x0D || *s == 0x09 || + (*s == 0x20 && *(s + 1) == 0x20)) + ok = false; + } + + // No trailing whitespaces. + // + if (ok && s != tmp.c_str () && *(s - 1) == 0x20) + ok = false; + + if (ok) + _characters (tmp.c_str (), tmp.size ()); + else + _schema_error (schema_error::invalid_token_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/token-stl.hxx b/libxsde/xsde/cxx/serializer/validating/token-stl.hxx new file mode 100644 index 0000000..6de5f1e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/token-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/token-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_simpl: virtual token_sskel +#else + struct token_simpl: token_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/token.cxx b/libxsde/xsde/cxx/serializer/validating/token.cxx new file mode 100644 index 0000000..76bbce4 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/token.cxx @@ -0,0 +1,66 @@ +// file : xsde/cxx/serializer/validating/token.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + token_simpl:: + ~token_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void token_simpl:: + pre (const char* value) + { + value_ = value; + } + + void token_simpl:: + _serialize_content () + { + bool ok = true; + const char* s = value_; + + // No leading whitespaces. + // + if (*s == 0x20) + ok = false; + + for (; ok && *s != '\0'; ++s) + { + if (*s == 0x0A || *s == 0x0D || *s == 0x09 || + (*s == 0x20 && *(s + 1) == 0x20)) + ok = false; + } + + // No trailing whitespaces. + // + if (ok && s != value_ && *(s - 1) == 0x20) + ok = false; + + if (ok) + _characters (value_); + else + _schema_error (schema_error::invalid_token_value); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/token.hxx b/libxsde/xsde/cxx/serializer/validating/token.hxx new file mode 100644 index 0000000..3b3c099 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/token.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/token.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_simpl: virtual token_sskel +#else + struct token_simpl: token_sskel +#endif + { + virtual + ~token_simpl (); + + token_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_TOKEN_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/token.ixx b/libxsde/xsde/cxx/serializer/validating/token.ixx new file mode 100644 index 0000000..30d119c --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/token.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/token.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline token_simpl:: + token_simpl (bool free) + : free_ (free) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-byte.cxx b/libxsde/xsde/cxx/serializer/validating/unsigned-byte.cxx new file mode 100644 index 0000000..97b45f3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-byte.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/unsigned-byte.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void unsigned_byte_simpl:: + pre (unsigned char value) + { + value_ = value; + } + + void unsigned_byte_simpl:: + _serialize_content () + { + // We only need strlen("256") + 1 characters to hold all + // representations of unsigned byte. + // + char str[4]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 4, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 4) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_unsigned_byte_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-byte.hxx b/libxsde/xsde/cxx/serializer/validating/unsigned-byte.hxx new file mode 100644 index 0000000..1afa8db --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-byte.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/unsigned-byte.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_BYTE_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_BYTE_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 8-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_byte_simpl: virtual unsigned_byte_sskel +#else + struct unsigned_byte_simpl: unsigned_byte_sskel +#endif + { + virtual void + pre (unsigned char); + + virtual void + _serialize_content (); + + protected: + unsigned char value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_BYTE_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-int.cxx b/libxsde/xsde/cxx/serializer/validating/unsigned-int.cxx new file mode 100644 index 0000000..14e478f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-int.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/unsigned-int.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void unsigned_int_simpl:: + pre (unsigned int value) + { + value_ = value; + } + + void unsigned_int_simpl:: + _serialize_content () + { + // We only need strlen("4294967295") + 1 characters to hold all + // representations of unsigned int. + // + char str[11]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 11, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 11) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_unsigned_int_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-int.hxx b/libxsde/xsde/cxx/serializer/validating/unsigned-int.hxx new file mode 100644 index 0000000..fb103cd --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-int.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/unsigned-int.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_INT_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_INT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 32-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_int_simpl: virtual unsigned_int_sskel +#else + struct unsigned_int_simpl: unsigned_int_sskel +#endif + { + virtual void + pre (unsigned int); + + virtual void + _serialize_content (); + + protected: + unsigned int value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_INT_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.cxx b/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.cxx new file mode 100644 index 0000000..3520b31 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/unsigned-long-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void unsigned_long_simpl:: + pre (unsigned long long value) + { + value_ = value; + } + + void unsigned_long_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of unsigned long long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%llu", value_); +#else + int n = sprintf (str, "%llu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_unsigned_long_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.hxx b/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.hxx new file mode 100644 index 0000000..8a746e3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-long-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/unsigned-long-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_LONG_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 64-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_simpl: virtual unsigned_long_sskel +#else + struct unsigned_long_simpl: unsigned_long_sskel +#endif + { + virtual void + pre (unsigned long long); + + virtual void + _serialize_content (); + + protected: + unsigned long long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-long.cxx b/libxsde/xsde/cxx/serializer/validating/unsigned-long.cxx new file mode 100644 index 0000000..b34d8aa --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-long.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/unsigned-long.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void unsigned_long_simpl:: + pre (unsigned long value) + { + value_ = value; + } + + void unsigned_long_simpl:: + _serialize_content () + { + // We only need strlen("18446744073709551615") + 1 characters to + // hold all representations of (possibly 64-bit) unsigned long. + // + char str[21]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 21, "%lu", value_); +#else + int n = sprintf (str, "%lu", value_); +#endif + if (n > 0 && n < 21) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_unsigned_long_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-long.hxx b/libxsde/xsde/cxx/serializer/validating/unsigned-long.hxx new file mode 100644 index 0000000..2659ef1 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-long.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/unsigned-long.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // Fall-back implementation when 64 bit long long is not available. + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_long_simpl: virtual unsigned_long_sskel +#else + struct unsigned_long_simpl: unsigned_long_sskel +#endif + { + virtual void + pre (unsigned long); + + virtual void + _serialize_content (); + + protected: + unsigned long value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_LONG_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-short.cxx b/libxsde/xsde/cxx/serializer/validating/unsigned-short.cxx new file mode 100644 index 0000000..d9bb308 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-short.cxx @@ -0,0 +1,45 @@ +// file : xsde/cxx/serializer/validating/unsigned-short.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // sprintf/snprintf + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void unsigned_short_simpl:: + pre (unsigned short value) + { + value_ = value; + } + + void unsigned_short_simpl:: + _serialize_content () + { + // We only need strlen("65535") + 1 characters to hold all + // representations of short. + // + char str[6]; + +#ifdef XSDE_SNPRINTF + int n = snprintf (str, 6, "%u", value_); +#else + int n = sprintf (str, "%u", value_); +#endif + if (n > 0 && n < 6) + _characters (str, static_cast (n)); + else + _schema_error (schema_error::invalid_unsigned_short_value); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/unsigned-short.hxx b/libxsde/xsde/cxx/serializer/validating/unsigned-short.hxx new file mode 100644 index 0000000..902d75e --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/unsigned-short.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/unsigned-short.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_SHORT_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_SHORT_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // 16-bit unsigned integer + // +#ifdef XSDE_REUSE_STYLE_MIXIN + struct unsigned_short_simpl: virtual unsigned_short_sskel +#else + struct unsigned_short_simpl: unsigned_short_sskel +#endif + { + virtual void + pre (unsigned short); + + virtual void + _serialize_content (); + + protected: + unsigned short value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_UNSIGNED_SHORT_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/uri-stl.cxx b/libxsde/xsde/cxx/serializer/validating/uri-stl.cxx new file mode 100644 index 0000000..d22c992 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/uri-stl.cxx @@ -0,0 +1,39 @@ +// file : xsde/cxx/serializer/validating/uri-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + void uri_simpl:: + pre (const std::string& value) + { + value_ = value; + } + + void uri_simpl:: + _serialize_content () + { + // Make sure we don't hold any references to the string. + // + std::string tmp; + tmp.swap (value_); + + // According to Datatypes 3.2.17 and RFC2396 pretty much anything + // can be a URI and conforming processors do not need to figure + // out and verify particular URI schemes. + // + _characters (tmp.c_str (), tmp.size ()); + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/uri-stl.hxx b/libxsde/xsde/cxx/serializer/validating/uri-stl.hxx new file mode 100644 index 0000000..4de5922 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/uri-stl.hxx @@ -0,0 +1,41 @@ +// file : xsde/cxx/serializer/validating/uri-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_URI_STL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_URI_STL_HXX + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_simpl: virtual uri_sskel +#else + struct uri_simpl: uri_sskel +#endif + { + virtual void + pre (const std::string&); + + virtual void + _serialize_content (); + + protected: + std::string value_; + }; + } + } + } +} + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_URI_STL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/uri.cxx b/libxsde/xsde/cxx/serializer/validating/uri.cxx new file mode 100644 index 0000000..46148d3 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/uri.cxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/uri.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + uri_simpl:: + ~uri_simpl () + { + if (free_) + delete[] const_cast (value_); + } + + void uri_simpl:: + pre (const char* value) + { + value_ = value; + } + + void uri_simpl:: + _serialize_content () + { + // According to Datatypes 3.2.17 and RFC2396 pretty much anything + // can be a URI and conforming processors do not need to figure + // out and verify particular URI schemes. + // + _characters (value_); + + if (free_) + { + delete[] const_cast (value_); + value_ = 0; + } + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/uri.hxx b/libxsde/xsde/cxx/serializer/validating/uri.hxx new file mode 100644 index 0000000..63b502a --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/uri.hxx @@ -0,0 +1,47 @@ +// file : xsde/cxx/serializer/validating/uri.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_URI_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_URI_HXX + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { +#ifdef XSDE_REUSE_STYLE_MIXIN + struct uri_simpl: virtual uri_sskel +#else + struct uri_simpl: uri_sskel +#endif + { + virtual + ~uri_simpl (); + + uri_simpl (bool free = false); + + virtual void + pre (const char*); + + virtual void + _serialize_content (); + + protected: + bool free_; + const char* value_; + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_URI_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/uri.ixx b/libxsde/xsde/cxx/serializer/validating/uri.ixx new file mode 100644 index 0000000..6cbf6ae --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/uri.ixx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/validating/uri.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + inline uri_simpl:: + uri_simpl (bool free) + : free_ (free), value_ (0) + { + } + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/xml-schema-simpl.hxx b/libxsde/xsde/cxx/serializer/validating/xml-schema-simpl.hxx new file mode 100644 index 0000000..039722f --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/xml-schema-simpl.hxx @@ -0,0 +1,82 @@ +// file : xsde/cxx/serializer/validating/xml-schema-simpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SIMPL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SIMPL_HXX + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_LONGLONG +# include +# include +#else +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XSDE_STL +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SIMPL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.cxx b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.cxx new file mode 100644 index 0000000..a18141b --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.cxx @@ -0,0 +1,560 @@ +// file : xsde/cxx/serializer/validating/xml-schema-sskel.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // any_type_sskel + // + void any_type_sskel:: + pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_type_impl_) + any_type_impl_->pre (); +#endif + } + + // any_simple_type_sskel + // + void any_simple_type_sskel:: + pre () + { +#ifdef XSDE_REUSE_STYLE_TIEIN + if (any_simple_type_impl_) + any_simple_type_impl_->pre (); +#endif + } + + // static/dynamic_type function implementations. + // +#ifdef XSDE_POLYMORPHIC + const char* any_type_sskel:: + _static_type () + { + return "anyType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_type_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* any_simple_type_sskel:: + _static_type () + { + return "anySimpleType http://www.w3.org/2001/XMLSchema"; + } + + const char* any_simple_type_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* boolean_sskel:: + _static_type () + { + return "boolean http://www.w3.org/2001/XMLSchema"; + } + + const char* boolean_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* byte_sskel:: + _static_type () + { + return "byte http://www.w3.org/2001/XMLSchema"; + } + + const char* byte_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_byte_sskel:: + _static_type () + { + return "unsignedByte http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_byte_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* short_sskel:: + _static_type () + { + return "short http://www.w3.org/2001/XMLSchema"; + } + + const char* short_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_short_sskel:: + _static_type () + { + return "unsignedShort http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_short_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* int_sskel:: + _static_type () + { + return "int http://www.w3.org/2001/XMLSchema"; + } + + const char* int_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_int_sskel:: + _static_type () + { + return "unsignedInt http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_int_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* long_sskel:: + _static_type () + { + return "long http://www.w3.org/2001/XMLSchema"; + } + + const char* long_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* unsigned_long_sskel:: + _static_type () + { + return "unsignedLong http://www.w3.org/2001/XMLSchema"; + } + + const char* unsigned_long_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* integer_sskel:: + _static_type () + { + return "integer http://www.w3.org/2001/XMLSchema"; + } + + const char* integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* negative_integer_sskel:: + _static_type () + { + return "negativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* negative_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_positive_integer_sskel:: + _static_type () + { + return "nonPositiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_positive_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* positive_integer_sskel:: + _static_type () + { + return "positiveInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* positive_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* non_negative_integer_sskel:: + _static_type () + { + return "nonNegativeInteger http://www.w3.org/2001/XMLSchema"; + } + + const char* non_negative_integer_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* float_sskel:: + _static_type () + { + return "float http://www.w3.org/2001/XMLSchema"; + } + + const char* float_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* double_sskel:: + _static_type () + { + return "double http://www.w3.org/2001/XMLSchema"; + } + + const char* double_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* decimal_sskel:: + _static_type () + { + return "decimal http://www.w3.org/2001/XMLSchema"; + } + + const char* decimal_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* string_sskel:: + _static_type () + { + return "string http://www.w3.org/2001/XMLSchema"; + } + + const char* string_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* normalized_string_sskel:: + _static_type () + { + return "normalizedString http://www.w3.org/2001/XMLSchema"; + } + + const char* normalized_string_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* token_sskel:: + _static_type () + { + return "token http://www.w3.org/2001/XMLSchema"; + } + + const char* token_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* name_sskel:: + _static_type () + { + return "Name http://www.w3.org/2001/XMLSchema"; + } + + const char* name_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtoken_sskel:: + _static_type () + { + return "NMTOKEN http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtoken_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* nmtokens_sskel:: + _static_type () + { + return "NMTOKENS http://www.w3.org/2001/XMLSchema"; + } + + const char* nmtokens_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* ncname_sskel:: + _static_type () + { + return "NCName http://www.w3.org/2001/XMLSchema"; + } + + const char* ncname_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* id_sskel:: + _static_type () + { + return "ID http://www.w3.org/2001/XMLSchema"; + } + + const char* id_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idref_sskel:: + _static_type () + { + return "IDREF http://www.w3.org/2001/XMLSchema"; + } + + const char* idref_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* idrefs_sskel:: + _static_type () + { + return "IDREFS http://www.w3.org/2001/XMLSchema"; + } + + const char* idrefs_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* language_sskel:: + _static_type () + { + return "language http://www.w3.org/2001/XMLSchema"; + } + + const char* language_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* uri_sskel:: + _static_type () + { + return "anyURI http://www.w3.org/2001/XMLSchema"; + } + + const char* uri_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* qname_sskel:: + _static_type () + { + return "QName http://www.w3.org/2001/XMLSchema"; + } + + const char* qname_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* base64_binary_sskel:: + _static_type () + { + return "base64Binary http://www.w3.org/2001/XMLSchema"; + } + + const char* base64_binary_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* hex_binary_sskel:: + _static_type () + { + return "hexBinary http://www.w3.org/2001/XMLSchema"; + } + + const char* hex_binary_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gday_sskel:: + _static_type () + { + return "gDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gday_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_sskel:: + _static_type () + { + return "gMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_sskel:: + _static_type () + { + return "gYear http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gmonth_day_sskel:: + _static_type () + { + return "gMonthDay http://www.w3.org/2001/XMLSchema"; + } + + const char* gmonth_day_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* gyear_month_sskel:: + _static_type () + { + return "gYearMonth http://www.w3.org/2001/XMLSchema"; + } + + const char* gyear_month_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_sskel:: + _static_type () + { + return "date http://www.w3.org/2001/XMLSchema"; + } + + const char* date_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* time_sskel:: + _static_type () + { + return "time http://www.w3.org/2001/XMLSchema"; + } + + const char* time_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* date_time_sskel:: + _static_type () + { + return "dateTime http://www.w3.org/2001/XMLSchema"; + } + + const char* date_time_sskel:: + _dynamic_type () const + { + return _static_type (); + } + + const char* duration_sskel:: + _static_type () + { + return "duration http://www.w3.org/2001/XMLSchema"; + } + + const char* duration_sskel:: + _dynamic_type () const + { + return _static_type (); + } +#endif // XSDE_POLYMORPHIC + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.hxx b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.hxx new file mode 100644 index 0000000..9a158b0 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.hxx @@ -0,0 +1,1382 @@ +// file : xsde/cxx/serializer/validating/xml-schema-sskel.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SSKEL_HXX +#define XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SSKEL_HXX + +#include + +#ifdef XSDE_STL +# include +#endif + +#include + +#include + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // anyType and anySimpleType. + // + struct any_type_sskel: complex_content + { + virtual void + pre (); + + // Override the following two functions to implement + // your logic. + // + + // virtual void + // _serialize_attributes (); + + // virtual void + // _serialize_content (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_type_sskel (); + any_type_sskel (any_type_sskel* impl, void*); + + protected: + any_type_sskel* any_type_impl_; +#endif + }; + + struct any_simple_type_sskel: simple_content + { + virtual void + pre (); + + // Override the following function to implement your + // logic. + // + + // virtual void + // _serialize_content (); + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + any_simple_type_sskel (); + any_simple_type_sskel (any_simple_type_sskel* impl, void*); + + protected: + any_simple_type_sskel* any_simple_type_impl_; +#endif + }; + + // Boolean. + // + struct boolean_sskel: simple_content + { + virtual void + pre (bool) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + boolean_sskel (); + boolean_sskel (boolean_sskel* impl, void*); + + protected: + boolean_sskel* boolean_impl_; +#endif + }; + + // 8-bit + // + + struct byte_sskel: simple_content + { + virtual void + pre (signed char) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + byte_sskel (); + byte_sskel (byte_sskel* impl, void*); + + protected: + byte_sskel* byte_impl_; +#endif + }; + + struct unsigned_byte_sskel: simple_content + { + virtual void + pre (unsigned char) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_byte_sskel (); + unsigned_byte_sskel (unsigned_byte_sskel* impl, void*); + + protected: + unsigned_byte_sskel* unsigned_byte_impl_; +#endif + }; + + + // 16-bit + // + + struct short_sskel: simple_content + { + virtual void + pre (short) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + short_sskel (); + short_sskel (short_sskel* impl, void*); + + protected: + short_sskel* short_impl_; +#endif + }; + + struct unsigned_short_sskel: simple_content + { + virtual void + pre (unsigned short) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_short_sskel (); + unsigned_short_sskel (unsigned_short_sskel* impl, void*); + + protected: + unsigned_short_sskel* unsigned_short_impl_; +#endif + }; + + // 32-bit + // + + struct int_sskel: simple_content + { + virtual void + pre (int) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + int_sskel (); + int_sskel (int_sskel* impl, void*); + + protected: + int_sskel* int_impl_; +#endif + }; + + struct unsigned_int_sskel: simple_content + { + virtual void + pre (unsigned int) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_int_sskel (); + unsigned_int_sskel (unsigned_int_sskel* impl, void*); + + protected: + unsigned_int_sskel* unsigned_int_impl_; +#endif + }; + + // 64-bit + // + +#ifdef XSDE_LONGLONG + struct long_sskel: simple_content + { + virtual void + pre (long long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_sskel (); + long_sskel (long_sskel* impl, void*); + + protected: + long_sskel* long_impl_; +#endif + }; + + struct unsigned_long_sskel: simple_content + { + virtual void + pre (unsigned long long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_sskel (); + unsigned_long_sskel (unsigned_long_sskel* impl, void*); + + protected: + unsigned_long_sskel* unsigned_long_impl_; +#endif + }; +#else + struct long_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + long_sskel (); + long_sskel (long_sskel* impl, void*); + + protected: + long_sskel* long_impl_; +#endif + }; + + struct unsigned_long_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + unsigned_long_sskel (); + unsigned_long_sskel (unsigned_long_sskel* impl, void*); + + protected: + unsigned_long_sskel* unsigned_long_impl_; +#endif + }; +#endif + + // Arbitrary-length integers. + // + + struct integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + integer_sskel (); + integer_sskel (integer_sskel* impl, void*); + + protected: + integer_sskel* integer_impl_; +#endif + }; + + struct negative_integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + negative_integer_sskel (); + negative_integer_sskel (negative_integer_sskel* impl, void*); + + protected: + negative_integer_sskel* negative_integer_impl_; +#endif + }; + + struct non_positive_integer_sskel: simple_content + { + virtual void + pre (long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_positive_integer_sskel (); + non_positive_integer_sskel (non_positive_integer_sskel* impl, void*); + + protected: + non_positive_integer_sskel* non_positive_integer_impl_; +#endif + }; + + struct positive_integer_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + positive_integer_sskel (); + positive_integer_sskel (positive_integer_sskel* impl, void*); + + protected: + positive_integer_sskel* positive_integer_impl_; +#endif + }; + + struct non_negative_integer_sskel: simple_content + { + virtual void + pre (unsigned long) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + non_negative_integer_sskel (); + non_negative_integer_sskel (non_negative_integer_sskel* impl, void*); + + protected: + non_negative_integer_sskel* non_negative_integer_impl_; +#endif + }; + + // Floats. + // + + struct float_sskel: simple_content + { + virtual void + pre (float) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + float_sskel (); + float_sskel (float_sskel* impl, void*); + + protected: + float_sskel* float_impl_; +#endif + }; + + struct double_sskel: simple_content + { + virtual void + pre (double) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + double_sskel (); + double_sskel (double_sskel* impl, void*); + + protected: + double_sskel* double_impl_; +#endif + }; + + struct decimal_sskel: simple_content + { + virtual void + pre (double) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + decimal_sskel (); + decimal_sskel (decimal_sskel* impl, void*); + + protected: + decimal_sskel* decimal_impl_; +#endif + }; + + // String-based types. + // +#ifdef XSDE_STL + + struct string_sskel: simple_content + { + virtual void + pre (const std::string&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_sskel (); + string_sskel (string_sskel* impl, void*); + + protected: + string_sskel* string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_sskel: virtual string_sskel +#else + struct normalized_string_sskel: string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_sskel (); + normalized_string_sskel (normalized_string_sskel* impl, void*); + + protected: + normalized_string_sskel* normalized_string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_sskel: virtual normalized_string_sskel +#else + struct token_sskel: normalized_string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_sskel (); + token_sskel (token_sskel* impl, void*); + + protected: + token_sskel* token_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_sskel: virtual token_sskel +#else + struct name_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_sskel (); + name_sskel (name_sskel* impl, void*); + + protected: + name_sskel* name_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_sskel: virtual token_sskel +#else + struct nmtoken_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_sskel (); + nmtoken_sskel (nmtoken_sskel* impl, void*); + + protected: + nmtoken_sskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_sskel (); + nmtokens_sskel (nmtokens_sskel* impl, void*); + + protected: + nmtokens_sskel* nmtokens_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_sskel: virtual name_sskel +#else + struct ncname_sskel: name_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_sskel (); + ncname_sskel (ncname_sskel* impl, void*); + + protected: + ncname_sskel* ncname_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_sskel: virtual ncname_sskel +#else + struct id_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_sskel (); + id_sskel (id_sskel* impl, void*); + + protected: + id_sskel* id_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_sskel: virtual ncname_sskel +#else + struct idref_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_sskel (); + idref_sskel (idref_sskel* impl, void*); + + protected: + idref_sskel* idref_impl_; +#endif + }; + + struct idrefs_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_sskel (); + idrefs_sskel (idrefs_sskel* impl, void*); + + protected: + idrefs_sskel* idrefs_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_sskel: virtual token_sskel +#else + struct language_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_sskel (); + language_sskel (language_sskel* impl, void*); + + protected: + language_sskel* language_impl_; +#endif + }; + + struct uri_sskel: simple_content + { + virtual void + pre (const std::string&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_sskel (); + uri_sskel (uri_sskel* impl, void*); + + protected: + uri_sskel* uri_impl_; +#endif + }; + + struct qname_sskel: simple_content + { + virtual void + pre (const qname&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_sskel (); + qname_sskel (qname_sskel* impl, void*); + + protected: + qname_sskel* qname_impl_; +#endif + }; + +#else // XSDE_STL + + struct string_sskel: simple_content + { + virtual void + pre (const char*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + string_sskel (); + string_sskel (string_sskel* impl, void*); + + protected: + string_sskel* string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct normalized_string_sskel: virtual string_sskel +#else + struct normalized_string_sskel: string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + normalized_string_sskel (); + normalized_string_sskel (normalized_string_sskel* impl, void*); + + protected: + normalized_string_sskel* normalized_string_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct token_sskel: virtual normalized_string_sskel +#else + struct token_sskel: normalized_string_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + token_sskel (); + token_sskel (token_sskel* impl, void*); + + protected: + token_sskel* token_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct name_sskel: virtual token_sskel +#else + struct name_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + name_sskel (); + name_sskel (name_sskel* impl, void*); + + protected: + name_sskel* name_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct nmtoken_sskel: virtual token_sskel +#else + struct nmtoken_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtoken_sskel (); + nmtoken_sskel (nmtoken_sskel* impl, void*); + + protected: + nmtoken_sskel* nmtoken_impl_; +#endif + }; + + struct nmtokens_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + nmtokens_sskel (); + nmtokens_sskel (nmtokens_sskel* impl, void*); + + protected: + nmtokens_sskel* nmtokens_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct ncname_sskel: virtual name_sskel +#else + struct ncname_sskel: name_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + ncname_sskel (); + ncname_sskel (ncname_sskel* impl, void*); + + protected: + ncname_sskel* ncname_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct id_sskel: virtual ncname_sskel +#else + struct id_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + id_sskel (); + id_sskel (id_sskel* impl, void*); + + protected: + id_sskel* id_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct idref_sskel: virtual ncname_sskel +#else + struct idref_sskel: ncname_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idref_sskel (); + idref_sskel (idref_sskel* impl, void*); + + protected: + idref_sskel* idref_impl_; +#endif + }; + + struct idrefs_sskel: simple_content + { + virtual void + pre (const string_sequence*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + idrefs_sskel (); + idrefs_sskel (idrefs_sskel* impl, void*); + + protected: + idrefs_sskel* idrefs_impl_; +#endif + }; + +#ifdef XSDE_REUSE_STYLE_MIXIN + struct language_sskel: virtual token_sskel +#else + struct language_sskel: token_sskel +#endif + { +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + language_sskel (); + language_sskel (language_sskel* impl, void*); + + protected: + language_sskel* language_impl_; +#endif + }; + + struct uri_sskel: simple_content + { + virtual void + pre (const char*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + uri_sskel (); + uri_sskel (uri_sskel* impl, void*); + + protected: + uri_sskel* uri_impl_; +#endif + }; + + struct qname_sskel: simple_content + { + virtual void + pre (const qname*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + qname_sskel (); + qname_sskel (qname_sskel* impl, void*); + + protected: + qname_sskel* qname_impl_; +#endif + }; + +#endif // XSDE_STL + + + // base64Binary + // + struct base64_binary_sskel: simple_content + { + virtual void + pre (const buffer*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + base64_binary_sskel (); + base64_binary_sskel (base64_binary_sskel* impl, void*); + + protected: + base64_binary_sskel* base64_binary_impl_; +#endif + }; + + // hexBinary + // + struct hex_binary_sskel: simple_content + { + virtual void + pre (const buffer*) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + hex_binary_sskel (); + hex_binary_sskel (hex_binary_sskel* impl, void*); + + protected: + hex_binary_sskel* hex_binary_impl_; +#endif + }; + + // Time and date types. + // + struct gday_sskel: simple_content + { + virtual void + pre (const gday&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gday_sskel (); + gday_sskel (gday_sskel* impl, void*); + + protected: + gday_sskel* gday_impl_; +#endif + }; + + struct gmonth_sskel: simple_content + { + virtual void + pre (const gmonth&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_sskel (); + gmonth_sskel (gmonth_sskel* impl, void*); + + protected: + gmonth_sskel* gmonth_impl_; +#endif + }; + + struct gyear_sskel: simple_content + { + virtual void + pre (const gyear&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_sskel (); + gyear_sskel (gyear_sskel* impl, void*); + + protected: + gyear_sskel* gyear_impl_; +#endif + }; + + struct gmonth_day_sskel: simple_content + { + virtual void + pre (const gmonth_day&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gmonth_day_sskel (); + gmonth_day_sskel (gmonth_day_sskel* impl, void*); + + protected: + gmonth_day_sskel* gmonth_day_impl_; +#endif + }; + + struct gyear_month_sskel: simple_content + { + virtual void + pre (const gyear_month&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + gyear_month_sskel (); + gyear_month_sskel (gyear_month_sskel* impl, void*); + + protected: + gyear_month_sskel* gyear_month_impl_; +#endif + }; + + struct date_sskel: simple_content + { + virtual void + pre (const date&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_sskel (); + date_sskel (date_sskel* impl, void*); + + protected: + date_sskel* date_impl_; +#endif + }; + + struct time_sskel: simple_content + { + virtual void + pre (const time&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + time_sskel (); + time_sskel (time_sskel* impl, void*); + + protected: + time_sskel* time_impl_; +#endif + }; + + struct date_time_sskel: simple_content + { + virtual void + pre (const date_time&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + date_time_sskel (); + date_time_sskel (date_time_sskel* impl, void*); + + protected: + date_time_sskel* date_time_impl_; +#endif + }; + + struct duration_sskel: simple_content + { + virtual void + pre (const duration&) = 0; + +#ifdef XSDE_POLYMORPHIC + static const char* + _static_type (); + + virtual const char* + _dynamic_type () const; +#endif + +#ifdef XSDE_REUSE_STYLE_TIEIN + duration_sskel (); + duration_sskel (duration_sskel* impl, void*); + + protected: + duration_sskel* duration_impl_; +#endif + }; + } + } + } +} + +#include + +#endif // XSDE_CXX_SERIALIZER_VALIDATING_XML_SCHEMA_SSKEL_HXX diff --git a/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.ixx b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.ixx new file mode 100644 index 0000000..23647b5 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.ixx @@ -0,0 +1,704 @@ +// file : xsde/cxx/serializer/validating/xml-schema-sskel.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + namespace serializer + { + namespace validating + { + // any_type_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_type_sskel:: + any_type_sskel () + : any_type_impl_ (0) + { + } + + inline any_type_sskel:: + any_type_sskel (any_type_sskel* impl, void*) + : complex_content (impl, 0), any_type_impl_ (impl) + { + } +#endif + + // any_simple_type_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline any_simple_type_sskel:: + any_simple_type_sskel () + : any_simple_type_impl_ (0) + { + } + + inline any_simple_type_sskel:: + any_simple_type_sskel (any_simple_type_sskel* impl, void*) + : simple_content (impl, 0), any_simple_type_impl_ (impl) + { + } +#endif + + // boolean_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline boolean_sskel:: + boolean_sskel () + : boolean_impl_ (0) + { + } + + inline boolean_sskel:: + boolean_sskel (boolean_sskel* impl, void*) + : simple_content (impl, 0), boolean_impl_ (impl) + { + } +#endif + + // byte_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline byte_sskel:: + byte_sskel () + : byte_impl_ (0) + { + } + + inline byte_sskel:: + byte_sskel (byte_sskel* impl, void*) + : simple_content (impl, 0), byte_impl_ (impl) + { + } +#endif + + // unsigned_byte_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_byte_sskel:: + unsigned_byte_sskel () + : unsigned_byte_impl_ (0) + { + } + + inline unsigned_byte_sskel:: + unsigned_byte_sskel (unsigned_byte_sskel* impl, void*) + : simple_content (impl, 0), unsigned_byte_impl_ (impl) + { + } +#endif + + // short_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline short_sskel:: + short_sskel () + : short_impl_ (0) + { + } + + inline short_sskel:: + short_sskel (short_sskel* impl, void*) + : simple_content (impl, 0), short_impl_ (impl) + { + } +#endif + + // unsigned_short_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_short_sskel:: + unsigned_short_sskel () + : unsigned_short_impl_ (0) + { + } + + inline unsigned_short_sskel:: + unsigned_short_sskel (unsigned_short_sskel* impl, void*) + : simple_content (impl, 0), unsigned_short_impl_ (impl) + { + } +#endif + + // int_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline int_sskel:: + int_sskel () + : int_impl_ (0) + { + } + + inline int_sskel:: + int_sskel (int_sskel* impl, void*) + : simple_content (impl, 0), int_impl_ (impl) + { + } +#endif + + // unsigned_int_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_int_sskel:: + unsigned_int_sskel () + : unsigned_int_impl_ (0) + { + } + + inline unsigned_int_sskel:: + unsigned_int_sskel (unsigned_int_sskel* impl, void*) + : simple_content (impl, 0), unsigned_int_impl_ (impl) + { + } +#endif + + // long_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline long_sskel:: + long_sskel () + : long_impl_ (0) + { + } + + inline long_sskel:: + long_sskel (long_sskel* impl, void*) + : simple_content (impl, 0), long_impl_ (impl) + { + } +#endif + + // unsigned_long_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline unsigned_long_sskel:: + unsigned_long_sskel () + : unsigned_long_impl_ (0) + { + } + + inline unsigned_long_sskel:: + unsigned_long_sskel (unsigned_long_sskel* impl, void*) + : simple_content (impl, 0), unsigned_long_impl_ (impl) + { + } +#endif + + // integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline integer_sskel:: + integer_sskel () + : integer_impl_ (0) + { + } + + inline integer_sskel:: + integer_sskel (integer_sskel* impl, void*) + : simple_content (impl, 0), integer_impl_ (impl) + { + } +#endif + + // negative_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline negative_integer_sskel:: + negative_integer_sskel () + : negative_integer_impl_ (0) + { + } + + inline negative_integer_sskel:: + negative_integer_sskel (negative_integer_sskel* impl, void*) + : simple_content (impl, 0), negative_integer_impl_ (impl) + { + } +#endif + + // non_positive_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_positive_integer_sskel:: + non_positive_integer_sskel () + : non_positive_integer_impl_ (0) + { + } + + inline non_positive_integer_sskel:: + non_positive_integer_sskel (non_positive_integer_sskel* impl, void*) + : simple_content (impl, 0), non_positive_integer_impl_ (impl) + { + } +#endif + + // positive_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline positive_integer_sskel:: + positive_integer_sskel () + : positive_integer_impl_ (0) + { + } + + inline positive_integer_sskel:: + positive_integer_sskel (positive_integer_sskel* impl, void*) + : simple_content (impl, 0), positive_integer_impl_ (impl) + { + } +#endif + + // non_negative_integer_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline non_negative_integer_sskel:: + non_negative_integer_sskel () + : non_negative_integer_impl_ (0) + { + } + + inline non_negative_integer_sskel:: + non_negative_integer_sskel (non_negative_integer_sskel* impl, void*) + : simple_content (impl, 0), non_negative_integer_impl_ (impl) + { + } +#endif + + // float_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline float_sskel:: + float_sskel () + : float_impl_ (0) + { + } + + inline float_sskel:: + float_sskel (float_sskel* impl, void*) + : simple_content (impl, 0), float_impl_ (impl) + { + } +#endif + + // double_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline double_sskel:: + double_sskel () + : double_impl_ (0) + { + } + + inline double_sskel:: + double_sskel (double_sskel* impl, void*) + : simple_content (impl, 0), double_impl_ (impl) + { + } +#endif + + // decimal_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline decimal_sskel:: + decimal_sskel () + : decimal_impl_ (0) + { + } + + inline decimal_sskel:: + decimal_sskel (decimal_sskel* impl, void*) + : simple_content (impl, 0), decimal_impl_ (impl) + { + } +#endif + + // string_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline string_sskel:: + string_sskel () + : string_impl_ (0) + { + } + + inline string_sskel:: + string_sskel (string_sskel* impl, void*) + : simple_content (impl, 0), string_impl_ (impl) + { + } +#endif + + // normalized_string_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline normalized_string_sskel:: + normalized_string_sskel () + : normalized_string_impl_ (0) + { + } + + inline normalized_string_sskel:: + normalized_string_sskel (normalized_string_sskel* impl, void*) + : string_sskel (impl, 0), normalized_string_impl_ (impl) + { + } +#endif + + // token_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline token_sskel:: + token_sskel () + : token_impl_ (0) + { + } + + inline token_sskel:: + token_sskel (token_sskel* impl, void*) + : normalized_string_sskel (impl, 0), token_impl_ (impl) + { + } +#endif + + // name_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline name_sskel:: + name_sskel () + : name_impl_ (0) + { + } + + inline name_sskel:: + name_sskel (name_sskel* impl, void*) + : token_sskel (impl, 0), name_impl_ (impl) + { + } +#endif + + // nmtoken_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtoken_sskel:: + nmtoken_sskel () + : nmtoken_impl_ (0) + { + } + + inline nmtoken_sskel:: + nmtoken_sskel (nmtoken_sskel* impl, void*) + : token_sskel (impl, 0), nmtoken_impl_ (impl) + { + } +#endif + + // nmtokens_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline nmtokens_sskel:: + nmtokens_sskel () + : nmtokens_impl_ (0) + { + } + + inline nmtokens_sskel:: + nmtokens_sskel (nmtokens_sskel* impl, void*) + : simple_content (impl, 0), nmtokens_impl_ (impl) + { + } +#endif + + // ncname_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline ncname_sskel:: + ncname_sskel () + : ncname_impl_ (0) + { + } + + inline ncname_sskel:: + ncname_sskel (ncname_sskel* impl, void*) + : name_sskel (impl, 0), ncname_impl_ (impl) + { + } +#endif + + // id_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline id_sskel:: + id_sskel () + : id_impl_ (0) + { + } + + inline id_sskel:: + id_sskel (id_sskel* impl, void*) + : ncname_sskel (impl, 0), id_impl_ (impl) + { + } +#endif + + // idref_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idref_sskel:: + idref_sskel () + : idref_impl_ (0) + { + } + + inline idref_sskel:: + idref_sskel (idref_sskel* impl, void*) + : ncname_sskel (impl, 0), idref_impl_ (impl) + { + } +#endif + + // idrefs_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline idrefs_sskel:: + idrefs_sskel () + : idrefs_impl_ (0) + { + } + + inline idrefs_sskel:: + idrefs_sskel (idrefs_sskel* impl, void*) + : simple_content (impl, 0), idrefs_impl_ (impl) + { + } +#endif + + // language_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline language_sskel:: + language_sskel () + : language_impl_ (0) + { + } + + inline language_sskel:: + language_sskel (language_sskel* impl, void*) + : token_sskel (impl, 0), language_impl_ (impl) + { + } +#endif + + // uri_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline uri_sskel:: + uri_sskel () + : uri_impl_ (0) + { + } + + inline uri_sskel:: + uri_sskel (uri_sskel* impl, void*) + : simple_content (impl, 0), uri_impl_ (impl) + { + } +#endif + + // qname_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline qname_sskel:: + qname_sskel () + : qname_impl_ (0) + { + } + + inline qname_sskel:: + qname_sskel (qname_sskel* impl, void*) + : simple_content (impl, 0), qname_impl_ (impl) + { + } +#endif + + // base64_binary_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline base64_binary_sskel:: + base64_binary_sskel () + : base64_binary_impl_ (0) + { + } + + inline base64_binary_sskel:: + base64_binary_sskel (base64_binary_sskel* impl, void*) + : simple_content (impl, 0), base64_binary_impl_ (impl) + { + } +#endif + + // hex_binary_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline hex_binary_sskel:: + hex_binary_sskel () + : hex_binary_impl_ (0) + { + } + + inline hex_binary_sskel:: + hex_binary_sskel (hex_binary_sskel* impl, void*) + : simple_content (impl, 0), hex_binary_impl_ (impl) + { + } +#endif + + // gday_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gday_sskel:: + gday_sskel () + : gday_impl_ (0) + { + } + + inline gday_sskel:: + gday_sskel (gday_sskel* impl, void*) + : simple_content (impl, 0), gday_impl_ (impl) + { + } +#endif + + // gmonth_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_sskel:: + gmonth_sskel () + : gmonth_impl_ (0) + { + } + + inline gmonth_sskel:: + gmonth_sskel (gmonth_sskel* impl, void*) + : simple_content (impl, 0), gmonth_impl_ (impl) + { + } +#endif + + // gyear_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_sskel:: + gyear_sskel () + : gyear_impl_ (0) + { + } + + inline gyear_sskel:: + gyear_sskel (gyear_sskel* impl, void*) + : simple_content (impl, 0), gyear_impl_ (impl) + { + } +#endif + + // gmonth_day_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gmonth_day_sskel:: + gmonth_day_sskel () + : gmonth_day_impl_ (0) + { + } + + inline gmonth_day_sskel:: + gmonth_day_sskel (gmonth_day_sskel* impl, void*) + : simple_content (impl, 0), gmonth_day_impl_ (impl) + { + } +#endif + + // gyear_month_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline gyear_month_sskel:: + gyear_month_sskel () + : gyear_month_impl_ (0) + { + } + + inline gyear_month_sskel:: + gyear_month_sskel (gyear_month_sskel* impl, void*) + : simple_content (impl, 0), gyear_month_impl_ (impl) + { + } +#endif + + // date_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_sskel:: + date_sskel () + : date_impl_ (0) + { + } + + inline date_sskel:: + date_sskel (date_sskel* impl, void*) + : simple_content (impl, 0), date_impl_ (impl) + { + } +#endif + + // time_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline time_sskel:: + time_sskel () + : time_impl_ (0) + { + } + + inline time_sskel:: + time_sskel (time_sskel* impl, void*) + : simple_content (impl, 0), time_impl_ (impl) + { + } +#endif + + // date_time_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline date_time_sskel:: + date_time_sskel () + : date_time_impl_ (0) + { + } + + inline date_time_sskel:: + date_time_sskel (date_time_sskel* impl, void*) + : simple_content (impl, 0), date_time_impl_ (impl) + { + } +#endif + + // duration_sskel + // +#ifdef XSDE_REUSE_STYLE_TIEIN + inline duration_sskel:: + duration_sskel () + : duration_impl_ (0) + { + } + + inline duration_sskel:: + duration_sskel (duration_sskel* impl, void*) + : simple_content (impl, 0), duration_impl_ (impl) + { + } +#endif + } + } + } +} diff --git a/libxsde/xsde/cxx/serializer/xml-schema.hxx b/libxsde/xsde/cxx/serializer/xml-schema.hxx new file mode 100644 index 0000000..5897914 --- /dev/null +++ b/libxsde/xsde/cxx/serializer/xml-schema.hxx @@ -0,0 +1,20 @@ +// file : xsde/cxx/serializer/xml-schema.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SERIALIZER_XML_SCHEMA_HXX +#define XSDE_CXX_SERIALIZER_XML_SCHEMA_HXX + +#include +#include + +#ifdef XSDE_STL +# include +# include +#else +# include +# include +#endif + +#endif // XSDE_CXX_SERIALIZER_XML_SCHEMA_HXX diff --git a/libxsde/xsde/cxx/strdupx.cxx b/libxsde/xsde/cxx/strdupx.cxx new file mode 100644 index 0000000..254df2a --- /dev/null +++ b/libxsde/xsde/cxx/strdupx.cxx @@ -0,0 +1,48 @@ +// file : xsde/cxx/strdupx.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // strlen, memcpy + +#include +#include + +namespace xsde +{ + namespace cxx + { + char* + strdupx (const char* s) + { + size_t n = strlen (s); + char* r = new char[n + 1]; + +#ifndef XSDE_EXCEPTIONS + if (r) +#endif + memcpy (r, s, n + 1); + + return r; + } + + char* + strndupx (const char* s, size_t n) + { + char* r = new char[n + 1]; + +#ifndef XSDE_EXCEPTIONS + if (r) + { +#endif + memcpy (r, s, n); + r[n] = '\0'; + +#ifndef XSDE_EXCEPTIONS + } +#endif + + return r; + } + } +} diff --git a/libxsde/xsde/cxx/strdupx.hxx b/libxsde/xsde/cxx/strdupx.hxx new file mode 100644 index 0000000..9277f3c --- /dev/null +++ b/libxsde/xsde/cxx/strdupx.hxx @@ -0,0 +1,27 @@ +// file : xsde/cxx/strdupx.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_STRDUPX_HXX +#define XSDE_CXX_STRDUPX_HXX + +#include // size_t + +namespace xsde +{ + namespace cxx + { + // C++ versions of strdup and strndup. They allocate the string + // using new char[]. In the no-exceptions case return 0 if + // allocation fails. + // + char* + strdupx (const char*); + + char* + strndupx (const char*, size_t); + } +} + +#endif // XSDE_CXX_STRDUPX_HXX diff --git a/libxsde/xsde/cxx/string-sequence-stl.cxx b/libxsde/xsde/cxx/string-sequence-stl.cxx new file mode 100644 index 0000000..ea2cb81 --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence-stl.cxx @@ -0,0 +1,147 @@ +// file : xsde/cxx/string-sequence-stl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + void string_sequence:: + clear () + { + typedef std::string type; + for (size_t i = 0; i < size_; ++i) + static_cast (data_)[i].~type (); + + size_ = 0; + } + +#ifdef XSDE_EXCEPTIONS + struct guard + { + guard (std::string* p, size_t& n) : p_ (p), n_ (n) {} + + ~guard () + { + typedef std::string type; + if (p_) + for (; n_ > 0; --n_) + p_[n_ - 1].~type (); + } + + void + release () { p_ = 0; } + + private: + std::string* p_; + size_t& n_; + }; + + void string_sequence:: + move_ (void* dst, void* src, size_t n) + { + std::string* d = static_cast (dst); + std::string* s = static_cast (src); + + // The copy c-tor can throw in which case we need to destroy + // whatever objects we already copied into d. + // + size_t i = 0; + guard g (d, i); + + for (; i < n; i++) + new (d + i) std::string (s[i]); + + g.release (); + + typedef std::string type; + for (size_t j = 0; j < n; j++) + s[j].~type (); + } +#else + void string_sequence:: + move_ (void* dst, void* src, size_t n) + { + std::string* d = static_cast (dst); + std::string* s = static_cast (src); + + for (size_t i = 0; i < n; i++) + { + typedef std::string type; + new (d + i) std::string (s[i]); + s[i].~type (); + } + } +#endif + + void string_sequence:: + move_forward_ (void* p, size_t n) + { + // We are moving a sequence of elements one position to the left. + // The tricky part is to make sure we are in at least destructable + // state if things turn bad. We assume that there is a valid + // element at position p. + // + std::string* d = static_cast (p); + + for (size_t i = 0; i < n; i++) + d[i] = d[i + 1]; + + typedef std::string type; + d[n].~type (); + } + +#ifdef XSDE_EXCEPTIONS + void string_sequence:: + move_backward_ (void* p, size_t n, size_t& size) + { + // We are moving a sequence of elements one position to the right. + // The tricky part is to make sure we are in at least destructable + // state if things turn bad. + // + std::string* d = static_cast (p); + std::string* e = d + n; + + new (e) std::string; + size++; + + for (size_t i = n; i > 0; i--) + d[i] = d[i - 1]; + } +#else + void string_sequence:: + move_backward_ (void* p, size_t n) + { + // We are moving a sequence of elements one position to the right. + // + std::string* d = static_cast (p); + std::string* e = d + n; + + new (e) std::string; + + for (size_t i = n; i > 0; i--) + d[i] = d[i - 1]; + } +#endif + + bool + operator== (const string_sequence& x, const string_sequence& y) + { + if (x.size () != y.size ()) + return false; + + for (string_sequence::const_iterator + xi (x.begin ()), yi (y.begin ()), xe (x.end ()); + xi != xe; ++xi, ++yi) + { + if (*xi != *yi) + return false; + } + + return true; + } + } +} diff --git a/libxsde/xsde/cxx/string-sequence-stl.hxx b/libxsde/xsde/cxx/string-sequence-stl.hxx new file mode 100644 index 0000000..d466d85 --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence-stl.hxx @@ -0,0 +1,135 @@ +// file : xsde/cxx/string-sequence-stl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_STRING_SEQUENCE_STL_HXX +#define XSDE_CXX_STRING_SEQUENCE_STL_HXX + +#include +#include // size_t, ptrdiff_t + +#include +#include + +namespace xsde +{ + namespace cxx + { + class string_sequence: public sequence_base + { + public: + typedef std::string value_type; + typedef std::string* pointer; + typedef const std::string* const_pointer; + typedef std::string& reference; + typedef const std::string& const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef std::string* iterator; + typedef const std::string* const_iterator; + + public: + ~string_sequence (); + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + std::string& + front (); + + const std::string& + front () const; + + std::string& + back (); + + const std::string& + back () const; + + std::string& + operator[] (size_t); + + const std::string& + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (const std::string&); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, const std::string&); + + error + insert (iterator, const std::string&, iterator& result); +#else + iterator + insert (iterator, const std::string&); +#endif + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (string_sequence&); + + private: + static void + move_ (void* dst, void* src, size_t n); + + static void + move_forward_ (void* p, size_t n); + +#ifdef XSDE_EXCEPTIONS + static void + move_backward_ (void* p, size_t n, size_t& size); +#else + static void + move_backward_ (void* p, size_t n); +#endif + }; + + bool + operator== (const string_sequence&, const string_sequence&); + + bool + operator!= (const string_sequence&, const string_sequence&); + } +} + +#include + +#endif // XSDE_CXX_STRING_SEQUENCE_STL_HXX diff --git a/libxsde/xsde/cxx/string-sequence-stl.ixx b/libxsde/xsde/cxx/string-sequence-stl.ixx new file mode 100644 index 0000000..be05012 --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence-stl.ixx @@ -0,0 +1,204 @@ +// file : xsde/cxx/string-sequence-stl.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline string_sequence:: + ~string_sequence () + { + clear (); + } + + inline size_t string_sequence:: + max_size () const + { + return size_t (-1) / sizeof (std::string); + } + + inline void string_sequence:: + swap (string_sequence& x) + { + swap_ (x); + } + + inline std::string* string_sequence:: + begin () + { + return static_cast (data_); + } + + inline const std::string* string_sequence:: + begin () const + { + // g++ 2.95 does not like static_cast here. + // + return (const std::string*) (data_); + } + + inline std::string* string_sequence:: + end () + { + return static_cast (data_) + size_; + } + + inline const std::string* string_sequence:: + end () const + { + return ((const std::string*) (data_)) + size_; + } + + inline std::string& string_sequence:: + front () + { + return *static_cast (data_); + } + + inline const std::string& string_sequence:: + front () const + { + return *((const std::string*) (data_)); + } + + inline std::string& string_sequence:: + back () + { + return static_cast (data_)[size_ - 1]; + } + + inline const std::string& string_sequence:: + back () const + { + return ((const std::string*) (data_))[size_ - 1]; + } + + inline std::string& string_sequence:: + operator[] (size_t i) + { + return static_cast (data_)[i]; + } + + inline const std::string& string_sequence:: + operator[] (size_t i) const + { + return ((const std::string*) (data_))[i]; + } + + inline void string_sequence:: + pop_back () + { + typedef std::string type; + static_cast (data_)[size_ - 1].~type (); + --size_; + } + + inline std::string* string_sequence:: + erase (std::string* i) + { + if (i != static_cast (data_) + (size_ - 1)) + erase_ (i, sizeof (std::string), &move_forward_); + else + { + typedef std::string type; + static_cast (data_)[size_ - 1].~type (); + --size_; + } + + return i; + } + +#ifdef XSDE_EXCEPTIONS + inline void string_sequence:: + push_back (const std::string& x) + { + if (capacity_ < size_ + 1) + grow_ (0, sizeof (std::string), &move_); + + new (static_cast (data_) + size_) std::string (x); + size_++; + } + + inline std::string* string_sequence:: + insert (std::string* i, const std::string& x) + { + std::string* p = static_cast ( + insert_ (i, sizeof (std::string), &move_, &move_backward_)); + *p = x; + return p; + } + + inline void string_sequence:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (std::string*), &move_); + } +#else + inline sequence_base::error string_sequence:: + push_back (const std::string& x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (std::string), &move_); + + if (r == error_none) + { + new (static_cast (data_) + size_) std::string (x); + size_++; + } + + return r; + } + + inline sequence_base::error string_sequence:: + insert (std::string* i, const std::string& x) + { + std::string* p = static_cast ( + insert_ (i, sizeof (std::string), &move_, &move_backward_)); + + if (p) + { + *p = x; + return error_none; + } + else + return error_no_memory; + } + + inline sequence_base::error string_sequence:: + insert (std::string* i, const std::string& x, std::string*& r) + { + std::string* p = static_cast ( + insert_ (i, sizeof (std::string), &move_, &move_backward_)); + + if (p) + { + *p = x; + r = p; + return error_none; + } + else + return error_no_memory; + } + + inline sequence_base::error string_sequence:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (std::string), &move_); + return r; + } +#endif + + inline bool + operator!= (const string_sequence& x, const string_sequence& y) + { + return !(x == y); + } + } +} diff --git a/libxsde/xsde/cxx/string-sequence.cxx b/libxsde/xsde/cxx/string-sequence.cxx new file mode 100644 index 0000000..beb58ef --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence.cxx @@ -0,0 +1,76 @@ +// file : xsde/cxx/string-sequence.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include // memcpy, strlen, strcmp + +#include + +namespace xsde +{ + namespace cxx + { + void string_sequence:: + clear () + { + for (size_t i = 0; i < size_; ++i) + delete[] static_cast (data_)[i]; + + size_ = 0; + } + +#ifdef XSDE_EXCEPTIONS + void string_sequence:: + push_back_copy (const char* cs) + { + if (capacity_ < size_ + 1) + grow_ (0, sizeof (char*), 0); + + size_t n = strlen (cs) + 1; + char* s = new char[n]; + memcpy (s, cs, n); + + static_cast (data_)[size_++] = s; + } +#else + string_sequence::error string_sequence:: + push_back_copy (const char* cs) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (char*), 0); + + if (r == error_none) + { + size_t n = strlen (cs) + 1; + char* s = new char[n]; + + if (s != 0) + { + memcpy (s, cs, n); + static_cast (data_)[size_++] = s; + } + else + r = error_no_memory; + } + + return r; + } +#endif + + bool + operator== (const string_sequence& x, const string_sequence& y) + { + if (x.size () != y.size ()) + return false; + + for (size_t i = 0; i < x.size (); ++i) + if (strcmp (x[i], y[i]) != 0) + return false; + + return true; + } + } +} diff --git a/libxsde/xsde/cxx/string-sequence.hxx b/libxsde/xsde/cxx/string-sequence.hxx new file mode 100644 index 0000000..50c0025 --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence.hxx @@ -0,0 +1,133 @@ +// file : xsde/cxx/string-sequence.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_STRING_SEQUENCE_HXX +#define XSDE_CXX_STRING_SEQUENCE_HXX + +#include // size_t, ptrdiff_t + +#include +#include + +namespace xsde +{ + namespace cxx + { + class string_sequence: public sequence_base + { + public: + typedef char* value_type; + typedef char** pointer; + typedef const char** const_pointer; + typedef char* reference; + typedef const char* const_reference; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef char** iterator; + typedef const char* const* const_iterator; + + public: + ~string_sequence (); + + public: + iterator + begin (); + + const_iterator + begin () const; + + iterator + end (); + + const_iterator + end () const; + + char* + front (); + + const char* + front () const; + + char* + back (); + + const char* + back () const; + + char* + operator[] (size_t); + + const char* + operator[] (size_t) const; + + public: + size_t + max_size () const; + + void + clear (); + + void + pop_back (); + + iterator + erase (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back (char*); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + push_back_copy (const char*); + +#ifndef XSDE_EXCEPTIONS + error + insert (iterator, char*); + + error + insert (iterator, char*, iterator& result); +#else + iterator + insert (iterator, char*); +#endif + + // Detach a string from the sequence at a given position. + // The string pointer at this position in the sequence is + // set to 0. + // + char* + detach (iterator); + +#ifndef XSDE_EXCEPTIONS + error +#else + void +#endif + reserve (size_t); + + void + swap (string_sequence&); + }; + + bool + operator== (const string_sequence&, const string_sequence&); + + bool + operator!= (const string_sequence&, const string_sequence&); + } +} + +#include + +#endif // XSDE_CXX_STRING_SEQUENCE_HXX diff --git a/libxsde/xsde/cxx/string-sequence.ixx b/libxsde/xsde/cxx/string-sequence.ixx new file mode 100644 index 0000000..58878b7 --- /dev/null +++ b/libxsde/xsde/cxx/string-sequence.ixx @@ -0,0 +1,233 @@ +// file : xsde/cxx/string-sequence.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline string_sequence:: + ~string_sequence () + { + clear (); + } + + inline size_t string_sequence:: + max_size () const + { + return size_t (-1) / sizeof (char*); + } + + inline void string_sequence:: + swap (string_sequence& x) + { + swap_ (x); + } + + inline string_sequence::iterator string_sequence:: + begin () + { + return static_cast (data_); + } + + inline string_sequence::const_iterator string_sequence:: + begin () const + { + // g++ 2.95 does not like static_cast here. + // + return (const char* const*) (data_); + } + + inline string_sequence::iterator string_sequence:: + end () + { + return static_cast (data_) + size_; + } + + inline string_sequence::const_iterator string_sequence:: + end () const + { + return ((const char* const*) (data_)) + size_; + } + + inline char* string_sequence:: + front () + { + return *static_cast (data_); + } + + inline const char* string_sequence:: + front () const + { + return *((const char* const*) (data_)); + } + + inline char* string_sequence:: + back () + { + return static_cast (data_)[size_ - 1]; + } + + inline const char* string_sequence:: + back () const + { + return ((const char* const*) (data_))[size_ - 1]; + } + + inline char* string_sequence:: + operator[] (size_t i) + { + return static_cast (data_)[i]; + } + + inline const char* string_sequence:: + operator[] (size_t i) const + { + return ((const char* const*) (data_))[i]; + } + + inline void string_sequence:: + pop_back () + { + delete[] static_cast (data_)[size_ - 1]; + --size_; + } + + inline string_sequence::iterator string_sequence:: + erase (iterator i) + { + delete[] *i; + + if (i != static_cast (data_) + (size_ - 1)) + erase_ (i, sizeof (char*), 0); + else + --size_; + + return i; + } + +#ifdef XSDE_EXCEPTIONS + namespace string_sequence_bits + { + struct guard + { + ~guard () { delete[] p_; } + guard (char* p) : p_ (p) {} + + void + release () { p_ = 0; } + + private: + char* p_; + }; + } + + inline void string_sequence:: + push_back (char* x) + { + string_sequence_bits::guard g (x); + + if (capacity_ < size_ + 1) + grow_ (0, sizeof (char*), 0); + + static_cast (data_)[size_++] = x; + + g.release (); + } + + inline string_sequence::iterator string_sequence:: + insert (iterator i, char* x) + { + string_sequence_bits::guard g (x); + char** p = static_cast (insert_ (i, sizeof (char*), 0, 0)); + *p = x; + g.release (); + return p; + } + + inline void string_sequence:: + reserve (size_t n) + { + if (capacity_ < n) + grow_ (n, sizeof (char*), 0); + } +#else + inline sequence_base::error string_sequence:: + push_back (char* x) + { + error r = error_none; + + if (capacity_ < size_ + 1) + r = grow_ (0, sizeof (char*), 0); + + if (r == error_none) + static_cast (data_)[size_++] = x; + else + delete[] x; + + return r; + } + + inline sequence_base::error string_sequence:: + insert (iterator i, char* x) + { + char** p = static_cast (insert_ (i, sizeof (char*), 0, 0)); + + if (p) + { + *p = x; + return error_none; + } + else + { + delete[] x; + return error_no_memory; + } + } + + inline sequence_base::error string_sequence:: + insert (iterator i, char* x, iterator& r) + { + char** p = static_cast (insert_ (i, sizeof (char*), 0, 0)); + + if (p) + { + *p = x; + r = p; + return error_none; + } + else + { + delete[] x; + return error_no_memory; + } + } + + inline sequence_base::error string_sequence:: + reserve (size_t n) + { + error r = error_none; + if (capacity_ < n) + r = grow_ (n, sizeof (char*), 0); + return r; + } +#endif + + inline char* string_sequence:: + detach (iterator p) + { + char* r = *p; + *p = 0; + return r; + } + + // + // + inline bool + operator!= (const string_sequence& x, const string_sequence& y) + { + return !(x == y); + } + } +} diff --git a/libxsde/xsde/cxx/string.cxx b/libxsde/xsde/cxx/string.cxx new file mode 100644 index 0000000..2edb3cb --- /dev/null +++ b/libxsde/xsde/cxx/string.cxx @@ -0,0 +1,75 @@ +// file : xsde/cxx/string.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +namespace xsde +{ + namespace cxx + { + string::error string:: + assign (const char* s, size_t size) + { + if (size + 1 > capacity_) + if (error e = resize (size + 1, false)) + return e; + + if (size != 0) + memcpy (data_, s, size); + + data_[size] = '\0'; + + size_ = size; + + return error_none; + } + + string::error string:: + append (const char* s, size_t size) + { + if (size_ + size + 1 > capacity_) + if (error e = resize (size_ + size + 1, true)) + return e; + + if (size != 0) + memcpy (data_ + size_, s, size); + + size_ += size; + data_[size_] = '\0'; + + return error_none; + } + + string::error string:: + resize (size_t new_cap, bool copy) + { + // Start with at least 64 chars (32 * 2). + // + size_t cap = capacity_ ? capacity_ : 32; + + if (new_cap <= 2 * cap) + new_cap = 2 * cap; + else + new_cap += (new_cap & 1) ? 1 : 0; // Make even. + + char* p = new char[new_cap]; + + if (p == 0) + return error_no_memory; + + if (copy && size_ != 0) + memcpy (p, data_, size_ + 1); + + delete[] data_; + + data_ = p; + capacity_ = new_cap; + + return error_none; + } + } +} diff --git a/libxsde/xsde/cxx/string.hxx b/libxsde/xsde/cxx/string.hxx new file mode 100644 index 0000000..27620bc --- /dev/null +++ b/libxsde/xsde/cxx/string.hxx @@ -0,0 +1,112 @@ +// file : xsde/cxx/string.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_STRING_HXX +#define XSDE_CXX_STRING_HXX + +#include // size_t + +namespace xsde +{ + namespace cxx + { + // Simple string for situations where std::string is not available. + // + struct string + { + enum error + { + error_none, + error_no_memory + }; + + typedef size_t size_type; + + ~string (); + + // The default c-tor creates an uninitialized string, not an + // empty string. Use assign() to initialize it. + // + string (); + + error + assign (const char*); + + error + assign (const char*, size_t); + + error + append (const char*); + + error + append (const char*, size_t); + + char& + operator[] (size_t); + + const char& + operator[] (size_t) const; + + size_t + size () const; + + char* + data (); + + const char* + data () const; + + bool + empty () const; + + void + swap (string&); + + public: + size_t + capacity () const; + + void + truncate (size_t); + + char* + detach (); + + void + attach (char*); + + private: + string (const string&); + + string& + operator= (const string&); + + private: + error + resize (size_t capacity, bool copy); + + private: + char* data_; + size_t size_; + size_t capacity_; + }; + + bool + operator== (const string&, const char*); + + bool + operator== (const char*, const string&); + + bool + operator!= (const string&, const char*); + + bool + operator!= (const char*, const string&); + } +} + +#include + +#endif // XSDE_CXX_STRING_HXX diff --git a/libxsde/xsde/cxx/string.ixx b/libxsde/xsde/cxx/string.ixx new file mode 100644 index 0000000..4977526 --- /dev/null +++ b/libxsde/xsde/cxx/string.ixx @@ -0,0 +1,149 @@ +// file : xsde/cxx/string.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + inline string:: + ~string () + { + delete[] data_; + } + + inline string:: + string () + : data_ (0), size_ (0), capacity_ (0) + { + } + + inline char* string:: + detach () + { + char* r = data_; + data_ = 0; + size_ = 0; + capacity_ = 0; + return r; + } + + inline void string:: + attach (char* s) + { + delete[] data_; + + data_ = s; + size_ = (s != 0 ? strlen (s) : 0); + capacity_ = (s != 0 ? size_ + 1 : 0); + } + + inline string::error string:: + assign (const char* s) + { + return assign (s, strlen (s)); + } + + inline string::error string:: + append (const char* s) + { + return append (s, strlen (s)); + } + + inline char& string:: + operator[] (size_t i) + { + return data_[i]; + } + + inline const char& string:: + operator[] (size_t i) const + { + return data_[i]; + } + + inline size_t string:: + size () const + { + return size_; + } + + inline char* string:: + data () + { + return data_; + } + + inline const char* string:: + data () const + { + return data_; + } + + inline bool string:: + empty () const + { + return size_ == 0; + } + + inline void string:: + swap (string& str) + { + char* d = data_; + data_ = str.data_; + str.data_ = d; + + size_t s = size_; + size_ = str.size_; + str.size_ = s; + + size_t c = capacity_; + capacity_ = str.capacity_; + str.capacity_ = c; + } + + inline size_t string:: + capacity () const + { + return capacity_; + } + + inline void string:: + truncate (size_t s) + { + if (s < size_) + { + size_ = s; + data_[s] = '\0'; + } + } + + inline bool + operator== (const string& a, const char* b) + { + return strcmp (a.data (), b) == 0; + } + + inline bool + operator== (const char* a, const string& b) + { + return strcmp (b.data (), a) == 0; + } + + inline bool + operator!= (const string& a, const char* b) + { + return strcmp (a.data (), b) != 0; + } + + inline bool + operator!= (const char* a, const string& b) + { + return strcmp (b.data (), a) != 0; + } + } +} + diff --git a/libxsde/xsde/cxx/sys-error.cxx b/libxsde/xsde/cxx/sys-error.cxx new file mode 100644 index 0000000..5f6d33a --- /dev/null +++ b/libxsde/xsde/cxx/sys-error.cxx @@ -0,0 +1,27 @@ +// file : xsde/cxx/sys-error.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + static const char* const text_[] = + { + "no error", + "no memory", + "open failed", + "read failed", + "write failed" + }; + + const char* sys_error:: + text (value v) + { + return text_[v]; + } + } +} diff --git a/libxsde/xsde/cxx/sys-error.hxx b/libxsde/xsde/cxx/sys-error.hxx new file mode 100644 index 0000000..2c1c770 --- /dev/null +++ b/libxsde/xsde/cxx/sys-error.hxx @@ -0,0 +1,42 @@ +// file : xsde/cxx/sys-error.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_SYS_ERROR_HXX +#define XSDE_CXX_SYS_ERROR_HXX + +namespace xsde +{ + namespace cxx + { + struct sys_error + { + enum value + { + none, + no_memory, + open_failed, + read_failed, + write_failed + }; + + sys_error (value); + + operator value () const + { + return v_; + } + + static const char* + text (value); + + private: + value v_; + }; + } +} + +#include + +#endif // XSDE_CXX_SYS_ERROR_HXX diff --git a/libxsde/xsde/cxx/sys-error.ixx b/libxsde/xsde/cxx/sys-error.ixx new file mode 100644 index 0000000..35c382c --- /dev/null +++ b/libxsde/xsde/cxx/sys-error.ixx @@ -0,0 +1,16 @@ +// file : xsde/cxx/sys-error.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +namespace xsde +{ + namespace cxx + { + inline sys_error:: + sys_error (value v) + : v_ (v) + { + } + } +} diff --git a/libxsde/xsde/cxx/version.hxx b/libxsde/xsde/cxx/version.hxx new file mode 100644 index 0000000..9033af7 --- /dev/null +++ b/libxsde/xsde/cxx/version.hxx @@ -0,0 +1,29 @@ +// file : xsde/cxx/version.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_VERSION_HXX +#define XSDE_CXX_VERSION_HXX + +// Version format is AABBCCDD where +// +// AA - major version number +// BB - minor version number +// CC - bugfix version number +// DD - alpha / beta (DD + 50) version number +// +// When DD is not 00, 1 is subtracted from AABBCC. For example: +// +// Version AABBCCDD +// 2.0.0 02000000 +// 2.1.0 02010000 +// 2.1.1 02010100 +// 2.2.0.a1 02019901 +// 3.0.0.b2 02999952 +// + +#define XSDE_STR_VERSION "3.0.0" +#define XSDE_INT_VERSION 3000000L + +#endif // XSDE_CXX_VERSION_HXX diff --git a/libxsde/xsde/cxx/xml/char-table.cxx b/libxsde/xsde/cxx/xml/char-table.cxx new file mode 100644 index 0000000..ae6239d --- /dev/null +++ b/libxsde/xsde/cxx/xml/char-table.cxx @@ -0,0 +1,27 @@ +// file : xsde/cxx/xml/char-table.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace xsde +{ + namespace cxx + { + namespace xml + { + unsigned char char_table[0x80] = + { + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD8, 0x48, 0x58, 0x48, 0x48, 0x48, 0x40, 0x58, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4D, 0x4D, 0x58, + 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x48, 0x50, 0x48, 0x58, 0x48, + 0x48, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x48, 0x48, 0x40, 0x48, 0x4F, + 0x48, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x48, 0x48, 0x48, 0x48, 0x48 + }; + } + } +} diff --git a/libxsde/xsde/cxx/xml/char-table.hxx b/libxsde/xsde/cxx/xml/char-table.hxx new file mode 100644 index 0000000..cd919f3 --- /dev/null +++ b/libxsde/xsde/cxx/xml/char-table.hxx @@ -0,0 +1,24 @@ +// file : xsde/cxx/xml/char-table.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_XML_CHAR_TABLE_HXX +#define XSDE_CXX_XML_CHAR_TABLE_HXX + +namespace xsde +{ + namespace cxx + { + namespace xml + { + const unsigned char ncname_char_mask = 0x1; + const unsigned char name_first_char_mask = 0x2; + const unsigned char name_char_mask = 0x4; + + extern unsigned char char_table[0x80]; + } + } +} + +#endif // XSDE_CXX_XML_CHAR_TABLE_HXX diff --git a/libxsde/xsde/cxx/xml/ncname.cxx b/libxsde/xsde/cxx/xml/ncname.cxx new file mode 100644 index 0000000..788a73d --- /dev/null +++ b/libxsde/xsde/cxx/xml/ncname.cxx @@ -0,0 +1,43 @@ +// file : xsde/cxx/xml/ncname.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace xsde +{ + namespace cxx + { + namespace xml + { + bool + valid_ncname (const char* s, size_t size) + { + // For now we are only checking the US-ASCII characters. + // + + bool ok = (size != 0); + + if (ok) + { + unsigned char c = static_cast (s[0]); + + ok = c >= 0x80 || + ((char_table[c] & name_first_char_mask) && c != ':'); + + for (size_t i = 1; ok && i < size; ++i) + { + c = static_cast (s[i]); + + if (c < 0x80 && !(xml::char_table[c] & xml::ncname_char_mask)) + ok = false; + } + } + + return ok; + } + } + } +} diff --git a/libxsde/xsde/cxx/xml/ncname.hxx b/libxsde/xsde/cxx/xml/ncname.hxx new file mode 100644 index 0000000..3e0fa98 --- /dev/null +++ b/libxsde/xsde/cxx/xml/ncname.hxx @@ -0,0 +1,23 @@ +// file : xsde/cxx/xml/ncname.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_CXX_XML_NCNAME_HXX +#define XSDE_CXX_XML_NCNAME_HXX + +#include // size_t + +namespace xsde +{ + namespace cxx + { + namespace xml + { + bool + valid_ncname (const char* s, size_t size); + } + } +} + +#endif // XSDE_CXX_XML_NCNAME_HXX diff --git a/libxsde/xsde/makefile b/libxsde/xsde/makefile new file mode 100644 index 0000000..e095030 --- /dev/null +++ b/libxsde/xsde/makefile @@ -0,0 +1,558 @@ +# file : xsde/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 + +cxx_tun := cxx/string.cxx cxx/ro-string.cxx + +ifeq ($(xsde_stl),n) +cxx_tun += cxx/strdupx.cxx +endif + +ifeq ($(xsde_exceptions),n) +cxx_tun += cxx/sys-error.cxx +endif + +ifneq ($(xsde_parser_validation)$(xsde_serializer_validation),nn) +cxx_tun += cxx/schema-error.cxx +endif + +ifeq ($(xsde_polymorphic),y) +cxx_tun += cxx/hashmap.cxx +endif + +# Common data types. +# +cxx_tun += cxx/buffer.cxx cxx/sequence-base.cxx + +ifeq ($(xsde_stl),y) +cxx_tun += cxx/string-sequence-stl.cxx +else +cxx_tun += cxx/qname.cxx cxx/string-sequence.cxx +endif + + +## XML +## +ifneq ($(xsde_parser_validation)$(xsde_serializer_validation),nn) +cxx_tun += cxx/xml/char-table.cxx cxx/xml/ncname.cxx +endif + + +## C++/Hybrid +## +cxx_tun += cxx/hybrid/sequence.cxx + + +## C++/Parser +## +cxx_tun += cxx/parser/elements.cxx cxx/parser/state.cxx + +ifeq ($(xsde_polymorphic),y) +cxx_tun += cxx/parser/map.cxx cxx/parser/substitution-map.cxx +endif + +ifeq ($(xsde_exceptions),y) +cxx_tun += cxx/parser/exceptions.cxx +else +cxx_tun += cxx/parser/error.cxx +endif + +cxx_tun += cxx/parser/expat/document.cxx cxx/parser/expat/xml-error.cxx + + +# Parser implementations. +# +ifeq ($(xsde_parser_validation),y) + +cxx_tun += \ +cxx/parser/validating/parser.cxx \ +cxx/parser/validating/time-zone.cxx \ +cxx/parser/validating/xml-schema-pskel.cxx + +ifeq ($(xsde_polymorphic),y) +cxx_tun += cxx/parser/validating/inheritance-map.cxx +endif + +cxx_tun += \ +cxx/parser/validating/boolean.cxx \ +cxx/parser/validating/number.cxx \ +cxx/parser/validating/byte.cxx \ +cxx/parser/validating/unsigned-byte.cxx \ +cxx/parser/validating/short.cxx \ +cxx/parser/validating/unsigned-short.cxx \ +cxx/parser/validating/int.cxx \ +cxx/parser/validating/unsigned-int.cxx \ +cxx/parser/validating/integer.cxx \ +cxx/parser/validating/negative-integer.cxx \ +cxx/parser/validating/non-positive-integer.cxx \ +cxx/parser/validating/positive-integer.cxx \ +cxx/parser/validating/non-negative-integer.cxx \ +cxx/parser/validating/float.cxx \ +cxx/parser/validating/double.cxx \ +cxx/parser/validating/decimal.cxx + +ifeq ($(xsde_longlong),y) +cxx_tun += \ +cxx/parser/validating/long-long.cxx \ +cxx/parser/validating/unsigned-long-long.cxx +else +cxx_tun += \ +cxx/parser/validating/long.cxx \ +cxx/parser/validating/unsigned-long.cxx +endif + +ifeq ($(xsde_stl),y) + +cxx_tun += \ +cxx/parser/validating/string-stl.cxx \ +cxx/parser/validating/normalized-string-stl.cxx \ +cxx/parser/validating/token-stl.cxx \ +cxx/parser/validating/name-stl.cxx \ +cxx/parser/validating/nmtoken-stl.cxx \ +cxx/parser/validating/nmtokens-stl.cxx \ +cxx/parser/validating/ncname-stl.cxx \ +cxx/parser/validating/id-stl.cxx \ +cxx/parser/validating/idref-stl.cxx \ +cxx/parser/validating/idrefs-stl.cxx \ +cxx/parser/validating/language-stl.cxx \ +cxx/parser/validating/uri-stl.cxx \ +cxx/parser/validating/qname-stl.cxx + +else + +cxx_tun += \ +cxx/parser/validating/string.cxx \ +cxx/parser/validating/normalized-string.cxx \ +cxx/parser/validating/token.cxx \ +cxx/parser/validating/name.cxx \ +cxx/parser/validating/nmtoken.cxx \ +cxx/parser/validating/nmtokens.cxx \ +cxx/parser/validating/ncname.cxx \ +cxx/parser/validating/id.cxx \ +cxx/parser/validating/idref.cxx \ +cxx/parser/validating/idrefs.cxx \ +cxx/parser/validating/language.cxx \ +cxx/parser/validating/uri.cxx \ +cxx/parser/validating/qname.cxx + +endif # stl + +cxx_tun += \ +cxx/parser/validating/base64-binary.cxx \ +cxx/parser/validating/hex-binary.cxx \ +cxx/parser/validating/gday.cxx \ +cxx/parser/validating/gmonth.cxx \ +cxx/parser/validating/gyear.cxx \ +cxx/parser/validating/gmonth-day.cxx \ +cxx/parser/validating/gyear-month.cxx \ +cxx/parser/validating/date.cxx \ +cxx/parser/validating/time.cxx \ +cxx/parser/validating/date-time.cxx \ +cxx/parser/validating/duration.cxx + +else # validation + +cxx_tun += \ +cxx/parser/non-validating/parser.cxx \ +cxx/parser/non-validating/time-zone.cxx \ +cxx/parser/non-validating/xml-schema-pskel.cxx + +cxx_tun += \ +cxx/parser/non-validating/boolean.cxx \ +cxx/parser/non-validating/number.cxx \ +cxx/parser/non-validating/byte.cxx \ +cxx/parser/non-validating/unsigned-byte.cxx \ +cxx/parser/non-validating/short.cxx \ +cxx/parser/non-validating/unsigned-short.cxx \ +cxx/parser/non-validating/int.cxx \ +cxx/parser/non-validating/unsigned-int.cxx \ +cxx/parser/non-validating/integer.cxx \ +cxx/parser/non-validating/negative-integer.cxx \ +cxx/parser/non-validating/non-positive-integer.cxx \ +cxx/parser/non-validating/positive-integer.cxx \ +cxx/parser/non-validating/non-negative-integer.cxx \ +cxx/parser/non-validating/float.cxx \ +cxx/parser/non-validating/double.cxx \ +cxx/parser/non-validating/decimal.cxx + +ifeq ($(xsde_longlong),y) +cxx_tun += \ +cxx/parser/non-validating/long-long.cxx \ +cxx/parser/non-validating/unsigned-long-long.cxx +else +cxx_tun += \ +cxx/parser/non-validating/long.cxx \ +cxx/parser/non-validating/unsigned-long.cxx +endif + +ifeq ($(xsde_stl),y) + +cxx_tun += \ +cxx/parser/non-validating/string-stl.cxx \ +cxx/parser/non-validating/normalized-string-stl.cxx \ +cxx/parser/non-validating/token-stl.cxx \ +cxx/parser/non-validating/name-stl.cxx \ +cxx/parser/non-validating/nmtoken-stl.cxx \ +cxx/parser/non-validating/nmtokens-stl.cxx \ +cxx/parser/non-validating/ncname-stl.cxx \ +cxx/parser/non-validating/id-stl.cxx \ +cxx/parser/non-validating/idref-stl.cxx \ +cxx/parser/non-validating/idrefs-stl.cxx \ +cxx/parser/non-validating/language-stl.cxx \ +cxx/parser/non-validating/uri-stl.cxx \ +cxx/parser/non-validating/qname-stl.cxx + +else + +cxx_tun += \ +cxx/parser/non-validating/string.cxx \ +cxx/parser/non-validating/normalized-string.cxx \ +cxx/parser/non-validating/token.cxx \ +cxx/parser/non-validating/name.cxx \ +cxx/parser/non-validating/nmtoken.cxx \ +cxx/parser/non-validating/nmtokens.cxx \ +cxx/parser/non-validating/ncname.cxx \ +cxx/parser/non-validating/id.cxx \ +cxx/parser/non-validating/idref.cxx \ +cxx/parser/non-validating/idrefs.cxx \ +cxx/parser/non-validating/language.cxx \ +cxx/parser/non-validating/uri.cxx \ +cxx/parser/non-validating/qname.cxx + +endif # stl + +cxx_tun += \ +cxx/parser/non-validating/base64-binary.cxx \ +cxx/parser/non-validating/hex-binary.cxx \ +cxx/parser/non-validating/gday.cxx \ +cxx/parser/non-validating/gmonth.cxx \ +cxx/parser/non-validating/gyear.cxx \ +cxx/parser/non-validating/gmonth-day.cxx \ +cxx/parser/non-validating/gyear-month.cxx \ +cxx/parser/non-validating/date.cxx \ +cxx/parser/non-validating/time.cxx \ +cxx/parser/non-validating/date-time.cxx \ +cxx/parser/non-validating/duration.cxx + +endif # validation + + +## C++/Serializer +## +cxx_tun += cxx/serializer/elements.cxx cxx/serializer/context.cxx + +ifeq ($(xsde_polymorphic),y) +cxx_tun += cxx/serializer/map.cxx cxx/serializer/substitution-map.cxx +endif + +ifeq ($(xsde_exceptions),y) +cxx_tun += cxx/serializer/exceptions.cxx +else +cxx_tun += cxx/serializer/error.cxx +endif + +cxx_tun += cxx/serializer/genx/document.cxx cxx/serializer/genx/xml-error.cxx + +# Serializer implementations. +# +ifeq ($(xsde_serializer_validation),y) + +cxx_tun += \ +cxx/serializer/validating/serializer.cxx \ +cxx/serializer/validating/time-zone.cxx \ +cxx/serializer/validating/xml-schema-sskel.cxx + +ifeq ($(xsde_polymorphic),y) +cxx_tun += cxx/serializer/validating/inheritance-map.cxx +endif + +cxx_tun += \ +cxx/serializer/validating/boolean.cxx \ +cxx/serializer/validating/byte.cxx \ +cxx/serializer/validating/unsigned-byte.cxx \ +cxx/serializer/validating/short.cxx \ +cxx/serializer/validating/unsigned-short.cxx \ +cxx/serializer/validating/int.cxx \ +cxx/serializer/validating/unsigned-int.cxx \ +cxx/serializer/validating/integer.cxx \ +cxx/serializer/validating/negative-integer.cxx \ +cxx/serializer/validating/non-positive-integer.cxx \ +cxx/serializer/validating/positive-integer.cxx \ +cxx/serializer/validating/non-negative-integer.cxx \ +cxx/serializer/validating/float.cxx \ +cxx/serializer/validating/double.cxx \ +cxx/serializer/validating/decimal.cxx + +ifeq ($(xsde_longlong),y) +cxx_tun += \ +cxx/serializer/validating/long-long.cxx \ +cxx/serializer/validating/unsigned-long-long.cxx +else +cxx_tun += \ +cxx/serializer/validating/long.cxx \ +cxx/serializer/validating/unsigned-long.cxx +endif + +ifeq ($(xsde_stl),y) + +cxx_tun += \ +cxx/serializer/validating/string-stl.cxx \ +cxx/serializer/validating/normalized-string-stl.cxx \ +cxx/serializer/validating/token-stl.cxx \ +cxx/serializer/validating/name-stl.cxx \ +cxx/serializer/validating/nmtoken-stl.cxx \ +cxx/serializer/validating/ncname-stl.cxx \ +cxx/serializer/validating/id-stl.cxx \ +cxx/serializer/validating/idref-stl.cxx \ +cxx/serializer/validating/language-stl.cxx \ +cxx/serializer/validating/uri-stl.cxx \ +cxx/serializer/validating/idrefs-stl.cxx \ +cxx/serializer/validating/nmtokens-stl.cxx \ +cxx/serializer/validating/qname-stl.cxx + +else + +cxx_tun += \ +cxx/serializer/validating/string.cxx \ +cxx/serializer/validating/normalized-string.cxx \ +cxx/serializer/validating/token.cxx \ +cxx/serializer/validating/name.cxx \ +cxx/serializer/validating/nmtoken.cxx \ +cxx/serializer/validating/ncname.cxx \ +cxx/serializer/validating/id.cxx \ +cxx/serializer/validating/idref.cxx \ +cxx/serializer/validating/language.cxx \ +cxx/serializer/validating/uri.cxx \ +cxx/serializer/validating/idrefs.cxx \ +cxx/serializer/validating/nmtokens.cxx \ +cxx/serializer/validating/qname.cxx + +endif # stl + +cxx_tun += \ +cxx/serializer/validating/base64-binary.cxx \ +cxx/serializer/validating/hex-binary.cxx \ +cxx/serializer/validating/gday.cxx \ +cxx/serializer/validating/gmonth.cxx \ +cxx/serializer/validating/gyear.cxx \ +cxx/serializer/validating/gmonth-day.cxx \ +cxx/serializer/validating/gyear-month.cxx \ +cxx/serializer/validating/date.cxx \ +cxx/serializer/validating/time.cxx \ +cxx/serializer/validating/date-time.cxx \ +cxx/serializer/validating/duration.cxx + +else # validation + +cxx_tun += \ +cxx/serializer/non-validating/serializer.cxx \ +cxx/serializer/non-validating/time-zone.cxx \ +cxx/serializer/non-validating/xml-schema-sskel.cxx + +cxx_tun += \ +cxx/serializer/non-validating/boolean.cxx \ +cxx/serializer/non-validating/byte.cxx \ +cxx/serializer/non-validating/unsigned-byte.cxx \ +cxx/serializer/non-validating/short.cxx \ +cxx/serializer/non-validating/unsigned-short.cxx \ +cxx/serializer/non-validating/int.cxx \ +cxx/serializer/non-validating/unsigned-int.cxx \ +cxx/serializer/non-validating/integer.cxx \ +cxx/serializer/non-validating/negative-integer.cxx \ +cxx/serializer/non-validating/non-positive-integer.cxx \ +cxx/serializer/non-validating/positive-integer.cxx \ +cxx/serializer/non-validating/non-negative-integer.cxx \ +cxx/serializer/non-validating/float.cxx \ +cxx/serializer/non-validating/double.cxx \ +cxx/serializer/non-validating/decimal.cxx + +ifeq ($(xsde_longlong),y) +cxx_tun += \ +cxx/serializer/non-validating/long-long.cxx \ +cxx/serializer/non-validating/unsigned-long-long.cxx +else +cxx_tun += \ +cxx/serializer/non-validating/long.cxx \ +cxx/serializer/non-validating/unsigned-long.cxx +endif + +ifeq ($(xsde_stl),y) + +cxx_tun += \ +cxx/serializer/non-validating/string-stl.cxx \ +cxx/serializer/non-validating/normalized-string-stl.cxx \ +cxx/serializer/non-validating/token-stl.cxx \ +cxx/serializer/non-validating/name-stl.cxx \ +cxx/serializer/non-validating/nmtoken-stl.cxx \ +cxx/serializer/non-validating/ncname-stl.cxx \ +cxx/serializer/non-validating/id-stl.cxx \ +cxx/serializer/non-validating/idref-stl.cxx \ +cxx/serializer/non-validating/language-stl.cxx \ +cxx/serializer/non-validating/uri-stl.cxx \ +cxx/serializer/non-validating/idrefs-stl.cxx \ +cxx/serializer/non-validating/nmtokens-stl.cxx \ +cxx/serializer/non-validating/qname-stl.cxx + +else + +cxx_tun += \ +cxx/serializer/non-validating/string.cxx \ +cxx/serializer/non-validating/normalized-string.cxx \ +cxx/serializer/non-validating/token.cxx \ +cxx/serializer/non-validating/name.cxx \ +cxx/serializer/non-validating/nmtoken.cxx \ +cxx/serializer/non-validating/ncname.cxx \ +cxx/serializer/non-validating/id.cxx \ +cxx/serializer/non-validating/idref.cxx \ +cxx/serializer/non-validating/language.cxx \ +cxx/serializer/non-validating/uri.cxx \ +cxx/serializer/non-validating/idrefs.cxx \ +cxx/serializer/non-validating/nmtokens.cxx \ +cxx/serializer/non-validating/qname.cxx + +endif # stl + +cxx_tun += \ +cxx/serializer/non-validating/base64-binary.cxx \ +cxx/serializer/non-validating/hex-binary.cxx \ +cxx/serializer/non-validating/gday.cxx \ +cxx/serializer/non-validating/gmonth.cxx \ +cxx/serializer/non-validating/gyear.cxx \ +cxx/serializer/non-validating/gmonth-day.cxx \ +cxx/serializer/non-validating/gyear-month.cxx \ +cxx/serializer/non-validating/date.cxx \ +cxx/serializer/non-validating/time.cxx \ +cxx/serializer/non-validating/date-time.cxx \ +cxx/serializer/non-validating/duration.cxx + +endif # validation + + +cxx_o := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_d := $(cxx_o:.o=.o.d) + +xsde.l := $(out_base)/xsde.l +xsde.l.cpp-options := $(out_base)/xsde.l.cpp-options + +clean := $(out_base)/.clean + + +# Build. +# +$(xsde.l): $(cxx_o) -lexpat -lgenx + +$(cxx_o) $(cxx_d): $(xsde.l.cpp-options) $(out_base)/config.h + +$(xsde.l.cpp-options): prefix := xsde/ $(out_root)/libxsde/ +$(xsde.l.cpp-options): value := -I$(out_root)/libxsde -I$(src_root)/libxsde + +$(call include-dep,$(cxx_d)) + +# config.h +# +$(out_base)/config.h: $(dcf_root)/configuration-dynamic.make + @echo '// file : xsde/config.h' >$@ + @echo '// author : automatically generated' >>$@ + @echo '' >>$@ + @echo '#ifndef XSDE_CONFIG_H' >>$@ + @echo '#define XSDE_CONFIG_H' >>$@ + @echo '' >>$@ + @echo '#define XSDE_PLATFORM_POSIX' >>$@ + @echo '#define XSDE_ARCH_WIDTH $(xsde_arch_width)' >>$@ +ifeq ($(xsde_byteorder),l) + @echo '#define XSDE_BYTEORDER 1234' >>$@ +else + @echo '#define XSDE_BYTEORDER 4321' >>$@ +endif +ifeq ($(xsde_stl),y) + @echo '#define XSDE_STL' >>$@ +else + @echo '#undef XSDE_STL' >>$@ +endif +ifeq ($(xsde_iostream),y) + @echo '#define XSDE_IOSTREAM' >>$@ +else + @echo '#undef XSDE_IOSTREAM' >>$@ +endif +ifeq ($(xsde_exceptions),y) + @echo '#define XSDE_EXCEPTIONS' >>$@ +else + @echo '#undef XSDE_EXCEPTIONS' >>$@ +endif +ifeq ($(xsde_longlong),y) + @echo '#define XSDE_LONGLONG' >>$@ +else + @echo '#undef XSDE_LONGLONG' >>$@ +endif +ifeq ($(xsde_snprintf),y) + @echo '#define XSDE_SNPRINTF' >>$@ +else + @echo '#undef XSDE_SNPRINTF' >>$@ +endif +ifeq ($(xsde_parser_validation),y) + @echo '#define XSDE_PARSER_VALIDATION' >>$@ +else + @echo '#undef XSDE_PARSER_VALIDATION' >>$@ +endif +ifeq ($(xsde_serializer_validation),y) + @echo '#define XSDE_SERIALIZER_VALIDATION' >>$@ +else + @echo '#undef XSDE_SERIALIZER_VALIDATION' >>$@ +endif +ifeq ($(xsde_reuse_style),mixin) + @echo '#define XSDE_REUSE_STYLE_MIXIN' >>$@ +else + @echo '#undef XSDE_REUSE_STYLE_MIXIN' >>$@ +endif +ifeq ($(xsde_reuse_style),tiein) + @echo '#define XSDE_REUSE_STYLE_TIEIN' >>$@ +else + @echo '#undef XSDE_REUSE_STYLE_TIEIN' >>$@ +endif +ifeq ($(xsde_reuse_style),none) + @echo '#define XSDE_REUSE_STYLE_NONE' >>$@ +else + @echo '#undef XSDE_REUSE_STYLE_NONE' >>$@ +endif +ifeq ($(xsde_polymorphic),y) + @echo '#define XSDE_POLYMORPHIC' >>$@ + @echo '#define XSDE_PARSER_SMAP_BUCKETS $(xsde_parser_smap_buckets)UL' >>$@ +ifeq ($(xsde_parser_validation),y) + @echo '#define XSDE_PARSER_IMAP_BUCKETS $(xsde_parser_imap_buckets)UL' >>$@ +endif + @echo '#define XSDE_SERIALIZER_SMAP_BUCKETS $(xsde_serializer_smap_buckets)UL' >>$@ + @echo '#define XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS $(xsde_serializer_smap_bucket_buckets)UL' >>$@ +ifeq ($(xsde_serializer_validation),y) + @echo '#define XSDE_SERIALIZER_IMAP_BUCKETS $(xsde_serializer_imap_buckets)UL' >>$@ +endif +else + @echo '#undef XSDE_POLYMORPHIC' >>$@ +endif + @echo '' >>$@ + @echo '#endif // XSDE_CONFIG_H' >>$@ + + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(xsde.l) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(xsde.l).o.clean \ + $(xsde.l.cpp-options).clean \ + $(addsuffix .cxx.clean,$(cxx_o)) \ + $(addsuffix .cxx.clean,$(cxx_d)) + $(call message,rm $$1,rm -f $$1,$(out_base)/config.h) + +# How to. +# +$(call include,$(bld_root)/cxx/o-l.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) diff --git a/makefile b/makefile new file mode 100644 index 0000000..3f83dda --- /dev/null +++ b/makefile @@ -0,0 +1,43 @@ +# file : 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 + +default := $(out_base)/ +test := $(out_base)/.test +install := $(out_base)/.install +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(install) $(clean) + +$(default): $(out_base)/xsde/ \ + $(out_base)/libxsde/ \ + $(out_base)/tests/ \ + $(out_base)/examples/ + +$(test): $(out_base)/tests/.test + +$(install): $(out_base)/xsde/.install \ + $(out_base)/libxsde/.install \ + $(out_base)/documentation/.install + $(call install-data,$(src_base)/FLOSSE,$(install_doc_dir)/xsde/FLOSSE) + $(call install-data,$(src_base)/GPLv2,$(install_doc_dir)/xsde/GPLv2) + $(call install-data,$(src_base)/LICENSE,$(install_doc_dir)/xsde/LICENSE) + $(call install-data,$(src_base)/NEWS,$(install_doc_dir)/xsde/NEWS) + $(call install-data,$(src_base)/README,$(install_doc_dir)/xsde/README) + + +$(clean): $(out_base)/xsde/.clean \ + $(out_base)/libxsde/.clean \ + $(out_base)/tests/.clean \ + $(out_base)/examples/.clean + +$(call include,$(bld_root)/install.make) + +$(call import,$(src_base)/xsde/makefile) +$(call import,$(src_base)/libxsde/makefile) +$(call import,$(src_base)/tests/makefile) +$(call import,$(src_base)/examples/makefile) +$(call import,$(src_base)/documentation/makefile) diff --git a/tests/cxx/hashmap/driver.cxx b/tests/cxx/hashmap/driver.cxx new file mode 100644 index 0000000..99c773f --- /dev/null +++ b/tests/cxx/hashmap/driver.cxx @@ -0,0 +1,98 @@ +// file : tests/cxx/hashmap/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test xsde::cxx::hashmap type. +// +#include +#include + +#include + +#include + +using xsde::cxx::hashmap; +using namespace std; + +const char* table[] = +{ + "apple", "1", + "orange", "2", + "peach", "3", + "apricot", "4", + "mango", "5", + "banana", "6", + "pear", "7", + "grapefruit", "8", + "tangerine", "9", +}; + +const size_t table_size = (sizeof (table) / sizeof (const char*)) / 2; + +int +main () +{ + { + hashmap h (1, sizeof (const char*)); + assert (h.size () == 0 && h.empty () && h.max_bucket_size () == 0); + assert (h.begin () == h.end ()); + } + + { + hashmap h (2, sizeof (const char*)); + + const char* v = "bar"; + h.insert ("foo", &v); + assert (h.size () == 1 && !h.empty () && h.max_bucket_size () == 1); + assert (h.begin () != h.end ()); + const void* p = h.find ("foo"); + assert (p != 0 && *static_cast (p) == v); + } + + { + hashmap h (5, sizeof (const char*)); + + for (size_t i = 0; i < table_size; ++i) + { + const char* v = table[i * 2 + 1]; + h.insert (table[i * 2], &v); + } + + assert (h.size () == table_size); + + for (size_t i = 0; i < table_size; ++i) + { + const char* v = table[i * 2 + 1]; + const void* p = h.find (table[i * 2]); + assert (p != 0 && *static_cast (p) == v); + } + + // Figure out how many elements are in each bucket. + // + size_t bucket_entries[5] = {0, 0, 0, 0, 0}; + + for (size_t i = 0; i < table_size; ++i) + { + bucket_entries[hashmap::hash (table[i * 2]) % 5]++; + } + + size_t max = 0; + + for (size_t i = 0; i < 5; ++i) + { + if (bucket_entries[i] > max) + max = bucket_entries[i]; + } + + assert (max == h.max_bucket_size ()); + + // Test iteration + // + for (hashmap::const_iterator i = h.begin (); i != h.end (); ++i) + { + const void* p = *i; + cout << "'" << *static_cast (p) << "'" << endl; + } + } +} diff --git a/tests/cxx/hashmap/makefile b/tests/cxx/hashmap/makefile new file mode 100644 index 0000000..e9b3aca --- /dev/null +++ b/tests/cxx/hashmap/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/hashmap/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/hashmap/output b/tests/cxx/hashmap/output new file mode 100644 index 0000000..295e6da --- /dev/null +++ b/tests/cxx/hashmap/output @@ -0,0 +1,9 @@ +'1' +'4' +'2' +'9' +'3' +'8' +'5' +'6' +'7' diff --git a/tests/cxx/hybrid/built-in/driver.cxx b/tests/cxx/hybrid/built-in/driver.cxx new file mode 100644 index 0000000..6204882 --- /dev/null +++ b/tests/cxx/hybrid/built-in/driver.cxx @@ -0,0 +1,56 @@ +// file : tests/cxx/hybrid/built-in/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test built-in types. +// + +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/built-in/makefile b/tests/cxx/hybrid/built-in/makefile new file mode 100644 index 0000000..c62315c --- /dev/null +++ b/tests/cxx/hybrid/built-in/makefile @@ -0,0 +1,88 @@ +# file : tests/cxx/hybrid/built-in/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 := test.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 +test := $(out_base)/.test +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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(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/tests/cxx/hybrid/built-in/output b/tests/cxx/hybrid/built-in/output new file mode 100644 index 0000000..6798590 --- /dev/null +++ b/tests/cxx/hybrid/built-in/output @@ -0,0 +1,5 @@ +123abc123456789123YmFzZTY0IGJpbmFyeQ== +YmFzZTY0IGJpbmFyeQ== +YmFzZTY0IGJpbmFyeQ== +YmFzZTY0IGJpbmFyeQ== +abcdefghijkl \ No newline at end of file diff --git a/tests/cxx/hybrid/built-in/test.xml b/tests/cxx/hybrid/built-in/test.xml new file mode 100644 index 0000000..ae72e80 --- /dev/null +++ b/tests/cxx/hybrid/built-in/test.xml @@ -0,0 +1,24 @@ + + + + 123abc + + + + + 123 + 456 + 789 + 123 + + YmFzZTY0IGJpbmFyeQ== + YmFzZTY0IGJpbmFyeQ== + YmFzZTY0IGJpbmFyeQ== + YmFzZTY0IGJpbmFyeQ== + + abc + def + ghi + jkl + + diff --git a/tests/cxx/hybrid/built-in/test.xsd b/tests/cxx/hybrid/built-in/test.xsd new file mode 100644 index 0000000..1481d4f --- /dev/null +++ b/tests/cxx/hybrid/built-in/test.xsd @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/choice/driver.cxx b/tests/cxx/hybrid/choice/driver.cxx new file mode 100644 index 0000000..0ba13de --- /dev/null +++ b/tests/cxx/hybrid/choice/driver.cxx @@ -0,0 +1,70 @@ +// file : tests/cxx/hybrid/choice/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test choice mapping. +// + +#include +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + +#ifdef XSDE_STL + { + test1 x; + x.b ("foo"); + test1 y (x); + assert (y.b () == "foo"); + test1 z; + y.a (123); + z = y; + assert (z.a () == 123); + } +#endif + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/choice/makefile b/tests/cxx/hybrid/choice/makefile new file mode 100644 index 0000000..cd256ff --- /dev/null +++ b/tests/cxx/hybrid/choice/makefile @@ -0,0 +1,88 @@ +# file : tests/cxx/hybrid/choice/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 := test.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 +test := $(out_base)/.test +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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(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/tests/cxx/hybrid/choice/output b/tests/cxx/hybrid/choice/output new file mode 100644 index 0000000..b299e90 --- /dev/null +++ b/tests/cxx/hybrid/choice/output @@ -0,0 +1 @@ +123abcdef1.23123truefalseabc1.231231.231231.231234.564561.23true1.23true123truefalseabc1.23true1231.23truefalseabctrue1.23true1.23true123truefalseabc1.23true1231.23truefalseabctruetruetrue \ No newline at end of file diff --git a/tests/cxx/hybrid/choice/test.xml b/tests/cxx/hybrid/choice/test.xml new file mode 100644 index 0000000..48f06fd --- /dev/null +++ b/tests/cxx/hybrid/choice/test.xml @@ -0,0 +1,57 @@ + + + + + 123 + + abcdef + + 1.23123 + + truefalseabc + + + + 1.23123 + 1.23123 + 1.231234.56456 + + + + + 1.23 + true + 1.23 + true + + + 123 + truefalseabc + 1.23 + true + 1231.23 + truefalseabctrue + + + + + 1.23 + true + 1.23 + true + 123 + truefalseabc + 1.23 + true + 1231.23 + truefalseabctrue + + + + + true + true + + + diff --git a/tests/cxx/hybrid/choice/test.xsd b/tests/cxx/hybrid/choice/test.xsd new file mode 100644 index 0000000..9fe5f5c --- /dev/null +++ b/tests/cxx/hybrid/choice/test.xsd @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/compositor/includee.xsd b/tests/cxx/hybrid/compositor/includee.xsd new file mode 100644 index 0000000..1def761 --- /dev/null +++ b/tests/cxx/hybrid/compositor/includee.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/compositor/includer.xsd b/tests/cxx/hybrid/compositor/includer.xsd new file mode 100644 index 0000000..fc730e4 --- /dev/null +++ b/tests/cxx/hybrid/compositor/includer.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/compositor/test.xsd b/tests/cxx/hybrid/compositor/test.xsd new file mode 100644 index 0000000..3d1b1ce --- /dev/null +++ b/tests/cxx/hybrid/compositor/test.xsd @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/compositor/tmp.xsd b/tests/cxx/hybrid/compositor/tmp.xsd new file mode 100644 index 0000000..fc3a4bd --- /dev/null +++ b/tests/cxx/hybrid/compositor/tmp.xsd @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/file-per-type/a.xsd b/tests/cxx/hybrid/file-per-type/a.xsd new file mode 100644 index 0000000..9abe165 --- /dev/null +++ b/tests/cxx/hybrid/file-per-type/a.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/file-per-type/b.xsd b/tests/cxx/hybrid/file-per-type/b.xsd new file mode 100644 index 0000000..f10ad4c --- /dev/null +++ b/tests/cxx/hybrid/file-per-type/b.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/file-per-type/test.xsd b/tests/cxx/hybrid/file-per-type/test.xsd new file mode 100644 index 0000000..ebb2f23 --- /dev/null +++ b/tests/cxx/hybrid/file-per-type/test.xsd @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/cxx/hybrid/list/driver.cxx b/tests/cxx/hybrid/list/driver.cxx new file mode 100644 index 0000000..5d6b20e --- /dev/null +++ b/tests/cxx/hybrid/list/driver.cxx @@ -0,0 +1,56 @@ +// file : tests/cxx/hybrid/list/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test list mapping. +// + +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/list/makefile b/tests/cxx/hybrid/list/makefile new file mode 100644 index 0000000..5d70a97 --- /dev/null +++ b/tests/cxx/hybrid/list/makefile @@ -0,0 +1,88 @@ +# file : tests/cxx/hybrid/list/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 := test.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 +test := $(out_base)/.test +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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(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/tests/cxx/hybrid/list/output b/tests/cxx/hybrid/list/output new file mode 100644 index 0000000..6c1ac43 --- /dev/null +++ b/tests/cxx/hybrid/list/output @@ -0,0 +1 @@ +123 456 789one t:two threeabc def ghiabc def ghi \ No newline at end of file diff --git a/tests/cxx/hybrid/list/test.xml b/tests/cxx/hybrid/list/test.xml new file mode 100644 index 0000000..2451a4b --- /dev/null +++ b/tests/cxx/hybrid/list/test.xml @@ -0,0 +1,8 @@ + + + 123 456 789 + one t:two three + abc def ghi + abc def ghi + + diff --git a/tests/cxx/hybrid/list/test.xsd b/tests/cxx/hybrid/list/test.xsd new file mode 100644 index 0000000..d864b12 --- /dev/null +++ b/tests/cxx/hybrid/list/test.xsd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/makefile b/tests/cxx/hybrid/makefile new file mode 100644 index 0000000..3351241 --- /dev/null +++ b/tests/cxx/hybrid/makefile @@ -0,0 +1,29 @@ +# file : tests/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 + +tests := sequences + +ifeq ($(xsde_iostream),y) +tests += built-in list test-template union + +ifeq ($(xsde_parser_validation),y) +tests += choice +endif + +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/hybrid/reorder/test.xsd b/tests/cxx/hybrid/reorder/test.xsd new file mode 100644 index 0000000..1b610cc --- /dev/null +++ b/tests/cxx/hybrid/reorder/test.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/sequences/driver.cxx b/tests/cxx/hybrid/sequences/driver.cxx new file mode 100644 index 0000000..3d6c702 --- /dev/null +++ b/tests/cxx/hybrid/sequences/driver.cxx @@ -0,0 +1,442 @@ +// file : tests/cxx/hybrid/sequences/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test sequence templates. +// +#include +#include + +#include + +#ifndef XSDE_STL +#include +#endif + +#include + +using std::string; +using namespace xsde::cxx::hybrid; + +void data_destructor (void* p, size_t) +{ + delete static_cast (p); +} + +void data_destructor_pos (void* p, size_t i) +{ + switch (i) + { + case 0: + { + delete static_cast (p); + break; + } + case 1: + { + delete static_cast (p); + break; + } + } +} + +int +main () +{ + // + // pod_seq + // + typedef pod_seq pod; + + { + pod s; + s.push_back (111); + assert (s.size () == 1 && s[0] == 111); + s.pop_back (); + assert (s.size () == 0); + } + + { + pod s; + s.push_back (111); + s.erase (s.begin ()); + assert (s.size () == 0); + + s.push_back (111); + s.push_back (222); + s.push_back (333); + s.erase (s.begin ()); + assert (s.size () == 2 && s[0] == 222 && s[1] == 333); + + s.push_back (444); + s.erase (s.begin () + 1); + assert (s.size () == 2 && s[0] == 222 && s[1] == 444); + + s.push_back (555); + s.erase (s.begin () + 2); + assert (s.size () == 2 && s[0] == 222 && s[1] == 444); + } + + { + pod s; + s.reserve (2); + s.push_back (111); + s.push_back (222); + s.push_back (333); + assert (s.size () == 3 && s[0] == 111 && s[1] == 222 && s[2] == 333); + } + + { + pod s; + s.insert (s.begin (), 111); + assert (s.size () == 1 && s[0] == 111); + s.push_back (222); + s.push_back (333); + + s.insert (s.begin (), 444); + assert (s[0] == 444); + + s.insert (s.begin () + 1, 555); + assert (s[1] == 555); + + s.insert (s.end (), 666); + assert (s[5] == 666); + + assert (s[0] == 444 && s[1] == 555 && s[2] == 111 && + s[3] == 222 && s[4] == 333 && s[5] == 666); + } + + { + pod s; + s.reserve (2); + s.push_back (111); + s.push_back (222); + s.insert (s.begin () + 1, 333); + assert (s[0] == 111 && s[1] == 333 && s[2] == 222); + } + + // + // fix_seq + // + typedef fix_seq fix; + + { + fix s; + s.push_back ("aaa"); + assert (s.size () == 1 && s[0] == "aaa"); + s.pop_back (); + assert (s.size () == 0); + } + + { + fix s; + s.push_back ("aaa"); + s.erase (s.begin ()); + assert (s.size () == 0); + + s.push_back ("aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + s.erase (s.begin ()); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ccc"); + + s.push_back ("ddd"); + s.erase (s.begin () + 1); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + + s.push_back ("eee"); + s.erase (s.begin () + 2); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + } + + { + fix s; + s.reserve (2); + s.push_back ("aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + assert (s.size () == 3 && s[0] == "aaa" && + s[1] == "bbb" && s[2] == "ccc"); + } + + { + fix s; + s.insert (s.begin (), "aaa"); + assert (s.size () == 1 && s[0] == "aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + + s.insert (s.begin (), "ddd"); + assert (s[0] == "ddd"); + + s.insert (s.begin () + 1, "eee"); + assert (s[1] == "eee"); + + s.insert (s.end (), "fff"); + assert (s[5] == "fff"); + + assert (s[0] == "ddd" && s[1] == "eee" && s[2] == "aaa" && + s[3] == "bbb" && s[4] == "ccc" && s[5] == "fff"); + } + + { + fix s; + s.reserve (2); + s.push_back ("aaa"); + s.push_back ("bbb"); + s.insert (s.begin () + 1, "ccc"); + assert (s[0] == "aaa" && s[1] == "ccc" && s[2] == "bbb"); + } + + // + // var_seq + // + typedef var_seq var; + + { + var s; + s.push_back (new string ("aaa")); + assert (s.size () == 1 && s[0] == "aaa"); + s.pop_back (); + assert (s.size () == 0); + } + + { + var s; + s.push_back (new string ("aaa")); + s.erase (s.begin ()); + assert (s.size () == 0); + + s.push_back (new string ("aaa")); + s.push_back (new string ("bbb")); + s.push_back (new string ("ccc")); + s.erase (s.begin ()); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ccc"); + + s.push_back (new string ("ddd")); + s.erase (s.begin () + 1); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + + s.push_back (new string ("eee")); + s.erase (s.begin () + 2); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + } + + { + var s; + s.reserve (2); + s.push_back (new string ("aaa")); + s.push_back (new string ("bbb")); + s.push_back (new string ("ccc")); + assert (s.size () == 3 && s[0] == "aaa" && + s[1] == "bbb" && s[2] == "ccc"); + } + + { + var s; + s.insert (s.begin (), new string ("aaa")); + assert (s.size () == 1 && s[0] == "aaa"); + s.push_back (new string ("bbb")); + s.push_back (new string ("ccc")); + + s.insert (s.begin (), new string ("ddd")); + assert (s[0] == "ddd"); + + s.insert (s.begin () + 1, new string ("eee")); + assert (s[1] == "eee"); + + s.insert (s.end (), new string ("fff")); + assert (s[5] == "fff"); + + assert (s[0] == "ddd" && s[1] == "eee" && s[2] == "aaa" && + s[3] == "bbb" && s[4] == "ccc" && s[5] == "fff"); + } + + { + var s; + s.reserve (2); + s.push_back (new string ("aaa")); + s.push_back (new string ("bbb")); + s.insert (s.begin () + 1, new string ("ccc")); + assert (s[0] == "aaa" && s[1] == "ccc" && s[2] == "bbb"); + } + + // + // str_seq + // + typedef str_seq str; + +#ifndef XSDE_STL + using xsde::cxx::strdupx; + + { + str s; + s.push_back (strdupx ("aaa")); + assert (s.size () == 1 && s[0] == string ("aaa")); + s.pop_back (); + assert (s.size () == 0); + } + + { + str s; + s.push_back_copy ("aaa"); + s.erase (s.begin ()); + assert (s.size () == 0); + + s.push_back_copy ("aaa"); + s.push_back_copy ("bbb"); + s.push_back_copy ("ccc"); + s.erase (s.begin ()); + assert (s.size () == 2 && + s[0] == string ("bbb") && s[1] == string ("ccc")); + + s.push_back_copy ("ddd"); + s.erase (s.begin () + 1); + assert (s.size () == 2 && + s[0] == string ("bbb") && s[1] == string ("ddd")); + + s.push_back_copy ("eee"); + s.erase (s.begin () + 2); + assert (s.size () == 2 && + s[0] == string ("bbb") && s[1] == string ("ddd")); + } + + { + str s; + s.reserve (2); + s.push_back_copy ("aaa"); + s.push_back_copy ("bbb"); + s.push_back_copy ("ccc"); + assert (s.size () == 3 && + s[0] == string ("aaa") && + s[1] == string ("bbb") && + s[2] == string ("ccc")); + } + + { + str s; + s.insert (s.begin (), strdupx ("aaa")); + assert (s.size () == 1 && s[0] == string ("aaa")); + s.push_back_copy ("bbb"); + s.push_back_copy ("ccc"); + + s.insert (s.begin (), strdupx ("ddd")); + assert (s[0] == string ("ddd")); + + s.insert (s.begin () + 1, strdupx ("eee")); + assert (s[1] == string ("eee")); + + s.insert (s.end (), strdupx ("fff")); + assert (s[5] == string ("fff")); + + assert (s[0] == string ("ddd") && s[1] == string ("eee") && + s[2] == string ("aaa") && s[3] == string ("bbb") && + s[4] == string ("ccc") && s[5] == string ("fff")); + } + + { + str s; + s.reserve (2); + s.push_back_copy ("aaa"); + s.push_back_copy ("bbb"); + s.insert (s.begin () + 1, strdupx ("ccc")); + assert (s[0] == string ("aaa") && + s[1] == string ("ccc") && + s[2] == string ("bbb")); + } + +#else + + { + str s; + s.push_back ("aaa"); + assert (s.size () == 1 && s[0] == "aaa"); + s.pop_back (); + assert (s.size () == 0); + } + + { + str s; + s.push_back ("aaa"); + s.erase (s.begin ()); + assert (s.size () == 0); + + s.push_back ("aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + s.erase (s.begin ()); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ccc"); + + s.push_back ("ddd"); + s.erase (s.begin () + 1); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + + s.push_back ("eee"); + s.erase (s.begin () + 2); + assert (s.size () == 2 && s[0] == "bbb" && s[1] == "ddd"); + } + + { + str s; + s.reserve (2); + s.push_back ("aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + assert (s.size () == 3 && + s[0] == "aaa" && s[1] == "bbb" && s[2] == "ccc"); + } + + { + str s; + s.insert (s.begin (), "aaa"); + assert (s.size () == 1 && s[0] == "aaa"); + s.push_back ("bbb"); + s.push_back ("ccc"); + + s.insert (s.begin (), "ddd"); + assert (s[0] == "ddd"); + + s.insert (s.begin () + 1, "eee"); + assert (s[1] == "eee"); + + s.insert (s.end (), "fff"); + assert (s[5] == "fff"); + + assert (s[0] == "ddd" && s[1] == "eee" && s[2] == "aaa" && + s[3] == "bbb" && s[4] == "ccc" && s[5] == "fff"); + } + + { + str s; + s.reserve (2); + s.push_back ("aaa"); + s.push_back ("bbb"); + s.insert (s.begin () + 1, "ccc"); + assert (s[0] == "aaa" && s[1] == "ccc" && s[2] == "bbb"); + } +#endif + + // + // data_seq + // + typedef data_seq data; + + { + data s; + s.destructor (&data_destructor); + s.push_back (new string ("aaa")); + s.push_back (new string ("bbb")); + assert (*static_cast (s[0]) == "aaa" && + *static_cast (s[1]) == "bbb"); + } + + { + data s; + s.destructor (&data_destructor_pos); + s.push_back (new string ("aaa")); + s.push_back (new int (5)); + assert (*static_cast (s[0]) == "aaa" && + *static_cast (s[1]) == 5); + } +} diff --git a/tests/cxx/hybrid/sequences/makefile b/tests/cxx/hybrid/sequences/makefile new file mode 100644 index 0000000..41f5941 --- /dev/null +++ b/tests/cxx/hybrid/sequences/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/hybrid/sequences/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/hybrid/size/test.xsd b/tests/cxx/hybrid/size/test.xsd new file mode 100644 index 0000000..e8e265d --- /dev/null +++ b/tests/cxx/hybrid/size/test.xsd @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/test-template/driver.cxx b/tests/cxx/hybrid/test-template/driver.cxx new file mode 100644 index 0000000..c482a0c --- /dev/null +++ b/tests/cxx/hybrid/test-template/driver.cxx @@ -0,0 +1,56 @@ +// file : tests/cxx/hybrid/test-template/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Insert test description here. +// + +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/test-template/makefile b/tests/cxx/hybrid/test-template/makefile new file mode 100644 index 0000000..2a73ad9 --- /dev/null +++ b/tests/cxx/hybrid/test-template/makefile @@ -0,0 +1,88 @@ +# file : tests/cxx/hybrid/test-template/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 := test.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 +test := $(out_base)/.test +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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(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/tests/cxx/hybrid/test-template/output b/tests/cxx/hybrid/test-template/output new file mode 100644 index 0000000..66261f6 --- /dev/null +++ b/tests/cxx/hybrid/test-template/output @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/tests/cxx/hybrid/test-template/test.xml b/tests/cxx/hybrid/test-template/test.xml new file mode 100644 index 0000000..1b7571e --- /dev/null +++ b/tests/cxx/hybrid/test-template/test.xml @@ -0,0 +1,5 @@ + + + 123 + + diff --git a/tests/cxx/hybrid/test-template/test.xsd b/tests/cxx/hybrid/test-template/test.xsd new file mode 100644 index 0000000..e0a9be1 --- /dev/null +++ b/tests/cxx/hybrid/test-template/test.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/union/driver.cxx b/tests/cxx/hybrid/union/driver.cxx new file mode 100644 index 0000000..286bf14 --- /dev/null +++ b/tests/cxx/hybrid/union/driver.cxx @@ -0,0 +1,56 @@ +// file : tests/cxx/hybrid/union/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test union mapping. +// + +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/union/makefile b/tests/cxx/hybrid/union/makefile new file mode 100644 index 0000000..5c1289c --- /dev/null +++ b/tests/cxx/hybrid/union/makefile @@ -0,0 +1,88 @@ +# file : tests/cxx/hybrid/union/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 := test.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 +test := $(out_base)/.test +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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(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/tests/cxx/hybrid/union/output b/tests/cxx/hybrid/union/output new file mode 100644 index 0000000..9748083 --- /dev/null +++ b/tests/cxx/hybrid/union/output @@ -0,0 +1 @@ +123one \ No newline at end of file diff --git a/tests/cxx/hybrid/union/test.xml b/tests/cxx/hybrid/union/test.xml new file mode 100644 index 0000000..a2218b2 --- /dev/null +++ b/tests/cxx/hybrid/union/test.xml @@ -0,0 +1,6 @@ + + + 123 + one + + diff --git a/tests/cxx/hybrid/union/test.xsd b/tests/cxx/hybrid/union/test.xsd new file mode 100644 index 0000000..60a8d21 --- /dev/null +++ b/tests/cxx/hybrid/union/test.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/makefile b/tests/cxx/makefile new file mode 100644 index 0000000..447d7ec --- /dev/null +++ b/tests/cxx/makefile @@ -0,0 +1,24 @@ +# file : tests/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 + +tests := hybrid parser serializer string + +ifeq ($(xsde_polymorphic),y) +tests += hashmap +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/parser/built-in/driver.cxx b/tests/cxx/parser/built-in/driver.cxx new file mode 100644 index 0000000..adaea5a --- /dev/null +++ b/tests/cxx/parser/built-in/driver.cxx @@ -0,0 +1,661 @@ +// file : tests/cxx/parser/built-in/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test built-in type parsing. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +using xml_schema::ro_string; + +struct any_type_pimpl: xml_schema::any_type_pimpl +{ + virtual void + pre () + { + cout << "{" << endl; + } + + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (ro_string const&, ro_string const& n) +#else + _start_any_element (ro_string const&, ro_string const& n, const char*) +#endif + { + cout << " start any element '" << n << "'" << endl; + } + + virtual void + _end_any_element (ro_string const&, ro_string const& n) + { + cout << " end any element '" << n << "'" << endl; + } + + virtual void + _any_attribute (ro_string const&, + ro_string const& n, + ro_string const& v) + { + cout << " any attribute " << n << " = '" << v << "'" << endl; + } + + virtual void + _any_characters (ro_string const& s) + { + cout << " any text: '" << s << "'" << endl; + } + + virtual void + post_any_type () + { + cout << "}" << endl + << endl; + } +}; + +struct any_simple_type_pimpl: xml_schema::any_simple_type_pimpl +{ + virtual void + pre () + { + cout << "{" << endl; + } + + virtual void + _any_characters (ro_string const& s) + { + cout << " any text: '" << s << "'" << endl; + } + + virtual void + post_any_simple_type () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ + virtual void + boolean (bool v) + { + cout << v << endl; + } + + virtual void + byte (signed char v) + { + cout << short (v) << endl; + } + + virtual void + unsigned_byte (unsigned char v) + { + cout << (unsigned short) (v) << endl; + } + + virtual void + short_ (short v) + { + cout << v << endl; + } + + virtual void + unsigned_short (unsigned short v) + { + cout << v << endl; + } + + virtual void + int_ (int v) + { + cout << v << endl; + } + + virtual void + unsigned_int (unsigned int v) + { + cout << v << endl; + } + +#ifdef XSDE_LONGLONG + virtual void + long_ (long long v) + { + cout << v << endl; + } + + virtual void + unsigned_long (unsigned long long v) + { + cout << v << endl; + } +#else + virtual void + long_ (long v) + { + cout << v << endl; + } + + virtual void + unsigned_long (unsigned long v) + { + cout << v << endl; + } +#endif + + virtual void + integer (long v) + { + cout << v << endl; + } + + virtual void + negative_integer (long v) + { + cout << v << endl; + } + + + virtual void + non_positive_integer (long v) + { + cout << v << endl; + } + + + virtual void + positive_integer (unsigned long v) + { + cout << v << endl; + } + + virtual void + non_negative_integer (unsigned long v) + { + cout << v << endl; + } + + virtual void + float_ (float v) + { + cout << v << endl; + } + + virtual void + double_ (double v) + { + cout << v << endl; + } + + virtual void + decimal (double v) + { + cout << v << endl; + } + +#ifdef XSDE_STL + virtual void + string (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + normalized_string (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + token (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + name (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + nmtoken (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + nmtokens (xml_schema::string_sequence* s) + { + cout << "'"; + + for (xml_schema::string_sequence::const_iterator i (s->begin ()); + i != s->end (); ++i) + cout << *i << " "; + + cout << "'" << endl; + delete s; + } + + virtual void + ncname (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + id (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + idref (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + idrefs (xml_schema::string_sequence* s) + { + cout << "'"; + + for (xml_schema::string_sequence::const_iterator i (s->begin ()); + i != s->end (); ++i) + cout << *i << " "; + + cout << "'" << endl; + delete s; + } + + virtual void + language (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + uri (std::string const& v) + { + cout << "'" << v << "'" << endl; + } + + virtual void + qname (xml_schema::qname const& v) + { + cout << "'" << v.prefix () << ":" << v.name () << "'" << endl; + } + +#else // XSDE_STL + + virtual void + string (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + normalized_string (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + token (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + name (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + nmtoken (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + nmtokens (xml_schema::string_sequence* s) + { + cout << "'"; + + for (xml_schema::string_sequence::const_iterator i (s->begin ()); + i != s->end (); ++i) + cout << *i << " "; + + cout << "'" << endl; + delete s; + } + + virtual void + ncname (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + id (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + idref (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + idrefs (xml_schema::string_sequence* s) + { + cout << "'"; + + for (xml_schema::string_sequence::const_iterator i (s->begin ()); + i != s->end (); ++i) + cout << *i << " "; + + cout << "'" << endl; + delete s; + } + + virtual void + language (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + uri (char* v) + { + cout << "'" << v << "'" << endl; + delete[] v; + } + + virtual void + qname (xml_schema::qname* v) + { + cout << "'" << v->prefix () << ":" << v->name () << "'" << endl; + delete v; + } + +#endif // XSDE_STL + + + virtual void + base64_binary (xml_schema::buffer* v) + { + std::string tmp (v->data (), v->size ()); + cout << "'" << tmp << "'" << endl; + delete v; + } + + virtual void + hex_binary (xml_schema::buffer* v) + { + std::string tmp (v->data (), v->size ()); + cout << "'" << tmp << "'" << endl; + delete v; + } + + virtual void + gday (xml_schema::gday const& v) + { + cout << v.day (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + gmonth (xml_schema::gmonth const& v) + { + cout << v.month (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + gyear (xml_schema::gyear const& v) + { + cout << v.year (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + gmonth_day (xml_schema::gmonth_day const& v) + { + cout << v.month () << '-' << v.day (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + gyear_month (xml_schema::gyear_month const& v) + { + cout << v.year () << '-' << v.month (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + date (xml_schema::date const& v) + { + cout << v.year () << '-' << v.month () << '-' << v.day (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + time (xml_schema::time const& v) + { + cout << v.hours () << ':' << v.minutes () << ':' << v.seconds (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + date_time (xml_schema::date_time const& v) + { + cout << v.year () << '-' << v.month () << '-' << v.day () << 'T' + << v.hours () << ':' << v.minutes () << ':' << v.seconds (); + + if (v.zone_present ()) + cout << (v.zone_hours () < 0 ? "" : "+") << v.zone_hours () + << ':' << v.zone_minutes (); + + cout << endl; + } + + virtual void + duration (xml_schema::duration const& v) + { + cout << (v.negative () ? "-" : "") << 'P' + << v.years () << 'Y' + << v.months () << 'M' + << v.days () << 'D' + << 'T' + << v.hours () << 'H' + << v.minutes () << 'M' + << v.seconds () << 'S' + << endl; + } +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + any_type_pimpl any_type_p; + any_simple_type_pimpl any_simple_type_p; + + xml_schema::boolean_pimpl boolean_p; + + xml_schema::byte_pimpl byte_p; + xml_schema::unsigned_byte_pimpl unsigned_byte_p; + xml_schema::short_pimpl short_p; + xml_schema::unsigned_short_pimpl unsigned_short_p; + xml_schema::int_pimpl int_p; + xml_schema::unsigned_int_pimpl unsigned_int_p; + xml_schema::long_pimpl long_p; + xml_schema::unsigned_long_pimpl unsigned_long_p; + + xml_schema::integer_pimpl integer_p; + xml_schema::negative_integer_pimpl negative_integer_p; + xml_schema::non_positive_integer_pimpl non_positive_integer_p; + xml_schema::positive_integer_pimpl positive_integer_p; + xml_schema::non_negative_integer_pimpl non_negative_integer_p; + + xml_schema::float_pimpl float_p; + xml_schema::double_pimpl double_p; + xml_schema::decimal_pimpl decimal_p; + + xml_schema::string_pimpl string_p; + xml_schema::normalized_string_pimpl normalized_string_p; + xml_schema::token_pimpl token_p; + xml_schema::name_pimpl name_p; + xml_schema::nmtoken_pimpl nmtoken_p; + xml_schema::nmtokens_pimpl nmtokens_p; + xml_schema::ncname_pimpl ncname_p; + xml_schema::id_pimpl id_p; + xml_schema::idref_pimpl idref_p; + xml_schema::idrefs_pimpl idrefs_p; + + xml_schema::language_pimpl language_p; + xml_schema::uri_pimpl uri_p; + xml_schema::qname_pimpl qname_p; + + xml_schema::base64_binary_pimpl base64_binary_p; + xml_schema::hex_binary_pimpl hex_binary_p; + + xml_schema::gday_pimpl gday_p; + xml_schema::gmonth_pimpl gmonth_p; + xml_schema::gyear_pimpl gyear_p; + xml_schema::gmonth_day_pimpl gmonth_day_p; + xml_schema::gyear_month_pimpl gyear_month_p; + xml_schema::date_pimpl date_p; + xml_schema::time_pimpl time_p; + xml_schema::date_time_pimpl date_time_p; + xml_schema::duration_pimpl duration_p; + + type_pimpl type_p; + + type_p.parsers (any_type_p, + any_simple_type_p, + boolean_p, + byte_p, + unsigned_byte_p, + short_p, + unsigned_short_p, + int_p, + unsigned_int_p, + long_p, + unsigned_long_p, + integer_p, + negative_integer_p, + non_positive_integer_p, + positive_integer_p, + non_negative_integer_p, + float_p, + double_p, + decimal_p, + string_p, + normalized_string_p, + token_p, + name_p, + nmtoken_p, + nmtokens_p, + ncname_p, + id_p, + idref_p, + idrefs_p, + language_p, + uri_p, + qname_p, + base64_binary_p, + hex_binary_p, + gday_p, + gmonth_p, + gyear_p, + gmonth_day_p, + gyear_month_p, + date_p, + time_p, + date_time_p, + duration_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/built-in/makefile b/tests/cxx/parser/built-in/makefile new file mode 100644 index 0000000..9975660 --- /dev/null +++ b/tests/cxx/parser/built-in/makefile @@ -0,0 +1,79 @@ +# file : tests/cxx/parser/built-in/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) + +ifeq ($(xsde_longlong),y) +$(test): $(driver) $(src_base)/test-long-long.xml $(src_base)/output-long-long + $(call message,test $$1,$$1 $(src_base)/test-long-long.xml | diff -u $(src_base)/output-long-long -,$(driver)) +else +$(test): $(driver) $(src_base)/test-long.xml $(src_base)/output-long + $(call message,test $$1,$$1 $(src_base)/test-long.xml | diff -u $(src_base)/output-long -,$(driver)) +endif + +# 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/tests/cxx/parser/built-in/output-long b/tests/cxx/parser/built-in/output-long new file mode 100644 index 0000000..f3526bc --- /dev/null +++ b/tests/cxx/parser/built-in/output-long @@ -0,0 +1,167 @@ +{ + any attribute x = 'x' + any text: ' +' + any text: ' ' + start any element 'a' + any text: 'a' + end any element 'a' + any text: ' +' + any text: ' ' + start any element 'any-type' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any-type' + any text: ' +' + any text: ' ' +} + +{ + any text: '123abc' +} + +1 +0 +1 +0 +0 +127 +-128 +123 +0 +255 +123 +0 +32767 +-32768 +-12345 +0 +65535 +12345 +0 +2147483647 +-2147483648 +-1234567890 +0 +4294967295 +1234567890 +0 +2147483647 +-2147483648 +-1234567890 +0 +4294967295 +1234567890 +0 +2147483647 +-2147483648 +-1234567890 +-2147483648 +-1234567890 +0 +-2147483648 +-1234567890 +4294967295 +1234567890 +0 +4294967295 +1234567890 +0 +0 +-0 +inf +-inf +nan +123.567 +123.567 +-1.23567e+07 +-4.5e-06 +0 +0 +-0 +inf +-inf +nan +123.567 +123.567 +-1.23567e+07 +-4.5e-06 +0 +0 +-0 +123.567 +123.567 +-123.567 +'string space +newline + ' +' string space newline ' +'string space newline' +'as123:345-.abs' +'1as123:345-.abs' +'abc 123 ' +'as123_345-.abs' +'as123_345-.abs' +'abc' +'a123' +'as123_345-.abs' +'abc a123 ' +'x' +'en' +'en-us' +'one-two-three-four44-seven77-eight888' +'' +'relative' +'#id' +'http://www.example.com/foo#bar' +':schemaLocation' +'xsi:schemaLocation' +'12345abcjk' +'a' +'ab' +'abc' +'' +'12345abcjk' +12+12:0 +1 +31 +15+0:0 +15-14:0 +10+12:0 +1 +12+0:0 +2007+12:0 +1 +-20000+0:0 +10-28+12:0 +12-31 +1-1+0:0 +2007-12+12:0 +-2007-10 +20007-10+0:0 +-20007-1 +2007-12-26+12:0 +-2007-10-15 +20007-12-31+0:0 +-20007-1-1 +12:46:23.456+12:0 +12:13:14 +12:13:14+0:0 +2007-12-26T12:13:14.123+12:0 +-2007-10-15T12:13:14 +20007-12-31T12:13:14+0:0 +-20007-1-1T12:13:14 +-P2007Y13M32DT25H61M61.123S +P1Y0M0DT0H0M0S +P0Y1M0DT0H0M0S +P0Y0M1DT0H0M0S +P0Y0M0DT1H0M0S +P0Y0M0DT0H1M0S +P0Y0M0DT0H0M1.1S +P1Y0M0DT0H0M1S diff --git a/tests/cxx/parser/built-in/output-long-long b/tests/cxx/parser/built-in/output-long-long new file mode 100644 index 0000000..3b80787 --- /dev/null +++ b/tests/cxx/parser/built-in/output-long-long @@ -0,0 +1,167 @@ +{ + any attribute x = 'x' + any text: ' +' + any text: ' ' + start any element 'a' + any text: 'a' + end any element 'a' + any text: ' +' + any text: ' ' + start any element 'any-type' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any-type' + any text: ' +' + any text: ' ' +} + +{ + any text: '123abc' +} + +1 +0 +1 +0 +0 +127 +-128 +123 +0 +255 +123 +0 +32767 +-32768 +-12345 +0 +65535 +12345 +0 +2147483647 +-2147483648 +-1234567890 +0 +4294967295 +1234567890 +0 +9223372036854775807 +-9223372036854775808 +-1234567890123456789 +0 +18446744073709551615 +12345678901234567890 +0 +2147483647 +-2147483648 +-1234567890 +-2147483648 +-1234567890 +0 +-2147483648 +-1234567890 +4294967295 +1234567890 +0 +4294967295 +1234567890 +0 +0 +-0 +inf +-inf +nan +123.567 +123.567 +-1.23567e+07 +-4.5e-06 +0 +0 +-0 +inf +-inf +nan +123.567 +123.567 +-1.23567e+07 +-4.5e-06 +0 +0 +-0 +123.567 +123.567 +-123.567 +'string space +newline + ' +' string space newline ' +'string space newline' +'as123:345-.abs' +'1as123:345-.abs' +'abc 123 ' +'as123_345-.abs' +'as123_345-.abs' +'abc' +'a123' +'as123_345-.abs' +'abc a123 ' +'x' +'en' +'en-us' +'one-two-three-four44-seven77-eight888' +'' +'relative' +'#id' +'http://www.example.com/foo#bar' +':schemaLocation' +'xsi:schemaLocation' +'12345abcjk' +'a' +'ab' +'abc' +'' +'12345abcjk' +12+12:0 +1 +31 +15+0:0 +15-14:0 +10+12:0 +1 +12+0:0 +2007+12:0 +1 +-20000+0:0 +10-28+12:0 +12-31 +1-1+0:0 +2007-12+12:0 +-2007-10 +20007-10+0:0 +-20007-1 +2007-12-26+12:0 +-2007-10-15 +20007-12-31+0:0 +-20007-1-1 +12:46:23.456+12:0 +12:13:14 +12:13:14+0:0 +2007-12-26T12:13:14.123+12:0 +-2007-10-15T12:13:14 +20007-12-31T12:13:14+0:0 +-20007-1-1T12:13:14 +-P2007Y13M32DT25H61M61.123S +P1Y0M0DT0H0M0S +P0Y1M0DT0H0M0S +P0Y0M1DT0H0M0S +P0Y0M0DT1H0M0S +P0Y0M0DT0H1M0S +P0Y0M0DT0H0M1.1S +P1Y0M0DT0H0M1S diff --git a/tests/cxx/parser/built-in/test-long-long.xml b/tests/cxx/parser/built-in/test-long-long.xml new file mode 100644 index 0000000..8d9332a --- /dev/null +++ b/tests/cxx/parser/built-in/test-long-long.xml @@ -0,0 +1,199 @@ + + + + a + aaabbbccc + + + 123abc + + 1 + 0 + true + false + + 0 + +127 + -128 + 123 + + 0 + 255 + 123 + + 0 + +32767 + -32768 + -12345 + + 0 + 65535 + 12345 + + 0 + +2147483647 + -2147483648 + -1234567890 + + 0 + 4294967295 + 1234567890 + + 0 + +9223372036854775807 + -9223372036854775808 + -1234567890123456789 + + 0 + 18446744073709551615 + 12345678901234567890 + + 0 + +2147483647 + -02147483648 + -1234567890 + + -02147483648 + -1234567890 + + 0 + -02147483648 + -1234567890 + + 4294967295 + +01234567890 + + 0 + 4294967295 + +01234567890 + + 0 + +0 + -0 + INF + -INF + NaN + 123.567 + +123.567 + -123.567e5 + -.45E-5 + + 0 + +0 + -0 + INF + -INF + NaN + 123.567 + +123.567 + -123.567e5 + -.45E-5 + + 0 + +0 + -0 + 123.567 + +123.567 + -123.567 + + string space +newline + + + string space +newline + + + + string space +newline + + + + as123:345-.abs + + 1as123:345-.abs + + abc 123 + + as123_345-.abs + + as123_345-.abs + abc + a123 + + as123_345-.abs + + abc a123 + + x + en + en-us + one-two-three-four44-seven77-eight888 + + + relative + #id + http://www.example.com/foo#bar + + schemaLocation + xsi:schemaLocation + + MTIzND + VhYmNqaw = = + YQ== + YWI= + YWJj + + + 31323334356162636a6b + + ---12+12:00 + ---01 + ---31 + ---15Z + ---15-14:00 + + --10+12:00 + --01 + --12Z + + 2007+12:00 + 0001 + -20000Z + + --10-28+12:00 + --12-31 + --01-01Z + + 2007-12+12:00 + -2007-10 + 20007-10Z + -20007-01 + + 2007-12-26+12:00 + -2007-10-15 + 20007-12-31Z + -20007-01-01 + + + + + + 2007-12-26T12:13:14.123+12:00 + -2007-10-15T12:13:14 + 20007-12-31T12:13:14Z + -20007-01-01T12:13:14 + + -P2007Y13M32DT25H61M61.123S + P1Y + P1M + P1D + PT1H + PT1M + PT1.1S + P1YT1S + + diff --git a/tests/cxx/parser/built-in/test-long.xml b/tests/cxx/parser/built-in/test-long.xml new file mode 100644 index 0000000..380b0f4 --- /dev/null +++ b/tests/cxx/parser/built-in/test-long.xml @@ -0,0 +1,199 @@ + + + + a + aaabbbccc + + + 123abc + + 1 + 0 + true + false + + 0 + +127 + -128 + 123 + + 0 + 255 + 123 + + 0 + +32767 + -32768 + -12345 + + 0 + 65535 + 12345 + + 0 + +2147483647 + -2147483648 + -1234567890 + + 0 + 4294967295 + 1234567890 + + 0 + +2147483647 + -2147483648 + -1234567890 + + 0 + 4294967295 + 1234567890 + + 0 + +2147483647 + -02147483648 + -1234567890 + + -02147483648 + -1234567890 + + 0 + -02147483648 + -1234567890 + + 4294967295 + +01234567890 + + 0 + 4294967295 + +01234567890 + + 0 + +0 + -0 + INF + -INF + NaN + 123.567 + +123.567 + -123.567e5 + -.45E-5 + + 0 + +0 + -0 + INF + -INF + NaN + 123.567 + +123.567 + -123.567e5 + -.45E-5 + + 0 + +0 + -0 + 123.567 + +123.567 + -123.567 + + string space +newline + + + string space +newline + + + + string space +newline + + + + as123:345-.abs + + 1as123:345-.abs + + abc 123 + + as123_345-.abs + + as123_345-.abs + abc + a123 + + as123_345-.abs + + abc a123 + + x + en + en-us + one-two-three-four44-seven77-eight888 + + + relative + #id + http://www.example.com/foo#bar + + schemaLocation + xsi:schemaLocation + + MTIzND + VhYmNqaw = = + YQ== + YWI= + YWJj + + + 31323334356162636a6b + + ---12+12:00 + ---01 + ---31 + ---15Z + ---15-14:00 + + --10+12:00 + --01 + --12Z + + 2007+12:00 + 0001 + -20000Z + + --10-28+12:00 + --12-31 + --01-01Z + + 2007-12+12:00 + -2007-10 + 20007-10Z + -20007-01 + + 2007-12-26+12:00 + -2007-10-15 + 20007-12-31Z + -20007-01-01 + + + + + + 2007-12-26T12:13:14.123+12:00 + -2007-10-15T12:13:14 + 20007-12-31T12:13:14Z + -20007-01-01T12:13:14 + + -P2007Y13M32DT25H61M61.123S + P1Y + P1M + P1D + PT1H + PT1M + PT1.1S + P1YT1S + + diff --git a/tests/cxx/parser/built-in/test.xsd b/tests/cxx/parser/built-in/test.xsd new file mode 100644 index 0000000..9c00eb4 --- /dev/null +++ b/tests/cxx/parser/built-in/test.xsd @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/duplicate/makefile b/tests/cxx/parser/duplicate/makefile new file mode 100644 index 0000000..20b4a11 --- /dev/null +++ b/tests/cxx/parser/duplicate/makefile @@ -0,0 +1,79 @@ +# file : tests/cxx/parser/duplicate/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 := test.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) +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/duplicate/output b/tests/cxx/parser/duplicate/output new file mode 100644 index 0000000..f03814e --- /dev/null +++ b/tests/cxx/parser/duplicate/output @@ -0,0 +1,3 @@ +a: 1 +a: 2 +a: 3 diff --git a/tests/cxx/parser/duplicate/test.xml b/tests/cxx/parser/duplicate/test.xml new file mode 100644 index 0000000..62e4c0b --- /dev/null +++ b/tests/cxx/parser/duplicate/test.xml @@ -0,0 +1,9 @@ + + + 1 + 2 + 3 + + diff --git a/tests/cxx/parser/duplicate/test.xsd b/tests/cxx/parser/duplicate/test.xsd new file mode 100644 index 0000000..ebe1295 --- /dev/null +++ b/tests/cxx/parser/duplicate/test.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/enumeration/driver.cxx b/tests/cxx/parser/enumeration/driver.cxx new file mode 100644 index 0000000..e5440e1 --- /dev/null +++ b/tests/cxx/parser/enumeration/driver.cxx @@ -0,0 +1,99 @@ +// file : tests/cxx/parser/enumeration/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test xsd:enumeration parsing. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace xml_schema; + +namespace test +{ + struct digit_pimpl: digit_pskel + { + digit_pimpl () + : digit_pskel (&base_impl_) + { + } + + int_pimpl base_impl_; + }; + + struct gender_pimpl: gender_pskel + { + gender_pimpl () + : gender_pskel (&base_impl_) + { + } + + virtual ::gender + post_gender () + { + std::string str (post_string ()); + + if (str == "male") + return male; + else + return female; + } + + string_pimpl base_impl_; + }; + + struct type_pimpl: type_pskel + { + virtual void + digit (int i) + { + cout << i << endl; + } + + virtual void + gender (::gender g) + { + cout << g << endl; + } + }; +} + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + test::digit_pimpl digit_p; + test::gender_pimpl gender_p; + test::type_pimpl type_p; + + type_p.parsers (digit_p, gender_p); + + document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/enumeration/gender.hxx b/tests/cxx/parser/enumeration/gender.hxx new file mode 100644 index 0000000..be74b4a --- /dev/null +++ b/tests/cxx/parser/enumeration/gender.hxx @@ -0,0 +1,15 @@ +// file : tests/cxx/parser/enumeration/gender.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef GENDER_HXX +#define GENDER_HXX + +enum gender +{ + male, + female +}; + +#endif // GENDER_HXX diff --git a/tests/cxx/parser/enumeration/makefile b/tests/cxx/parser/enumeration/makefile new file mode 100644 index 0000000..ef898da --- /dev/null +++ b/tests/cxx/parser/enumeration/makefile @@ -0,0 +1,76 @@ +# file : tests/cxx/parser/enumeration/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 := test.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 +test := $(out_base)/.test +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)/test.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/test.map + +$(call include-dep,$(dep)) + + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/enumeration/output b/tests/cxx/parser/enumeration/output new file mode 100644 index 0000000..16db301 --- /dev/null +++ b/tests/cxx/parser/enumeration/output @@ -0,0 +1,3 @@ +1 +0 +1 diff --git a/tests/cxx/parser/enumeration/test.map b/tests/cxx/parser/enumeration/test.map new file mode 100644 index 0000000..f8868d6 --- /dev/null +++ b/tests/cxx/parser/enumeration/test.map @@ -0,0 +1,7 @@ +namespace test +{ + include "gender.hxx"; + + digit int int; + gender ::gender ::gender; +} diff --git a/tests/cxx/parser/enumeration/test.xml b/tests/cxx/parser/enumeration/test.xml new file mode 100644 index 0000000..a6fa893 --- /dev/null +++ b/tests/cxx/parser/enumeration/test.xml @@ -0,0 +1,10 @@ + + + 1 + + male + female + + diff --git a/tests/cxx/parser/enumeration/test.xsd b/tests/cxx/parser/enumeration/test.xsd new file mode 100644 index 0000000..ded3a18 --- /dev/null +++ b/tests/cxx/parser/enumeration/test.xsd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/error-handling/codes/driver.cxx b/tests/cxx/parser/error-handling/codes/driver.cxx new file mode 100644 index 0000000..8b3c693 --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/driver.cxx @@ -0,0 +1,276 @@ +// file : tests/cxx/parser/error-handling/codes/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test error reporting with error codes. +// + +#include +#include +#include +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct person_pimpl: person_pskel +{ + person_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (i_ == 4) + _app_error (4); + } + +#ifdef XSDE_STL + virtual void + id (string const&) + { + if (i_ == 5) + _app_error (5); + } +#else + virtual void + id (char* s) + { + delete[] s; + + if (i_ == 5) + _app_error (5); + } +#endif + + virtual void + age (int age) + { + if (i_ == 6) + _app_error (6); + + age_ = age; + } + + virtual int + post_person () + { + if (i_ == 7) + { + _app_error (7); + return 0; + } + + return age_; + } + +private: + int age_; + unsigned long i_; + +}; + + +struct type_pimpl: type_pskel +{ + type_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (i_ == 1) + _app_error (1); + } + + virtual void + person (int) + { + if (i_ == 2) + _app_error (2); + } + + virtual void + post_type () + { + if (i_ == 3) + _app_error (3); + } + +private: + unsigned long i_; +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // 0: xml error + // + // 1: app error from top-level pre + // 2: app error from top-level callback + // 3: app error from top-level post + // 4: app error from nested pre + // 5: app error from nested attribute callback + // 6: app error from nested element callback + // 7: app error from nested post + // + // 8: schema error (root element mismatch) + // 9: schema error (missing required element) + // 10: schema error (missing required attribute) + // 11: schema error (extraneous element) + // 12: schema error (extraneous attribute) + // 13: schema error (invalid datatype value) + // + // 14: io error (no such file) + // + // + for (unsigned long i (0); i < 15; ++i) + { + xml_schema::int_pimpl int_p; + xml_schema::string_pimpl string_p; + person_pimpl person_p (i); + type_pimpl type_p (i); + + person_p.parsers (string_p, int_p); + type_p.parsers (person_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + // + // + typedef xml_schema::parser_error error; + + type_p.pre (); + + if (error e = type_p._error ()) + { + assert (e.type () == error::app); + cout << "app: " << e.app_code () << endl; + continue; + } + + + if (i == 0) + { + istringstream is ("\n"); + doc_p.parse (is); + } + else if (i == 8) + { + istringstream is ("\n"); + doc_p.parse (is); + } + else if (i == 9) + { + istringstream is ( + "\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 10) + { + istringstream is ( + "\n" + "64\n" + ""); + doc_p.parse (is); + } + else if (i == 11) + { + istringstream is ( + "\n" + "\n" + "64\n" + "\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 12) + { + istringstream is ( + "\n" + "\n" + "64\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 13) + { + istringstream is ( + "\n" + "\n" + "a64\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 14) + { + doc_p.parse ("no-such-file.xml"); + } + else + doc_p.parse (argv[1]); + + + if (error e = doc_p._error ()) + { + switch (e.type ()) + { + case error::sys: + { + cout << "sys: " << e.sys_code () << ": " << e.sys_text () + << endl; + break; + } + case error::xml: + { + cout << "xml:" << e.line () << ":" << e.column () << ": " + << e.xml_code () << ": " << e.xml_text () << endl; + break; + } +#ifdef XSDE_PARSER_VALIDATION + case error::schema: + { + cout << "schema:" << e.line () << ":" << e.column () << ": " + << e.schema_code () << ": " << e.schema_text () << endl; + break; + } +#endif + case error::app: + { + cout << "app:" << e.line () << ":" << e.column () << ": " + << e.app_code () << endl; + break; + } + } + + continue; + } + + type_p.post_type (); + + if (error e = type_p._error ()) + { + assert (e.type () == error::app); + cout << "app: " << e.app_code () << endl; + continue; + } + } +} diff --git a/tests/cxx/parser/error-handling/codes/makefile b/tests/cxx/parser/error-handling/codes/makefile new file mode 100644 index 0000000..ca9ba5c --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/makefile @@ -0,0 +1,74 @@ +# file : tests/cxx/parser/error-handling/codes/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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 += --no-exceptions --type-map $(src_base)/test.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/test.map + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/error-handling/codes/output b/tests/cxx/parser/error-handling/codes/output new file mode 100644 index 0000000..bdf6520 --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/output @@ -0,0 +1,15 @@ +xml:2:2: 7: mismatched tag +app: 1 +app:7:11: 2 +app: 3 +app:5:19: 4 +app:5:19: 5 +app:6:17: 6 +app:7:11: 7 +schema:1:22: 4: unexpected element encountered +schema:2:16: 3: expected element not encountered +schema:2:30: 1: expected attribute not encountered +schema:4:6: 4: unexpected element encountered +schema:2:23: 2: unexpected attribute encountered +schema:3:14: 11: invalid int value +sys: 2: open failed diff --git a/tests/cxx/parser/error-handling/codes/test.map b/tests/cxx/parser/error-handling/codes/test.map new file mode 100644 index 0000000..5da7e3d --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/test.map @@ -0,0 +1,4 @@ +namespace test +{ + person int int; +} diff --git a/tests/cxx/parser/error-handling/codes/test.xml b/tests/cxx/parser/error-handling/codes/test.xml new file mode 100644 index 0000000..07def4b --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/test.xml @@ -0,0 +1,9 @@ + + + + 67 + + + diff --git a/tests/cxx/parser/error-handling/codes/test.xsd b/tests/cxx/parser/error-handling/codes/test.xsd new file mode 100644 index 0000000..6850342 --- /dev/null +++ b/tests/cxx/parser/error-handling/codes/test.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/error-handling/exceptions/driver.cxx b/tests/cxx/parser/error-handling/exceptions/driver.cxx new file mode 100644 index 0000000..0ad6b80 --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/driver.cxx @@ -0,0 +1,256 @@ +// file : tests/cxx/parser/error-handling/exceptions/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test error reporting with exceptions. +// + +#include +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct app +{ + app (unsigned long code) + : code_ (code) + { + } + + unsigned long + code () const + { + return code_; + } + +private: + unsigned long code_; +}; + +struct person_pimpl: person_pskel +{ + person_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (i_ == 4) + throw app (4); + } + +#ifdef XSDE_STL + virtual void + id (string const&) + { + if (i_ == 5) + throw app (5); + } +#else + virtual void + id (char* s) + { + delete[] s; + + if (i_ == 5) + throw app (5); + } +#endif + + virtual void + age (int age) + { + if (i_ == 6) + throw app (6); + + age_ = age; + } + + virtual int + post_person () + { + if (i_ == 7) + throw app (7); + + return age_; + } + +private: + int age_; + unsigned long i_; +}; + + +struct type_pimpl: type_pskel +{ + type_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (i_ == 1) + throw app (1); + } + + virtual void + person (int) + { + if (i_ == 2) + throw app (2); + } + + virtual void + post_type () + { + if (i_ == 3) + throw app (3); + } + +private: + unsigned long i_; +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // 0: xml error + // + // 1: app error from top-level pre + // 2: app error from top-level callback + // 3: app error from top-level post + // 4: app error from nested pre + // 5: app error from nested attribute callback + // 6: app error from nested element callback + // 7: app error from nested post + // + // 8: schema error (root element mismatch) + // 9: schema error (missing required element) + // 10: schema error (missing required attribute) + // 11: schema error (extraneous element) + // 12: schema error (extraneous attribute) + // 13: schema error (invalid datatype value) + // + // 14: io error (no such file) + // + // + for (unsigned long i (0); i < 15; ++i) + { + try + { + xml_schema::int_pimpl int_p; + xml_schema::string_pimpl string_p; + person_pimpl person_p (i); + type_pimpl type_p (i); + + person_p.parsers (string_p, int_p); + type_p.parsers (person_p); + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + // + // + type_p.pre (); + + if (i == 0) + { + istringstream is ("\n"); + doc_p.parse (is); + } + else if (i == 8) + { + istringstream is ("\n"); + doc_p.parse (is); + } + else if (i == 9) + { + istringstream is ( + "\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 10) + { + istringstream is ( + "\n" + "64\n" + ""); + doc_p.parse (is); + } + else if (i == 11) + { + istringstream is ( + "\n" + "\n" + "64\n" + "\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 12) + { + istringstream is ( + "\n" + "\n" + "64\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 13) + { + istringstream is ( + "\n" + "\n" + "a64\n" + "\n" + ""); + doc_p.parse (is); + } + else if (i == 14) + { + doc_p.parse ("no-such-file.xml"); + } + else + doc_p.parse (argv[1]); + + type_p.post_type (); + } + catch (ios_base::failure const&) + { + cout << "io: io error" << endl; + } + catch (xml_schema::parser_xml const& e) + { + cout << "xml:" << e.line () << ":" << e.column () << ": " + << e.code () << ": " << e.text () << endl; + } +#ifdef XSDE_PARSER_VALIDATION + catch (xml_schema::parser_schema const& e) + { + cout << "schema:" << e.line () << ":" << e.column () << ": " + << e.code () << ": " << e.text () << endl; + } +#endif + catch (app const& e) + { + cout << "app: " << e.code () << endl; + } + } +} diff --git a/tests/cxx/parser/error-handling/exceptions/makefile b/tests/cxx/parser/error-handling/exceptions/makefile new file mode 100644 index 0000000..8acb98a --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/makefile @@ -0,0 +1,75 @@ +# file : tests/cxx/parser/error-handling/exceptions/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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)/test.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/test.map + + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/error-handling/exceptions/output b/tests/cxx/parser/error-handling/exceptions/output new file mode 100644 index 0000000..b8046aa --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/output @@ -0,0 +1,15 @@ +xml:2:2: 7: mismatched tag +app: 1 +app: 2 +app: 3 +app: 4 +app: 5 +app: 6 +app: 7 +schema:1:22: 4: unexpected element encountered +schema:2:16: 3: expected element not encountered +schema:2:30: 1: expected attribute not encountered +schema:4:6: 4: unexpected element encountered +schema:2:23: 2: unexpected attribute encountered +schema:3:14: 11: invalid int value +io: io error diff --git a/tests/cxx/parser/error-handling/exceptions/test.map b/tests/cxx/parser/error-handling/exceptions/test.map new file mode 100644 index 0000000..5da7e3d --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/test.map @@ -0,0 +1,4 @@ +namespace test +{ + person int int; +} diff --git a/tests/cxx/parser/error-handling/exceptions/test.xml b/tests/cxx/parser/error-handling/exceptions/test.xml new file mode 100644 index 0000000..07def4b --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/test.xml @@ -0,0 +1,9 @@ + + + + 67 + + + diff --git a/tests/cxx/parser/error-handling/exceptions/test.xsd b/tests/cxx/parser/error-handling/exceptions/test.xsd new file mode 100644 index 0000000..6850342 --- /dev/null +++ b/tests/cxx/parser/error-handling/exceptions/test.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/error-handling/makefile b/tests/cxx/parser/error-handling/makefile new file mode 100644 index 0000000..e183785 --- /dev/null +++ b/tests/cxx/parser/error-handling/makefile @@ -0,0 +1,24 @@ +# file : tests/cxx/parser/error-handling/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 + +ifeq ($(xsde_exceptions),y) +tests := exceptions +else +tests := codes +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/parser/generated-impl/makefile b/tests/cxx/parser/generated-impl/makefile new file mode 100644 index 0000000..94cb8fc --- /dev/null +++ b/tests/cxx/parser/generated-impl/makefile @@ -0,0 +1,79 @@ +# file : tests/cxx/parser/generated-impl/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 := test.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) +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/generated-impl/output b/tests/cxx/parser/generated-impl/output new file mode 100644 index 0000000..7c58647 --- /dev/null +++ b/tests/cxx/parser/generated-impl/output @@ -0,0 +1,122 @@ +gender: male +foo: foo +gender: male +int: 0 +int: 1 +int: 2 +int: 3 +foo: foo +int: 3 +int: 2 +int: 1 +int: 0 +union: 9 +foo: foo +union: string +x: x +a: aaa +x: x +y: y +a: aaa +b: bbb +boolean: 1 +boolean: 0 +boolean: 1 +boolean: 0 +byte: 0 +byte: 123 +byte: -123 +unsigned-byte: 0 +unsigned-byte: 123 +short: 0 +short: -1234 +short: 1234 +unsigned-short: 0 +unsigned-short: 1234 +int: 0 +int: -12345 +int: 12345 +unsigned-int: 0 +unsigned-int: 12345 +long: 0 +long: -123456 +long: 123456 +unsigned-long: 0 +unsigned-long: 123456 +integer: 0 +integer: -123456 +integer: 123456 +negative-integer: -123456 +non-positive-integer: 0 +non-positive-integer: -123456 +positive-integer: 123456 +non-negative-integer: 0 +non-negative-integer: 123456 +float: 0 +float: 1.123 +float: -1.123 +double: 0 +double: 1.1234 +double: -1.1234 +decimal: 0 +decimal: 1.1234 +decimal: -1.1234 +string: string space newline +normalized-string: string space newline +token: string space newline +name: as123:345-.abs +nmtoken: 1as123:345-.abs +nmtokens: abc 123 +ncname: as123_345-.abs +id: abc +id: a123 +idref: abc +idrefs: abc a123 +language: en +language: en-us +uri: http://www.example.com/foo#bar +qname: schemaLocation +qname: xsi:schemaLocation +base64_binary: 10 bytes +base64_binary: 1 bytes +base64_binary: 2 bytes +base64_binary: 3 bytes +hex_binary: 0 bytes +hex_binary: 10 bytes +gday: ---12+12:0 +gday: ---1 +gday: ---31 +gday: ---15+0:0 +gday: ---15-14:0 +gmonth: --10+12:0 +gmonth: --1 +gmonth: --12+0:0 +gyear: 2007+12:0 +gyear: 1 +gyear: -20000+0:0 +gmonth_day: --10-28+12:0 +gmonth_day: --12-31 +gmonth_day: --1-1+0:0 +gyear_month: 2007-12+12:0 +gyear_month: -2007-10 +gyear_month: 20007-10+0:0 +gyear_month: -20007-1 +date: 2007-12-26+12:0 +date: -2007-10-15 +date: 20007-12-31+0:0 +date: -20007-1-1 +time: 12:46:23.456+12:0 +time: 12:13:14 +time: 12:13:14+0:0 +date_time: 2007-12-26T12:13:14.123+12:0 +date_time: -2007-10-15T12:13:14 +date_time: 20007-12-31T12:13:14+0:0 +date_time: -20007-1-1T12:13:14 +duration: -P2007Y13M32DT25H61M61.123S +duration: P1Y0M0DT0H0M0S +duration: P0Y1M0DT0H0M0S +duration: P0Y0M1DT0H0M0S +duration: P0Y0M0DT1H0M0S +duration: P0Y0M0DT0H1M0S +duration: P0Y0M0DT0H0M1.1S +duration: P1Y0M0DT0H0M1S diff --git a/tests/cxx/parser/generated-impl/test.xml b/tests/cxx/parser/generated-impl/test.xml new file mode 100644 index 0000000..2f29a39 --- /dev/null +++ b/tests/cxx/parser/generated-impl/test.xml @@ -0,0 +1,168 @@ + + + male + male + + 0 1 2 3 + 3 2 1 0 + + 9 + string + + + aaa + + + + aaa + bbb + + + aaabbbccc + abc123 + + 1 + 0 + true + false + + 0 + 123 + -123 + + 0 + 123 + + 0 + -1234 + 1234 + + 0 + 1234 + + 0 + -12345 + 12345 + + 0 + 12345 + + 0 + -123456 + 123456 + + 0 + 123456 + + 0 + -123456 + 123456 + + -123456 + + 0 + -123456 + + 123456 + + 0 + 123456 + + 0 + 1.123 + -1.123 + + 0 + 1.1234 + -1.1234 + + 0 + 1.1234 + -1.1234 + + string space newline + + string space newline + + string space newline + + as123:345-.abs + + 1as123:345-.abs + + abc 123 + + as123_345-.abs + + abc + a123 + + abc + + abc a123 + + en + en-us + + http://www.example.com/foo#bar + + schemaLocation + xsi:schemaLocation + + MTIzNDVhYmNqaw== + YQ== + YWI= + YWJj + + + 31323334356162636a6b + + ---12+12:00 + ---01 + ---31 + ---15Z + ---15-14:00 + + --10+12:00 + --01 + --12Z + + 2007+12:00 + 0001 + -20000Z + + --10-28+12:00 + --12-31 + --01-01Z + + 2007-12+12:00 + -2007-10 + 20007-10Z + -20007-01 + + 2007-12-26+12:00 + -2007-10-15 + 20007-12-31Z + -20007-01-01 + + + + + + 2007-12-26T12:13:14.123+12:00 + -2007-10-15T12:13:14 + 20007-12-31T12:13:14Z + -20007-01-01T12:13:14 + + -P2007Y13M32DT25H61M61.123S + P1Y + P1M + P1D + PT1H + PT1M + PT1.1S + P1YT1S + + diff --git a/tests/cxx/parser/generated-impl/test.xsd b/tests/cxx/parser/generated-impl/test.xsd new file mode 100644 index 0000000..7bc8f23 --- /dev/null +++ b/tests/cxx/parser/generated-impl/test.xsd @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/list/driver.cxx b/tests/cxx/parser/list/driver.cxx new file mode 100644 index 0000000..b920387 --- /dev/null +++ b/tests/cxx/parser/list/driver.cxx @@ -0,0 +1,127 @@ +// file : tests/cxx/parser/list/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test xsd:list parsing. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct string_list_pimpl: string_list_pskel +{ + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + item (string const& v) + { + cout << " '" << v << "'" << endl; + } +#else + virtual void + item (char* v) + { + cout << " '" << v << "'" << endl; + delete[] v; + } +#endif + + virtual void + post_string_list () + { + cout << "}" << endl + << endl; + } +}; + +struct string_list_lang_pimpl: string_list_lang_pskel +{ + string_list_lang_pimpl () + : string_list_lang_pskel (&base_impl_) + { + } + + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + lang (string const& v) + { + cout << " lang: '" << v << "'" << endl; + } +#else + virtual void + lang (char* v) + { + cout << " lang: '" << v << "'" << endl; + delete[] v; + } +#endif + + virtual void + post_string_list_lang () + { + cout << "}" << endl + << endl; + } + +private: + string_list_pimpl base_impl_; +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + string_list_pimpl string_list_p; + string_list_lang_pimpl string_list_lang_p; + type_pimpl type_p; + + string_list_p.parsers (string_p); + string_list_lang_p.parsers (string_p, string_p); + type_p.parsers (string_list_p, string_list_lang_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/list/makefile b/tests/cxx/parser/list/makefile new file mode 100644 index 0000000..d98b11f --- /dev/null +++ b/tests/cxx/parser/list/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/parser/list/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/list/output b/tests/cxx/parser/list/output new file mode 100644 index 0000000..3642c4d --- /dev/null +++ b/tests/cxx/parser/list/output @@ -0,0 +1,26 @@ +{ +} + +{ +} + +{ +} + +{ + 'one' +} + +{ + 'one' + 'two' + 'three' +} + +{ + lang: 'en' + 'one' + 'two' + 'three' +} + diff --git a/tests/cxx/parser/list/test.xml b/tests/cxx/parser/list/test.xml new file mode 100644 index 0000000..52229db --- /dev/null +++ b/tests/cxx/parser/list/test.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + one + + + one two + three + + + + one two + three + + + diff --git a/tests/cxx/parser/list/test.xsd b/tests/cxx/parser/list/test.xsd new file mode 100644 index 0000000..79bd084 --- /dev/null +++ b/tests/cxx/parser/list/test.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/makefile b/tests/cxx/parser/makefile new file mode 100644 index 0000000..94d6e45 --- /dev/null +++ b/tests/cxx/parser/makefile @@ -0,0 +1,57 @@ +# file : tests/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 + +tests := generated-impl duplicate + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) +tests += \ +built-in \ +recursive \ +test-template \ +union + +ifeq ($(xsde_reuse_style),tiein) +tests += \ +enumeration \ +list +endif + +endif # exceptions + +ifeq ($(xsde_polymorphic),y) +tests += polymorphism +endif + +tests += reset + +endif # iostream + + +ifeq ($(xsde_parser_validation),y) +tests += validation + +ifeq ($(xsde_iostream),y) +tests += error-handling + +ifeq ($(xsde_exceptions),y) +tests += name-clash/inheritance +endif +endif +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/parser/name-clash/inheritance/driver.cxx b/tests/cxx/parser/name-clash/inheritance/driver.cxx new file mode 100644 index 0000000..abe59b5 --- /dev/null +++ b/tests/cxx/parser/name-clash/inheritance/driver.cxx @@ -0,0 +1,87 @@ +// file : tests/cxx/parser/name-clash/inheritance/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test for name clashes across inheritance hierarchy. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct derived_pimpl: derived_pskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + derived_pimpl () + : derived_pskel (0) + { + } +#endif + +#ifdef XSDE_STL + virtual void + e (string const& v) + { + cout << "e: " << v << endl; + } + + virtual void + e1 (string const& v) + { + cout << "e1: " << v << endl; + } +#else + virtual void + e (char* v) + { + cout << "e: " << v << endl; + delete[] v; + } + + virtual void + e1 (char* v) + { + cout << "e1: " << v << endl; + delete[] v; + } +#endif +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + derived_pimpl derived_p; + + derived_p.parsers (string_p, string_p); + + xml_schema::document_pimpl doc_p (derived_p, "test", "root"); + + derived_p.pre (); + doc_p.parse (argv[1]); + derived_p.post_derived (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/name-clash/inheritance/makefile b/tests/cxx/parser/name-clash/inheritance/makefile new file mode 100644 index 0000000..0c12f20 --- /dev/null +++ b/tests/cxx/parser/name-clash/inheritance/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/parser/name-clash/inheritance/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/name-clash/inheritance/output b/tests/cxx/parser/name-clash/inheritance/output new file mode 100644 index 0000000..4efd51b --- /dev/null +++ b/tests/cxx/parser/name-clash/inheritance/output @@ -0,0 +1,2 @@ +e: e +e1: e1 diff --git a/tests/cxx/parser/name-clash/inheritance/test.xml b/tests/cxx/parser/name-clash/inheritance/test.xml new file mode 100644 index 0000000..8c17101 --- /dev/null +++ b/tests/cxx/parser/name-clash/inheritance/test.xml @@ -0,0 +1,8 @@ + + + e + e1 + + diff --git a/tests/cxx/parser/name-clash/inheritance/test.xsd b/tests/cxx/parser/name-clash/inheritance/test.xsd new file mode 100644 index 0000000..62a782e --- /dev/null +++ b/tests/cxx/parser/name-clash/inheritance/test.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/polymorphism/driver.cxx b/tests/cxx/parser/polymorphism/driver.cxx new file mode 100644 index 0000000..e9ef3f5 --- /dev/null +++ b/tests/cxx/parser/polymorphism/driver.cxx @@ -0,0 +1,124 @@ +// file : tests/cxx/parser/polymorphism/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test substitution groups and xsi:type support. +// +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct base_pimpl: base_pskel +{ + virtual void + a (int i) + { + cout << "a: " << i << endl; + } +}; + +struct interm_pimpl: interm_pskel +{ + interm_pimpl () + : interm_pskel (&base_impl_) + { + } + + virtual void + b (int i) + { + cout << "b: " << i << endl; + } + + base_pimpl base_impl_; +}; + +struct derived_pimpl: derived_pskel +{ + derived_pimpl () + : derived_pskel (&base_impl_) + { + } + + virtual void + c (int i) + { + cout << "c: " << i << endl; + } + + interm_pimpl base_impl_; +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + +#ifdef XSDE_EXCEPTIONS + try + { +#endif + xml_schema::int_pimpl int_p; + + base_pimpl base_p; + interm_pimpl interm_p; + derived_pimpl derived_p; + + xml_schema::parser_map_impl map (5); + type_pimpl type_p; + + base_p.parsers (int_p); + interm_p.parsers (int_p, int_p); + derived_p.parsers (int_p, int_p, int_p); + + map.insert (base_p); + map.insert (interm_p); + map.insert (derived_p); + + type_p.base_parser (map); + + xml_schema::document_pimpl doc_p (type_p, "test", "root", true); + + type_p.pre (); + doc_p.parse (argv[1]); + +#ifndef XSDE_EXCEPTIONS + if (doc_p._error ()) + { + cerr << "error" << endl; + return 1; + } +#endif + + type_p.post_type (); + + // Test parser resetting. + // + doc_p.reset (); + +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +#endif +} diff --git a/tests/cxx/parser/polymorphism/makefile b/tests/cxx/parser/polymorphism/makefile new file mode 100644 index 0000000..628ef02 --- /dev/null +++ b/tests/cxx/parser/polymorphism/makefile @@ -0,0 +1,73 @@ +# file : tests/cxx/parser/polymorphism/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/polymorphism/output b/tests/cxx/parser/polymorphism/output new file mode 100644 index 0000000..87168ca --- /dev/null +++ b/tests/cxx/parser/polymorphism/output @@ -0,0 +1,14 @@ +a: 1 +a: 1 +b: 2 +a: 1 +b: 2 +a: 1 +b: 2 +c: 3 +a: 1 +b: 2 +c: 3 +a: 1 +a: 1 +a: 1 diff --git a/tests/cxx/parser/polymorphism/test.xml b/tests/cxx/parser/polymorphism/test.xml new file mode 100644 index 0000000..8e635cc --- /dev/null +++ b/tests/cxx/parser/polymorphism/test.xml @@ -0,0 +1,19 @@ + + + 1 + + 12 + 12 + + 123 + 123 + + + + 1 + 1 + 1 + + diff --git a/tests/cxx/parser/polymorphism/test.xsd b/tests/cxx/parser/polymorphism/test.xsd new file mode 100644 index 0000000..80c5e06 --- /dev/null +++ b/tests/cxx/parser/polymorphism/test.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/recursive/driver.cxx b/tests/cxx/parser/recursive/driver.cxx new file mode 100644 index 0000000..9e17242 --- /dev/null +++ b/tests/cxx/parser/recursive/driver.cxx @@ -0,0 +1,172 @@ +// file : tests/cxx/parser/recursive/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test recursive parser invocation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; + +struct sub_pimpl: sub_type_pskel +{ + virtual void + pre () + { + cout << "sub::pre" << endl; + } + + virtual void + sub () + { + cout << "sub::sub" << endl; + } + + virtual void + sub2 () + { + cout << "sub::sub2" << endl; + } + +#ifdef XSDE_STL + virtual void + name (string const& n) + { + cout << "sub::name: " << n << endl; + } +#else + virtual void + name (char* n) + { + cout << "sub::name: " << n << endl; + delete[] n; + } +#endif + + virtual void + post_sub_type () + { + cout << "sub::post" << endl; + } +}; + +struct indir_pimpl: indir_type_pskel +{ + virtual void + pre () + { + cout << "indir::pre" << endl; + } + + virtual void + sub () + { + cout << "indir::sub" << endl; + } + +#ifdef XSDE_STL + virtual void + name (string const& n) + { + cout << "indir::name: " << n << endl; + } +#else + virtual void + name (char* n) + { + cout << "indir::name: " << n << endl; + delete[] n; + } +#endif + + virtual void + post_indir_type () + { + cout << "indir::post" << endl; + } +}; + +struct test_pimpl: test_type_pskel +{ + virtual void + pre () + { + cout << "test::pre" << endl; + } + + virtual void + sub () + { + cout << "test::sub" << endl; + } + +#ifdef XSDE_STL + virtual void + name (string const& n) + { + cout << "test::name: " << n << endl; + } +#else + virtual void + name (char* n) + { + cout << "test::name: " << n << endl; + delete[] n; + } +#endif + + virtual void + post_test_type () + { + cout << "test::post" << endl; + } +}; + + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + + sub_pimpl sub_p; + indir_pimpl indir_p; + test_pimpl test_p; + + sub_p.parsers (string_p, sub_p, indir_p, sub_p); + indir_p.parsers (string_p, sub_p); + test_p.parsers (string_p, sub_p); + + xml_schema::document_pimpl doc_p (test_p, "test"); + + test_p.pre (); + doc_p.parse (argv[1]); + test_p.post_test_type (); + + // Test parser resetting. + // + doc_p.reset (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/recursive/makefile b/tests/cxx/parser/recursive/makefile new file mode 100644 index 0000000..19ddfbd --- /dev/null +++ b/tests/cxx/parser/recursive/makefile @@ -0,0 +1,73 @@ +# file : tests/cxx/parser/recursive/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/recursive/output b/tests/cxx/parser/recursive/output new file mode 100644 index 0000000..f26fb72 --- /dev/null +++ b/tests/cxx/parser/recursive/output @@ -0,0 +1,22 @@ +test::pre +test::name: testName +sub::pre +sub::name: subName +sub::pre +sub::name: sub-subName +sub::post +sub::sub +indir::pre +indir::name: sub-indirName +sub::pre +sub::name: sub-indir-subName +sub::post +indir::sub +indir::post +sub::pre +sub::name: sub-sub2Name +sub::post +sub::sub2 +sub::post +test::sub +test::post diff --git a/tests/cxx/parser/recursive/test.xml b/tests/cxx/parser/recursive/test.xml new file mode 100644 index 0000000..f6c219d --- /dev/null +++ b/tests/cxx/parser/recursive/test.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/tests/cxx/parser/recursive/test.xsd b/tests/cxx/parser/recursive/test.xsd new file mode 100644 index 0000000..33e1d2d --- /dev/null +++ b/tests/cxx/parser/recursive/test.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/reset/driver.cxx b/tests/cxx/parser/reset/driver.cxx new file mode 100644 index 0000000..5701df5 --- /dev/null +++ b/tests/cxx/parser/reset/driver.cxx @@ -0,0 +1,300 @@ +// file : tests/cxx/parser/reset/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test parser resetting. +// + +#include + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +bool fail = true; + +struct error {}; + +#ifdef XSDE_REUSE_STYLE_MIXIN +struct base_pimpl: virtual base_pskel +#else +struct base_pimpl: base_pskel +#endif +{ + base_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { +#ifndef XSDE_EXCEPTIONS + assert (!_error ()); +#endif + + if (fail && i_ == 3) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: + unsigned long i_; +}; + +#ifdef XSDE_REUSE_STYLE_MIXIN +struct inner_pimpl: inner_pskel, base_pimpl +#else +struct inner_pimpl: inner_pskel +#endif +{ + inner_pimpl (unsigned long i) +#ifdef XSDE_REUSE_STYLE_MIXIN + : base_pimpl (i), i_ (i) +#else + : inner_pskel (&base_impl_), base_impl_ (i), i_ (i) +#endif + { + } + + virtual void + b (int v) + { + if (fail && i_ == 4) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + + if (!fail) + cout << i_ << ": " << v << endl; + } + + virtual void + post_inner () + { + if (fail && i_ == 5) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: +#ifdef XSDE_REUSE_STYLE_TIEIN + base_pimpl base_impl_; +#endif + unsigned long i_; +}; + +struct type_pimpl: type_pskel +{ + type_pimpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (fail && i_ == 0) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + + virtual void + a () + { + if (fail && i_ == 1) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + + virtual void + post_type () + { + if (fail && i_ == 2) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: + unsigned long i_; +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 4) + { + cerr << "usage: " << argv[0] << " pass.xml fail-xml.xml fail-schema.xml" + << endl; + return 1; + } + + const char* pass = argv[1]; + const char* fail_xml = argv[2]; + const char* fail_schema = argv[3]; + + try + { + for (unsigned long i (0); i < 8; ++i) + { +#ifndef XSDE_PARSER_VALIDATION + if (i == 7) + { + cout << "7: 1" << endl; + continue; + } +#endif + + xml_schema::int_pimpl int_p; + inner_pimpl inner_p (i); + type_pimpl type_p (i); + + inner_p.parsers (int_p); + type_p.parsers (inner_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + +#ifdef XSDE_EXCEPTIONS + try + { + fail = true; + + type_p.pre (); + + switch (i) + { + case 6: + { + doc_p.parse (fail_xml); + break; + } + case 7: + { + doc_p.parse (fail_schema); + break; + } + default: + { + doc_p.parse (pass); + break; + } + } + + type_p.post_type (); + assert (false); + } + catch (error const&) + { + } + catch (xml_schema::parser_exception const&) + { + } + + fail = false; + doc_p.reset (); + + type_p.pre (); + doc_p.parse (pass); + type_p.post_type (); +#else + do + { + fail = true; + + type_p.pre (); + + if (type_p._error ()) + break; + + switch (i) + { + case 6: + { + doc_p.parse (fail_xml); + break; + } + case 7: + { + doc_p.parse (fail_schema); + break; + } + default: + { + doc_p.parse (pass); + break; + } + } + + if (doc_p._error ()) + break; + + type_p.post_type (); + + if (type_p._error ()) + break; + + assert (false); + } + while (false); + + fail = false; + doc_p.reset (); + + type_p.pre (); + assert (!type_p._error ()); + + doc_p.parse (pass); + assert (!doc_p._error ()); + + type_p.post_type (); + assert (!type_p._error ()); +#endif + } + } +#ifdef XSDE_EXCEPTIONS + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } +#endif + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/reset/fail-schema.xml b/tests/cxx/parser/reset/fail-schema.xml new file mode 100644 index 0000000..92c6c8b --- /dev/null +++ b/tests/cxx/parser/reset/fail-schema.xml @@ -0,0 +1,8 @@ + + + 1 + 1 + + diff --git a/tests/cxx/parser/reset/fail-xml.xml b/tests/cxx/parser/reset/fail-xml.xml new file mode 100644 index 0000000..b2aacb2 --- /dev/null +++ b/tests/cxx/parser/reset/fail-xml.xml @@ -0,0 +1,7 @@ + + + 1 + + diff --git a/tests/cxx/parser/reset/makefile b/tests/cxx/parser/reset/makefile new file mode 100644 index 0000000..31dd3b4 --- /dev/null +++ b/tests/cxx/parser/reset/makefile @@ -0,0 +1,75 @@ +# file : tests/cxx/parser/reset/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/pass.xml $(src_base)/fail-xml.xml \ + $(src_base)/fail-schema.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/pass.xml \ +$(src_base)/fail-xml.xml $(src_base)/fail-schema.xml \ +| diff -u $(src_base)/output -,$(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/tests/cxx/parser/reset/output b/tests/cxx/parser/reset/output new file mode 100644 index 0000000..0e6cb1e --- /dev/null +++ b/tests/cxx/parser/reset/output @@ -0,0 +1,8 @@ +0: 1 +1: 1 +2: 1 +3: 1 +4: 1 +5: 1 +6: 1 +7: 1 diff --git a/tests/cxx/parser/reset/pass.xml b/tests/cxx/parser/reset/pass.xml new file mode 100644 index 0000000..956ec2a --- /dev/null +++ b/tests/cxx/parser/reset/pass.xml @@ -0,0 +1,7 @@ + + + 1 + + diff --git a/tests/cxx/parser/reset/test.xsd b/tests/cxx/parser/reset/test.xsd new file mode 100644 index 0000000..56ee5a4 --- /dev/null +++ b/tests/cxx/parser/reset/test.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/test-template/driver.cxx b/tests/cxx/parser/test-template/driver.cxx new file mode 100644 index 0000000..3b77569 --- /dev/null +++ b/tests/cxx/parser/test-template/driver.cxx @@ -0,0 +1,77 @@ +// file : tests/cxx/parser/test-template/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Insert test description here. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct type_pimpl: type_pskel +{ + virtual void + pre () + { + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << v << endl; + } +#else + virtual void + a (char* v) + { + cout << v << endl; + delete[] v; + } +#endif + + virtual void + post_type () + { + } +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + type_pimpl type_p; + + type_p.parsers (string_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/test-template/makefile b/tests/cxx/parser/test-template/makefile new file mode 100644 index 0000000..c618407 --- /dev/null +++ b/tests/cxx/parser/test-template/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/parser/test-template/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/test-template/output b/tests/cxx/parser/test-template/output new file mode 100644 index 0000000..7898192 --- /dev/null +++ b/tests/cxx/parser/test-template/output @@ -0,0 +1 @@ +a diff --git a/tests/cxx/parser/test-template/test.xml b/tests/cxx/parser/test-template/test.xml new file mode 100644 index 0000000..624a80c --- /dev/null +++ b/tests/cxx/parser/test-template/test.xml @@ -0,0 +1,7 @@ + + + a + + diff --git a/tests/cxx/parser/test-template/test.xsd b/tests/cxx/parser/test-template/test.xsd new file mode 100644 index 0000000..07bebc7 --- /dev/null +++ b/tests/cxx/parser/test-template/test.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/cxx/parser/union/driver.cxx b/tests/cxx/parser/union/driver.cxx new file mode 100644 index 0000000..d966c88 --- /dev/null +++ b/tests/cxx/parser/union/driver.cxx @@ -0,0 +1,62 @@ +// file : tests/cxx/parser/union/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test xsd:union parsing. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct int_string_union_pimpl: int_string_union_pskel +{ + virtual void + _characters (const xml_schema::ro_string& s) + { + cout << "'" << s << "'" << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + int_string_union_pimpl int_string_union_p; + type_pimpl type_p; + + type_p.parsers (int_string_union_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/union/makefile b/tests/cxx/parser/union/makefile new file mode 100644 index 0000000..46993f8 --- /dev/null +++ b/tests/cxx/parser/union/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/parser/union/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/union/output b/tests/cxx/parser/union/output new file mode 100644 index 0000000..b698505 --- /dev/null +++ b/tests/cxx/parser/union/output @@ -0,0 +1,3 @@ +' ' +'one' +'1' diff --git a/tests/cxx/parser/union/test.xml b/tests/cxx/parser/union/test.xml new file mode 100644 index 0000000..5b3e799 --- /dev/null +++ b/tests/cxx/parser/union/test.xml @@ -0,0 +1,10 @@ + + + + + one + 1 + + diff --git a/tests/cxx/parser/union/test.xsd b/tests/cxx/parser/union/test.xsd new file mode 100644 index 0000000..5bf3d47 --- /dev/null +++ b/tests/cxx/parser/union/test.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/all/driver.cxx b/tests/cxx/parser/validation/all/driver.cxx new file mode 100644 index 0000000..7498465 --- /dev/null +++ b/tests/cxx/parser/validation/all/driver.cxx @@ -0,0 +1,121 @@ +// file : tests/cxx/parser/validation/all/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the all compositor validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct all_pimpl: all_pskel +{ + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } + + virtual void + c (string const& v) + { + cout << " c = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } + + virtual void + c (char* v) + { + cout << " c = " << v << endl; + delete[] v; + } +#endif + + virtual void + post_all () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + all_pimpl all_p; + type_pimpl type_p; + + all_p.parsers (string_p, string_p, string_p); + type_p.parsers (all_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + try + { + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cout << " " << e.line () << ":" << e.column () << " " << e << endl + << "}" << endl + << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/all/makefile b/tests/cxx/parser/validation/all/makefile new file mode 100644 index 0000000..75990e2 --- /dev/null +++ b/tests/cxx/parser/validation/all/makefile @@ -0,0 +1,82 @@ +# file : tests/cxx/parser/validation/all/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 := test.xsd +cxx := driver.cxx + +tests := 000 001 002 003 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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/tests/cxx/parser/validation/all/test-000.std b/tests/cxx/parser/validation/all/test-000.std new file mode 100644 index 0000000..b4445f2 --- /dev/null +++ b/tests/cxx/parser/validation/all/test-000.std @@ -0,0 +1,46 @@ +{ + a = a + b = b + c = c +} + +{ + a = a + c = c + b = b +} + +{ + b = b + a = a + c = c +} + +{ + b = b + c = c + a = a +} + +{ + c = c + a = a + b = b +} + +{ + c = c + b = b + a = a +} + +{ + a = a + b = b +} + +{ + a = a + b = b +} + diff --git a/tests/cxx/parser/validation/all/test-000.xml b/tests/cxx/parser/validation/all/test-000.xml new file mode 100644 index 0000000..6e46fae --- /dev/null +++ b/tests/cxx/parser/validation/all/test-000.xml @@ -0,0 +1,53 @@ + + + + + a + b + c + + + + a + c + b + + + + b + a + c + + + + b + c + a + + + + c + a + b + + + + c + b + a + + + + + a + b + + + + a + b + + + diff --git a/tests/cxx/parser/validation/all/test-001.std b/tests/cxx/parser/validation/all/test-001.std new file mode 100644 index 0000000..921402a --- /dev/null +++ b/tests/cxx/parser/validation/all/test-001.std @@ -0,0 +1,6 @@ +{ + a = a + c = c + 9:8 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/all/test-001.xml b/tests/cxx/parser/validation/all/test-001.xml new file mode 100644 index 0000000..3df5600 --- /dev/null +++ b/tests/cxx/parser/validation/all/test-001.xml @@ -0,0 +1,11 @@ + + + + + a + c + + + diff --git a/tests/cxx/parser/validation/all/test-002.std b/tests/cxx/parser/validation/all/test-002.std new file mode 100644 index 0000000..55d65b3 --- /dev/null +++ b/tests/cxx/parser/validation/all/test-002.std @@ -0,0 +1,4 @@ +{ + 7:8 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/all/test-002.xml b/tests/cxx/parser/validation/all/test-002.xml new file mode 100644 index 0000000..aed0c0c --- /dev/null +++ b/tests/cxx/parser/validation/all/test-002.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/tests/cxx/parser/validation/all/test-003.std b/tests/cxx/parser/validation/all/test-003.std new file mode 100644 index 0000000..1d22181 --- /dev/null +++ b/tests/cxx/parser/validation/all/test-003.std @@ -0,0 +1,6 @@ +{ + a = a + b = b + 9:6 unexpected element encountered +} + diff --git a/tests/cxx/parser/validation/all/test-003.xml b/tests/cxx/parser/validation/all/test-003.xml new file mode 100644 index 0000000..b147cba --- /dev/null +++ b/tests/cxx/parser/validation/all/test-003.xml @@ -0,0 +1,12 @@ + + + + + a + b + a + + + diff --git a/tests/cxx/parser/validation/all/test.xsd b/tests/cxx/parser/validation/all/test.xsd new file mode 100644 index 0000000..1f670e3 --- /dev/null +++ b/tests/cxx/parser/validation/all/test.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/any/driver.cxx b/tests/cxx/parser/validation/any/driver.cxx new file mode 100644 index 0000000..827cbf8 --- /dev/null +++ b/tests/cxx/parser/validation/any/driver.cxx @@ -0,0 +1,139 @@ +// file : tests/cxx/parser/validation/any/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the any particle validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; +using xml_schema::ro_string; + +struct any_a_pimpl: any_a_pskel +{ + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + x (string const& v) + { + cout << " x = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + x (char* v) + { + cout << " x = " << v << endl; + delete[] v; + } +#endif + + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (ro_string const&, ro_string const& n) +#else + _start_any_element (ro_string const&, ro_string const& n, const char*) +#endif + { + cout << " start any element '" << n << "'" << endl; + } + + virtual void + _end_any_element (ro_string const&, ro_string const& n) + { + cout << " end any element '" << n << "'" << endl; + } + + virtual void + _any_attribute (ro_string const&, + ro_string const& n, + ro_string const& v) + { + cout << " any attribute " << n << " = '" << v << "'" << endl; + } + + virtual void + _any_characters (ro_string const& s) + { + cout << " any text: '" << s << "'" << endl; + } + + virtual void + post_any_a () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + any_a_pimpl any_a_p; + type_pimpl type_p; + + any_a_p.parsers (string_p, string_p); + type_p.parsers (any_a_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + try + { + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cout << " " << e.line () << ":" << e.column () << " " << e << endl + << "}" << endl + << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/any/makefile b/tests/cxx/parser/validation/any/makefile new file mode 100644 index 0000000..dfc1c21 --- /dev/null +++ b/tests/cxx/parser/validation/any/makefile @@ -0,0 +1,82 @@ +# file : tests/cxx/parser/validation/any/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 := test.xsd +cxx := driver.cxx + +tests := 000 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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) \ No newline at end of file diff --git a/tests/cxx/parser/validation/any/test-000.std b/tests/cxx/parser/validation/any/test-000.std new file mode 100644 index 0000000..a1cc6e3 --- /dev/null +++ b/tests/cxx/parser/validation/any/test-000.std @@ -0,0 +1,29 @@ +{ + start any element 'any' + end any element 'any' +} + +{ + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' +} + +{ + x = x + a = a + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' +} + diff --git a/tests/cxx/parser/validation/any/test-000.xml b/tests/cxx/parser/validation/any/test-000.xml new file mode 100644 index 0000000..f1a0c83 --- /dev/null +++ b/tests/cxx/parser/validation/any/test-000.xml @@ -0,0 +1,21 @@ + + + + + + + + + + aaabbbccc + + + + a + aaabbbccc + + + diff --git a/tests/cxx/parser/validation/any/test.xsd b/tests/cxx/parser/validation/any/test.xsd new file mode 100644 index 0000000..c05aeb5 --- /dev/null +++ b/tests/cxx/parser/validation/any/test.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/attribute/driver.cxx b/tests/cxx/parser/validation/attribute/driver.cxx new file mode 100644 index 0000000..935d2eb --- /dev/null +++ b/tests/cxx/parser/validation/attribute/driver.cxx @@ -0,0 +1,275 @@ +// file : tests/cxx/parser/validation/attribute/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test attribute and attribute wildcard (anyAttribute) validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; +using xml_schema::ro_string; + +struct pass_a_pimpl: pass_a_pskel +{ + virtual void + pre () + { + cout << "pass-a" << endl + << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } +#endif + + virtual void + _any_attribute (ro_string const& ns, + ro_string const& name, + ro_string const& value) + { + cout << " any: " << ns << "#" << name << " = " << value << endl; + } + + virtual void + post_pass_a () + { + cout << "}" << endl + << endl; + } +}; + +struct pass_b_pimpl: pass_b_pskel +{ + pass_b_pimpl () +#ifdef XSDE_REUSE_STYLE_TIEIN + : pass_b_pskel (0) +#endif + { + } + + virtual void + pre () + { + cout << "pass-b" << endl + << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } +#endif + + virtual void + _any_attribute (ro_string const& ns, + ro_string const& name, + ro_string const& value) + { + cout << " any: " << ns << "#" << name << " = " << value << endl; + } + + virtual void + post_pass_b () + { + cout << "}" << endl + << endl; + } +}; + +struct pass_c_pimpl: pass_c_pskel +{ + pass_c_pimpl () +#ifdef XSDE_REUSE_STYLE_TIEIN + : pass_c_pskel (0) +#endif + { + } + + virtual void + pre () + { + cout << "pass-c" << endl + << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } +#endif + + virtual void + post_pass_c () + { + cout << "}" << endl + << endl; + } +}; + +struct fail_pimpl: fail_pskel +{ + fail_pimpl () +#ifdef XSDE_REUSE_STYLE_TIEIN + : fail_pskel (0) +#endif + { + } + + virtual void + pre () + { + cout << "fail" << endl + << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } +#endif + + virtual void + post_fail () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + pass_a_pimpl pass_a_p; + pass_b_pimpl pass_b_p; + pass_c_pimpl pass_c_p; + fail_pimpl fail_p; + type_pimpl type_p; + + pass_a_p.parsers (string_p, string_p); + pass_b_p.parsers (string_p, string_p); + pass_c_p.parsers (string_p, string_p); + fail_p.parsers (string_p); + type_p.parsers (pass_a_p, pass_b_p, pass_c_p, fail_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + try + { + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cout << " " << e.line () << ":" << e.column () << " " << e << endl + << "}" << endl + << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/attribute/makefile b/tests/cxx/parser/validation/attribute/makefile new file mode 100644 index 0000000..d037791 --- /dev/null +++ b/tests/cxx/parser/validation/attribute/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/parser/validation/attribute/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -u $(src_base)/output -,$(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/tests/cxx/parser/validation/attribute/output b/tests/cxx/parser/validation/attribute/output new file mode 100644 index 0000000..990f995 --- /dev/null +++ b/tests/cxx/parser/validation/attribute/output @@ -0,0 +1,24 @@ +pass-a +{ + b = b + any: test#foo = foo + any: test#bar = bar +} + +pass-b +{ + a = a + b = b +} + +pass-c +{ + a = a + b = b +} + +fail +{ + 8:9 expected attribute not encountered +} + diff --git a/tests/cxx/parser/validation/attribute/test.xml b/tests/cxx/parser/validation/attribute/test.xml new file mode 100644 index 0000000..b994d1a --- /dev/null +++ b/tests/cxx/parser/validation/attribute/test.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/tests/cxx/parser/validation/attribute/test.xsd b/tests/cxx/parser/validation/attribute/test.xsd new file mode 100644 index 0000000..833eb8e --- /dev/null +++ b/tests/cxx/parser/validation/attribute/test.xsd @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/built-in/any-type/driver.cxx b/tests/cxx/parser/validation/built-in/any-type/driver.cxx new file mode 100644 index 0000000..6aadd78 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/any-type/driver.cxx @@ -0,0 +1,187 @@ +// file : tests/cxx/parser/validation/built-in/any-type/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the anyType and anySimpleType validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; +using xml_schema::ro_string; + +struct any_type_pimpl: xml_schema::any_type_pimpl +{ + virtual void + pre () + { + cout << "{" << endl; + } + + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (ro_string const&, ro_string const& n) +#else + _start_any_element (ro_string const&, ro_string const& n, const char*) +#endif + { + cout << " start any element '" << n << "'" << endl; + } + + virtual void + _end_any_element (ro_string const&, ro_string const& n) + { + cout << " end any element '" << n << "'" << endl; + } + + virtual void + _any_attribute (ro_string const&, + ro_string const& n, + ro_string const& v) + { + cout << " any attribute " << n << " = '" << v << "'" << endl; + } + + virtual void + _any_characters (ro_string const& s) + { + cout << " any text: '" << s << "'" << endl; + } + + virtual void + post_any_type () + { + cout << "}" << endl + << endl; + } +}; + +struct any_simple_type_pimpl: xml_schema::any_simple_type_pimpl +{ + virtual void + pre () + { + cout << "{" << endl; + } + + virtual void + _any_characters (ro_string const& s) + { + cout << " any text: '" << s << "'" << endl; + } + + virtual void + post_any_simple_type () + { + cout << "}" << endl + << endl; + } +}; + +struct any_extension_pimpl: any_extension_pskel +{ + any_extension_pimpl () + : any_extension_pskel (&base_impl_) + { + } + +#ifdef XSDE_STL + virtual void + x (const string& v) + { + cout << " x = " << v << endl; + } +#else + virtual void + x (char* v) + { + cout << " x = " << v << endl; + delete[] v; + } +#endif + +private: + any_type_pimpl base_impl_; +}; + +struct any_simple_extension_pimpl: any_simple_extension_pskel +{ + any_simple_extension_pimpl () + : any_simple_extension_pskel (&base_impl_) + { + } + +#ifdef XSDE_STL + virtual void + x (const string& v) + { + cout << " x = " << v << endl; + } +#else + virtual void + x (char* v) + { + cout << " x = " << v << endl; + delete[] v; + } +#endif + +private: + any_simple_type_pimpl base_impl_; +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + + any_type_pimpl any_type_p; + any_simple_type_pimpl any_simple_type_p; + + any_extension_pimpl any_extension_p; + any_simple_extension_pimpl any_simple_extension_p; + + type_pimpl type_p; + + any_extension_p.parsers (string_p); + any_simple_extension_p.parsers (string_p); + + type_p.parsers (any_simple_type_p, + any_type_p, + any_extension_p, + any_simple_extension_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/built-in/any-type/makefile b/tests/cxx/parser/validation/built-in/any-type/makefile new file mode 100644 index 0000000..951454e --- /dev/null +++ b/tests/cxx/parser/validation/built-in/any-type/makefile @@ -0,0 +1,82 @@ +# file : tests/cxx/parser/validation/built-in/any-type/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 := test.xsd +cxx := driver.cxx + +tests := 000 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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/tests/cxx/parser/validation/built-in/any-type/test-000.std b/tests/cxx/parser/validation/built-in/any-type/test-000.std new file mode 100644 index 0000000..9e263c0 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/any-type/test-000.std @@ -0,0 +1,113 @@ +{ + any text: '123abc' +} + +{ + any text: ' +' + any text: ' ' + start any element 'any' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + any text: ' +' + any text: ' ' + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + any attribute x = 'x' + any text: ' +' + any text: ' ' + start any element 'a' + any text: 'a' + end any element 'a' + any text: ' +' + any text: ' ' + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + any text: ' +' + any text: ' ' + start any element 'any' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + any text: ' +' + any text: ' ' + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + x = x + any text: ' +' + any text: ' ' + start any element 'a' + any text: 'a' + end any element 'a' + any text: ' +' + any text: ' ' + start any element 'any' + any attribute x = 'xxx' + any text: 'aaa' + start any element 'a' + any text: 'bbb' + end any element 'a' + any text: 'ccc' + end any element 'any' + any text: ' +' + any text: ' ' +} + +{ + x = x + any text: 'abc123' +} + diff --git a/tests/cxx/parser/validation/built-in/any-type/test-000.xml b/tests/cxx/parser/validation/built-in/any-type/test-000.xml new file mode 100644 index 0000000..7875b7e --- /dev/null +++ b/tests/cxx/parser/validation/built-in/any-type/test-000.xml @@ -0,0 +1,41 @@ + + + + + + + + + + aaabbbccc + + + + a + aaabbbccc + + + + + + + + + + aaabbbccc + + + + a + aaabbbccc + + + + + abc123 + + diff --git a/tests/cxx/parser/validation/built-in/any-type/test.xsd b/tests/cxx/parser/validation/built-in/any-type/test.xsd new file mode 100644 index 0000000..86a4e13 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/any-type/test.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/built-in/binary/driver.cxx b/tests/cxx/parser/validation/built-in/binary/driver.cxx new file mode 100644 index 0000000..23dbf45 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/binary/driver.cxx @@ -0,0 +1,176 @@ +// file : tests/cxx/parser/validation/built-in/binary/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in base64Binary and hexBinary types validation. +// +#include +#include // memcpy + +#include +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +bool +compare (buffer* x, const char* p, size_t n) +{ + buffer b; + b.size (n); + memcpy (b.data (), p, n); + + bool r = *x == b; + delete x; + return r; +} + +int +main () +{ + // Good. + // + + // hexBinary + // + { + context c (0); + hex_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + compare (p.post_hex_binary (), "", 0)); + } + + { + context c (0); + hex_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n313"); + p._characters ("23334356162636a6b "); + p._post (); + assert (!c.error_type () && + compare (p.post_hex_binary (), "12345abcjk", 10)); + } + + // base64Binary + // + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("MTIzND "); + p._characters ("VhYmNqaw = = "); + p._post (); + assert (!c.error_type () && + compare (p.post_base64_binary (), "12345abcjk", 10)); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("YQ=="); + p._post (); + assert (!c.error_type () && + compare (p.post_base64_binary (), "a", 1)); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("YWI="); + p._post (); + assert (!c.error_type () && + compare (p.post_base64_binary (), "ab", 2)); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("YWJj"); + p._post (); + assert (!c.error_type () && + compare (p.post_base64_binary (), "abc", 3)); + } + + // Bad + // + + // hexBinary + // + { + context c (0); + hex_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("313"); + p._post (); + assert (c.schema_error () == schema_error::invalid_hex_binary_value); + } + + { + context c (0); + hex_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("313233343X6162636a6b"); + p._post (); + assert (c.schema_error () == schema_error::invalid_hex_binary_value); + } + + // base64Binary + // + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_base64_binary_value); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("YQ"); + p._post (); + assert (c.schema_error () == schema_error::invalid_base64_binary_value); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("=="); + p._post (); + assert (c.schema_error () == schema_error::invalid_base64_binary_value); + } + + { + context c (0); + base64_binary_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("MTIzNDVhYmNqaw=A"); + p._post (); + assert (c.schema_error () == schema_error::invalid_base64_binary_value); + } +} diff --git a/tests/cxx/parser/validation/built-in/binary/makefile b/tests/cxx/parser/validation/built-in/binary/makefile new file mode 100644 index 0000000..5a07676 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/binary/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/binary/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/boolean/driver.cxx b/tests/cxx/parser/validation/built-in/boolean/driver.cxx new file mode 100644 index 0000000..7f08ed6 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/boolean/driver.cxx @@ -0,0 +1,150 @@ +// file : tests/cxx/parser/validation/built-in/boolean/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in boolean type validation. +// +#include + +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("true"); + p._post (); + assert (!c.error_type () && p.post_boolean ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1"); + p._post (); + assert (!c.error_type () && p.post_boolean ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("false"); + p._post (); + assert (!c.error_type () && !p.post_boolean ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && !p.post_boolean ()); + } + + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" true "); + p._post (); + assert (!c.error_type () && p.post_boolean ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" "); + p._characters (" \n "); + p._characters (" fa"); + p._characters ("l"); + p._characters ("se "); + p._characters (" \n "); + p._characters (" "); + p._post (); + assert (!c.error_type () && !p.post_boolean ()); + } + + // Bad + // + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + //p._characters (""); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (""); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" "); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" "); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("fal"); + p._characters ("s "); + p._characters ("e"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + boolean_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("01"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/boolean/makefile b/tests/cxx/parser/validation/built-in/boolean/makefile new file mode 100644 index 0000000..b844e00 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/boolean/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/boolean/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/byte/driver.cxx b/tests/cxx/parser/validation/built-in/byte/driver.cxx new file mode 100644 index 0000000..26f5a12 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/byte/driver.cxx @@ -0,0 +1,280 @@ +// file : tests/cxx/parser/validation/built-in/byte/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in byte and unsigned byte types validation. +// +#include + +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("123"); + p._post (); + assert (!c.error_type () && p.post_byte () == 123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("\t +123 \n "); + p._post (); + assert (!c.error_type () && p.post_byte () == 123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123"); + p._post (); + assert (!c.error_type () && p.post_byte () == -123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+123"); + p._post (); + assert (!c.error_type () && p.post_byte () == 123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0000000000000000123"); + p._post (); + assert (!c.error_type () && p.post_byte () == 123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+0000000000000000123"); + p._post (); + assert (!c.error_type () && p.post_byte () == 123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0000000000000000123"); + p._post (); + assert (!c.error_type () && p.post_byte () == -123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("\t \n"); + p._characters (" -"); + p._characters ("00000"); + p._characters ("001"); + p._characters ("23 \n\t"); + p._post (); + assert (!c.error_type () && p.post_byte () == -123); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-128"); + p._post (); + assert (!c.error_type () && p.post_byte () == -128); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("127"); + p._post (); + assert (!c.error_type () && p.post_byte () == 127); + } + + { + context c (0); + unsigned_byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+123"); + p._post (); + assert (!c.error_type () && p.post_unsigned_byte () == 123); + } + + { + context c (0); + unsigned_byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_unsigned_byte () == 0); + } + + { + context c (0); + unsigned_byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("255"); + p._post (); + assert (!c.error_type () && p.post_unsigned_byte () == 255); + } + + // Bad + // + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (""); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n \t "); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("++01"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--01"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-01"); + p._characters (" "); + p._characters ("23 "); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + unsigned_byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123"); + p._post (); + assert (c.schema_error ()); + } + + // Ranges + // + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-129"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("128"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + unsigned_byte_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("256"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/byte/makefile b/tests/cxx/parser/validation/built-in/byte/makefile new file mode 100644 index 0000000..855095f --- /dev/null +++ b/tests/cxx/parser/validation/built-in/byte/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/byte/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/date-time/driver.cxx b/tests/cxx/parser/validation/built-in/date-time/driver.cxx new file mode 100644 index 0000000..43b23f3 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/date-time/driver.cxx @@ -0,0 +1,1833 @@ +// file : tests/cxx/parser/validation/built-in/date-time/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in date and time types validation. +// +#include + +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + using xsde::cxx::time; + + // Good. + // + + // gday & time zone parsing + // + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("---1"); + p._characters ("2+12:00"); + p._post (); + assert (p.post_gday () == gday (12, 12, 0)); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---01"); + p._post (); + assert (p.post_gday () == gday (1)); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---31"); + p._post (); + assert (p.post_gday () == gday (31)); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---15Z"); + p._post (); + assert (p.post_gday () == gday (15, 0, 0)); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---15-14:00"); + p._post (); + assert (p.post_gday () == gday (15, -14, -0)); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---15-12:59"); + p._post (); + assert (p.post_gday () == gday (15, -12, -59)); + } + + // gmonth + // + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("--1"); + p._characters ("0+12:00"); + p._post (); + assert (p.post_gmonth () == gmonth (10, 12, 0)); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--01"); + p._post (); + assert (p.post_gmonth () == gmonth (1)); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12Z"); + p._post (); + assert (p.post_gmonth () == gmonth (12, 0, 0)); + } + + // gyear + // + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("20"); + p._characters ("07+12:00"); + p._post (); + assert (p.post_gyear () == gyear (2007, 12, 0)); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0001"); + p._post (); + assert (p.post_gyear () == gyear (1)); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-20000Z"); + p._post (); + assert (p.post_gyear () == gyear (-20000, 0, 0)); + } + + // gmonth_day + // + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("--1"); + p._characters ("0-28+12:00 "); + p._post (); + assert (p.post_gmonth_day () == gmonth_day (10, 28, 12, 00)); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12-31"); + p._post (); + assert (p.post_gmonth_day () == gmonth_day (12, 31)); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--01-01Z"); + p._post (); + assert (p.post_gmonth_day () == gmonth_day (1, 1, 0, 0)); + } + + // gyear_month + // + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("200"); + p._characters ("7-12+12:00 "); + p._post (); + assert (p.post_gyear_month () == gyear_month (2007, 12, 12, 0)); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2007-10"); + p._post (); + assert (p.post_gyear_month () == gyear_month (-2007, 10)); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20007-10Z"); + p._post (); + assert (p.post_gyear_month () == gyear_month (20007, 10, 0, 0)); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-20007-01"); + p._post (); + assert (p.post_gyear_month () == gyear_month (-20007, 1)); + } + + // date + // + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("200"); + p._characters ("7-12-26+12:00 "); + p._post (); + assert (p.post_date () == date (2007, 12, 26, 12, 0)); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2007-10-15"); + p._post (); + assert (p.post_date () == date (-2007, 10, 15)); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20007-12-31Z"); + p._post (); + assert (p.post_date () == date (20007, 12, 31, 0, 0)); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-20007-01-01"); + p._post (); + assert (p.post_date () == date (-20007, 1, 1)); + } + + // time + // + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("12:"); + p._characters ("46:23.456+12:00 "); + p._post (); + assert (p.post_time () == time (12, 46, 23.456, 12, 0)); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("12:13:14"); + p._post (); + assert (p.post_time () == time (12, 13, 14.0)); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("12:13:14Z"); + p._post (); + assert (p.post_time () == time (12, 13, 14.0, 0, 0)); + } + + // date_time + // + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("200"); + p._characters ("7-12-26T12:13:14.123+12:00 "); + p._post (); + assert (p.post_date_time () == + date_time (2007, 12, 26, 12, 13, 14.123, 12, 0)); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2007-10-15T12:13:14"); + p._post (); + assert (p.post_date_time () == date_time (-2007, 10, 15, 12, 13, 14.0)); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20007-12-31T12:13:14Z"); + p._post (); + assert (p.post_date_time () == + date_time (20007, 12, 31, 12, 13, 14.0, 0, 0)); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-20007-01-01T12:13:14"); + p._post (); + assert (p.post_date_time () == date_time (-20007, 1, 1, 12, 13, 14.0)); + } + + // duration + // + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \t\n "); + p._characters ("-P200"); + p._characters ("7Y13M32DT25H61M61.123S "); + p._post (); + assert (p.post_duration () == + duration (true, 2007, 13, 32, 25, 61, 61.123)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1Y"); + p._post (); + assert (p.post_duration () == duration (false, 1, 0, 0, 0, 0, 0.0)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1M"); + p._post (); + assert (p.post_duration () == duration (false, 0, 1, 0, 0, 0, 0.0)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1D"); + p._post (); + assert (p.post_duration () == duration (false, 0, 0, 1, 0, 0, 0.0)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT1H"); + p._post (); + assert (p.post_duration () == duration (false, 0, 0, 0, 1, 0, 0.0)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT1M"); + p._post (); + assert (p.post_duration () == duration (false, 0, 0, 0, 0, 1, 0.0)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT1.1S"); + p._post (); + assert (p.post_duration () == duration (false, 0, 0, 0, 0, 0, 1.1)); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1YT1S"); + p._post (); + assert (p.post_duration () == duration (false, 1, 0, 0, 0, 0, 1.0)); + } + + // Bad + // + + // gday & time zone parsing + // + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---1"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---32"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---2X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12asd"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---1212:00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12+2:00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12+1200"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12+15:00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12+12:60"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + context c (0); + gday_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("---12+14:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + // gmonth + // + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--13"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--1X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + context c (0); + gmonth_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--11+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + // gyear + // + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("207"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-207"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0000"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20X7"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + { + context c (0); + gyear_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + // gmonth_day + // + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-12-12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--1212"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12?12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--00-12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12-00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--13-23"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12-32"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--1X-12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--12-2X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + context c (0); + gmonth_day_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("--11-11+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + // gyear_month + // + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("207-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-207-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0000-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20X7-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007?12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-0"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-13"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-1X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + context c (0); + gyear_month_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + // date + // + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("207-01-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-207-01-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0000-01-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20X7-01-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007?01-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-0-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-00-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-13-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-1X-01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10?12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-0"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-32"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-2X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + context c (0); + date_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + // time + // + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1:01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2X:01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23?01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:0:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:60:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:4X:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10?12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10:"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10:0"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10:01."); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10:60"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:10:2X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("24:01:00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("24:00:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + context c (0); + time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:01:01+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + // date_time + // + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("207-01-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-207-01-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0000-01-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("20X7-01-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007?01-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-0-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-00-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-13-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-1X-01T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10?12T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-0T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-00T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-32T12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-10-2XT12:13:14"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T1:01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T2X:01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23?01:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:0:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:60:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:4X:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10?12"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10:"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10:0"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10:01."); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10:60"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T23:10:2X"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T24:01:00"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T24:00:01"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("23:01:01+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + context c (0); + date_time_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007-01-01T12:13:14+12:3o"); + p._post (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + // duration + // + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + // p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2007Y"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2007Y"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P-2007Y"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P-1M"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P-1D"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT-1H"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT-1M"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT-1.1S"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1H1M1S"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1M1Y"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT1S1H"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("PT1H1Y"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1Ygarbage"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } + + { + context c (0); + duration_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("P1YT"); + p._post (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } +} diff --git a/tests/cxx/parser/validation/built-in/date-time/makefile b/tests/cxx/parser/validation/built-in/date-time/makefile new file mode 100644 index 0000000..7e0b597 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/date-time/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/date-time/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/float/driver.cxx b/tests/cxx/parser/validation/built-in/float/driver.cxx new file mode 100644 index 0000000..852d158 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/float/driver.cxx @@ -0,0 +1,309 @@ +// file : tests/cxx/parser/validation/built-in/float/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in float, double, and decimal types validation. +// +#include +#include + +#include +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + + // float + // + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" 0000123.456 "); + p._post (); + assert (!c.error_type () && p.post_float () == 123.456F); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-12.345E2"); + p._post (); + assert (!c.error_type () && p.post_float () == -12.345E2F); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_float () == 0.0F); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0"); + p._post (); + assert (!c.error_type () && p.post_float () == -0.0F); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("INF"); + p._post (); + assert (!c.error_type () && isinf (p.post_float ())); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-INF"); + p._post (); + assert (!c.error_type () && isinf (p.post_float ())); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("NaN"); + p._post (); + assert (!c.error_type () && isnan (p.post_float ())); + } + + // double + // + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" 0000123.456789 "); + p._post (); + assert (!c.error_type () && p.post_double () == 123.456789); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-12.3456789E2"); + p._post (); + assert (!c.error_type () && p.post_double () == -12.3456789E2); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_double () == 0.0); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0"); + p._post (); + assert (!c.error_type () && p.post_double () == -0.0); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("INF"); + p._post (); + assert (!c.error_type () && isinf (p.post_double ())); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-INF"); + p._post (); + assert (!c.error_type () && isinf (p.post_double ())); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("NaN"); + p._post (); + assert (!c.error_type () && isnan (p.post_double ())); + } + + // decimal + // + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" 0000123.456789 "); + p._post (); + assert (!c.error_type () && p.post_decimal () == 123.456789); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123.45678912345"); + p._post (); + assert (!c.error_type () && p.post_decimal () == -123.45678912345); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_decimal () == 0.0); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0"); + p._post (); + assert (!c.error_type () && p.post_decimal () == -0.0); + } + + + // Bad + // + + // float + // + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+INF"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + float_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1.45 E2"); + p._post (); + assert (c.schema_error ()); + } + + // double + // + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+INF"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + double_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1.45 E2"); + p._post (); + assert (c.schema_error ()); + } + + // decimal + // + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("INF"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+INF"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-INF"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("NaN"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + decimal_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1.45 2"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/float/makefile b/tests/cxx/parser/validation/built-in/float/makefile new file mode 100644 index 0000000..0e5231e --- /dev/null +++ b/tests/cxx/parser/validation/built-in/float/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/float/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/int/driver.cxx b/tests/cxx/parser/validation/built-in/int/driver.cxx new file mode 100644 index 0000000..2395b04 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/int/driver.cxx @@ -0,0 +1,116 @@ +// file : tests/cxx/parser/validation/built-in/int/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in int and unsigned int types validation. +// +#include + +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + { + context c (0); + int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2147483648"); + p._post (); + assert (!c.error_type () && p.post_int () == -2147483648); + } + + { + context c (0); + int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_int () == 0); + } + + { + context c (0); + int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2147483647"); + p._post (); + assert (!c.error_type () && p.post_int () == 2147483647); + } + + { + context c (0); + unsigned_int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_unsigned_int () == 0); + } + + { + context c (0); + unsigned_int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("4294967295"); + p._post (); + assert (!c.error_type () && p.post_unsigned_int () == 4294967295); + } + + // Bad + // + + { + context c (0); + unsigned_int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123"); + p._post (); + assert (c.schema_error ()); + } + + + // Ranges + // + { + context c (0); + int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2147483649"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2147483648"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + unsigned_int_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("4294967296"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/int/makefile b/tests/cxx/parser/validation/built-in/int/makefile new file mode 100644 index 0000000..0fc4608 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/int/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/int/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/integer/driver.cxx b/tests/cxx/parser/validation/built-in/integer/driver.cxx new file mode 100644 index 0000000..9676046 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/integer/driver.cxx @@ -0,0 +1,317 @@ +// file : tests/cxx/parser/validation/built-in/int/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in integer & friends types validation. +// +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + + std::string min; + std::string max; + std::string umax; + + { + ostringstream ostr; + ostr << LONG_MIN; + min = ostr.str (); + } + + { + ostringstream ostr; + ostr << LONG_MAX; + max = ostr.str (); + } + + { + ostringstream ostr; + ostr << ULONG_MAX; + umax = ostr.str (); + } + + // integer + // + { + context c (0); + integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (min.c_str ()); + p._post (); + assert (!c.error_type () && p.post_integer () == LONG_MIN); + } + + { + context c (0); + integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_integer () == 0); + } + + { + context c (0); + integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (max.c_str ()); + p._post (); + assert (!c.error_type () && p.post_integer () == LONG_MAX); + } + + // negative_integer + // + { + context c (0); + negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (min.c_str ()); + p._post (); + assert (!c.error_type () && p.post_negative_integer () == LONG_MIN); + } + + { + context c (0); + negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-1"); + p._post (); + assert (!c.error_type () && p.post_negative_integer () == -1); + } + + // non_positive_integer + // + { + context c (0); + non_positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (min.c_str ()); + p._post (); + assert (!c.error_type () && p.post_non_positive_integer () == LONG_MIN); + } + + { + context c (0); + non_positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+0"); + p._post (); + assert (!c.error_type () && p.post_non_positive_integer () == 0); + } + + // positive_integer + // + { + context c (0); + positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1"); + p._post (); + assert (!c.error_type () && p.post_positive_integer () == 1); + } + + { + context c (0); + positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (umax.c_str ()); + p._post (); + assert (!c.error_type () && p.post_positive_integer () == ULONG_MAX); + } + + // non_negative_integer + // + { + context c (0); + non_negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0"); + p._post (); + assert (!c.error_type () && p.post_non_negative_integer () == 0); + } + + { + context c (0); + non_negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (umax.c_str ()); + p._post (); + assert (!c.error_type () && p.post_non_negative_integer () == ULONG_MAX); + } + + + // Bad + // + + std::string past_min (min); + std::string past_max (max); + std::string past_umax (umax); + + assert (*past_min.rbegin () != '9'); + assert (*past_max.rbegin () != '9'); + assert (*past_umax.rbegin () != '9'); + + (*past_min.rbegin ())++; + (*past_max.rbegin ())++; + (*past_umax.rbegin ())++; + + // integer + // + { + context c (0); + integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_min.c_str ()); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_max.c_str ()); + p._post (); + assert (c.schema_error ()); + } + + // negative_integer + // + { + context c (0); + negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_min.c_str ()); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-0"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1"); + p._post (); + assert (c.schema_error ()); + } + + // non_positive_integer + // + { + context c (0); + non_positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_min.c_str ()); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + non_positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1"); + p._post (); + assert (c.schema_error ()); + } + + // positive_integer + // + { + context c (0); + positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-1"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("+0"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + positive_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_umax.c_str ()); + p._post (); + assert (c.schema_error ()); + } + + // non_negative_integer + // + { + context c (0); + non_negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-1"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + non_negative_integer_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (past_umax.c_str ()); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/integer/makefile b/tests/cxx/parser/validation/built-in/integer/makefile new file mode 100644 index 0000000..8e5fa68 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/integer/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/integer/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/long-long/driver.cxx b/tests/cxx/parser/validation/built-in/long-long/driver.cxx new file mode 100644 index 0000000..3ddf6d9 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/long-long/driver.cxx @@ -0,0 +1,118 @@ +// file : tests/cxx/parser/validation/built-in/long-long/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in long and unsigned long types validation. +// +#include + +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-9223372036854775808"); + p._post (); + assert (!c.error_type () && + p.post_long () == (-9223372036854775807LL - 1)); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_long () == 0); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("9223372036854775807"); + p._post (); + assert (!c.error_type () && p.post_long () == 9223372036854775807LL); + } + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_unsigned_long () == 0); + } + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("18446744073709551615"); + p._post (); + assert (!c.error_type () && + p.post_unsigned_long () == 18446744073709551615ULL); + } + + // Bad + // + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123"); + p._post (); + assert (c.schema_error ()); + } + + + // Ranges + // + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-9223372036854775809"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("9223372036854775808"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("18446744073709551616"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/long-long/makefile b/tests/cxx/parser/validation/built-in/long-long/makefile new file mode 100644 index 0000000..948c89a --- /dev/null +++ b/tests/cxx/parser/validation/built-in/long-long/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/long-long/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/long/driver.cxx b/tests/cxx/parser/validation/built-in/long/driver.cxx new file mode 100644 index 0000000..0312b3b --- /dev/null +++ b/tests/cxx/parser/validation/built-in/long/driver.cxx @@ -0,0 +1,106 @@ +// file : tests/cxx/parser/validation/built-in/long/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test built-in long and unsigned long types validation (32 bit fall-back). +// +#include + +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main (int argc, char* argv[]) +{ + // Good. + // + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2147483648"); + p._post (); + assert (!c.error_type () && p.post_long () == -2147483648); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_long () == 0); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2147483647"); + p._post (); + assert (!c.error_type () && p.post_long () == 2147483647); + } + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_unsigned_long () == 0); + } + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("4294967295"); + p._post (); + assert (!c.error_type () && p.post_unsigned_long () == 4294967295); + } + + // Bad + // + + { + context c (0); + unsigned_long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-123"); + p._post (); + assert (c.schema_error ()); + } + + + // Ranges + // + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-2147483649"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + long_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("2147483648"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/long/makefile b/tests/cxx/parser/validation/built-in/long/makefile new file mode 100644 index 0000000..e050feb --- /dev/null +++ b/tests/cxx/parser/validation/built-in/long/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/long/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/makefile b/tests/cxx/parser/validation/built-in/makefile new file mode 100644 index 0000000..0e6b3aa --- /dev/null +++ b/tests/cxx/parser/validation/built-in/makefile @@ -0,0 +1,35 @@ +# file : tests/cxx/parser/validation/built-in/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 + +tests := binary boolean byte date-time float int integer qname short \ +string uri + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) +ifeq ($(xsde_reuse_style),tiein) +tests += any-type +endif +endif +endif + +ifeq ($(xsde_longlong),y) +tests += long-long +else +tests += long +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/parser/validation/built-in/qname/driver.cxx b/tests/cxx/parser/validation/built-in/qname/driver.cxx new file mode 100644 index 0000000..f3acc6b --- /dev/null +++ b/tests/cxx/parser/validation/built-in/qname/driver.cxx @@ -0,0 +1,132 @@ +// file : tests/cxx/parser/validation/built-in/qname/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in QName type validation. +// +#include + +#include + +// Let the runtime header sort out which version (stl/no-stl) to +// include. +// +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +#ifdef XSDE_STL +bool +compare (const qname& x, const char* p, const char* n) +{ + return x == qname (p, n); +} +#else +bool +compare (qname* x, const char* p, const char* n) +{ + qname y; + y.prefix_copy (p); + y.name_copy (n); + + bool r = *x == y; + delete x; + return r; +} +#endif + +int +main () +{ + // Good. + // + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" xsi"); + p._characters (":"); + p._characters ("schemaLocation"); + p._post (); + assert (!c.error_type () && + compare (p.post_qname (), "xsi", "schemaLocation")); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("schemaLocation"); + p._post (); + assert (!c.error_type () && + compare (p.post_qname (), "", "schemaLocation")); + } + + + // Bad + // + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + //p._characters (""); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (":"); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("xsi:"); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (":schemaLocation"); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("x?i:schemaLocation"); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + context c (0); + qname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("xsi:schema Location"); + p._post (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } +} diff --git a/tests/cxx/parser/validation/built-in/qname/makefile b/tests/cxx/parser/validation/built-in/qname/makefile new file mode 100644 index 0000000..eed5151 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/qname/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/qname/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/short/driver.cxx b/tests/cxx/parser/validation/built-in/short/driver.cxx new file mode 100644 index 0000000..6822f61 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/short/driver.cxx @@ -0,0 +1,116 @@ +// file : tests/cxx/parser/validation/built-in/short/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in short and unsigned short types validation. +// +#include + +#include +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + // Good. + // + { + context c (0); + short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-32768"); + p._post (); + assert (!c.error_type () && p.post_short () == -32768); + } + + { + context c (0); + short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_short () == 0); + } + + { + context c (0); + short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("32767"); + p._post (); + assert (!c.error_type () && p.post_short () == 32767); + } + + { + context c (0); + unsigned_short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("0"); + p._post (); + assert (!c.error_type () && p.post_unsigned_short () == 0); + } + + { + context c (0); + unsigned_short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("65535"); + p._post (); + assert (!c.error_type () && p.post_unsigned_short () == 65535); + } + + // Bad + // + + { + context c (0); + unsigned_short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-1234"); + p._post (); + assert (c.schema_error ()); + } + + + // Ranges + // + { + context c (0); + short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-32769"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("32768"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + unsigned_short_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("65536"); + p._post (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/parser/validation/built-in/short/makefile b/tests/cxx/parser/validation/built-in/short/makefile new file mode 100644 index 0000000..d82fc91 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/short/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/short/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/string/driver.cxx b/tests/cxx/parser/validation/built-in/string/driver.cxx new file mode 100644 index 0000000..06a4708 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/string/driver.cxx @@ -0,0 +1,613 @@ +// file : tests/cxx/parser/validation/built-in/string/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in string & friends types validation. +// +#include +#include + +#include + +// Let the runtime header sort out which version (stl/no-stl) to +// include. +// +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +bool +compare (const string_sequence* x, const string_sequence& y) +{ + bool r = *x == y; + delete x; + return r; +} + +int +main () +{ + // We are going to leak a bit of memory in the no-STL case. + // + using std::string; + + // Good. + // + + // string + // + { + context c (0); + string_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" aaa "); + p._characters ("bbb"); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_string () == string (" \n\t aaa bbb ")); + } + + // normalized_string + // + { + context c (0); + normalized_string_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" aaa \n\t "); + p._characters (" bbb"); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_normalized_string () == string (" aaa bbb ")); + } + + // token + // + { + context c (0); + token_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" aaa \n\t "); + p._characters (" bbb \n\t"); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_token () == string ("aaa bbb")); + } + + // name + // + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" a:b-c_d123 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_name () == string ("a:b-c_d123")); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" _12 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_name () == string ("_12")); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" :12 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_name () == string (":12")); + } + + // nmtoken + // + { + context c (0); + nmtoken_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" 123a:b-c_d123 "); + p._characters (" \n\t"); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_nmtoken () == string ("123a:b-c_d123")); + } + + // nmtokens + // + { + context c (0); + string_sequence s; +#ifdef XSDE_STL + s.push_back ("123"); + s.push_back ("abc"); +#else + s.push_back_copy ("123"); + s.push_back_copy ("abc"); +#endif + + nmtokens_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" 123 "); + p._characters (" \n\t abc "); + p._characters (" "); + p._post (); + assert (!c.error_type () && compare (p.post_nmtokens (), s)); + } + + // ncname + // + { + context c (0); + ncname_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" a.b-c_d123 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_ncname () == string ("a.b-c_d123")); + } + + // id + // + { + context c (0); + id_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" a.b-c_d123 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_id () == string ("a.b-c_d123")); + } + + // idref + // + { + context c (0); + idref_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" a.b-c_d123 "); + p._characters (" "); + p._post (); + assert (!c.error_type () && + p.post_idref () == string ("a.b-c_d123")); + } + + // idrefs + // + { + context c (0); + string_sequence s; +#ifdef XSDE_STL + s.push_back ("a123"); + s.push_back ("abc"); +#else + s.push_back_copy ("a123"); + s.push_back_copy ("abc"); +#endif + + idrefs_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" \n\t"); + p._characters (" a123 "); + p._characters (" \n\t abc "); + p._characters (" "); + p._post (); + assert (!c.error_type () && compare (p.post_idrefs (), s)); + } + + // language + // + { + context c (0); + language_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" x "); + p._post (); + assert (!c.error_type () && p.post_language () == string ("x")); + } + + { + context c (0); + language_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" en "); + p._post (); + assert (!c.error_type () && p.post_language () == string ("en")); + } + + { + context c (0); + language_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" en"); + p._characters ("-us "); + p._post (); + assert (!c.error_type () && p.post_language () == string ("en-us")); + } + + { + context c (0); + language_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("one-two-three-four44-seven77-eight888"); + p._post (); + assert (!c.error_type () && + p.post_language () == + string ("one-two-three-four44-seven77-eight888")); + } + + // Bad + // + + // name + // + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (""); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (".a"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("-a"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("1a"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("a,b"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("a b"); + p._post (); + assert (c.schema_error ()); + } + + { + context c (0); + name_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("a +# 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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/built-in/uri/driver.cxx b/tests/cxx/parser/validation/built-in/uri/driver.cxx new file mode 100644 index 0000000..5d1f91a --- /dev/null +++ b/tests/cxx/parser/validation/built-in/uri/driver.cxx @@ -0,0 +1,66 @@ +// file : tests/cxx/parser/validation/built-in/uri/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in anyURI type validation. +// +#include +#include + +// Let the runtime header sort out which version (stl/no-stl) to +// include. +// +#include + +using namespace xsde::cxx::parser; +using namespace xsde::cxx::parser::validating; + +int +main () +{ + using std::string; + + // Good. + // + { + context c (0); + uri_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters (" "); + p._post (); + assert (!c.error_type () && p.post_uri () == string ("")); + } + + { + context c (0); + uri_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("relative"); + p._post (); + assert (!c.error_type () && p.post_uri () == string ("relative")); + } + + { + context c (0); + uri_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("#id"); + p._post (); + assert (!c.error_type () && p.post_uri () == string ("#id")); + } + + { + context c (0); + uri_pimpl p; + p.pre (); + p._pre_impl (c); + p._characters ("http://www.example.com/foo#bar"); + p._post (); + assert (!c.error_type () && + p.post_uri () == string ("http://www.example.com/foo#bar")); + } +} diff --git a/tests/cxx/parser/validation/built-in/uri/makefile b/tests/cxx/parser/validation/built-in/uri/makefile new file mode 100644 index 0000000..09da436 --- /dev/null +++ b/tests/cxx/parser/validation/built-in/uri/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/parser/validation/built-in/uri/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/parser/validation/choice/driver.cxx b/tests/cxx/parser/validation/choice/driver.cxx new file mode 100644 index 0000000..e49539a --- /dev/null +++ b/tests/cxx/parser/validation/choice/driver.cxx @@ -0,0 +1,158 @@ +// file : tests/cxx/parser/validation/choice/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the choice compositor validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; +using xml_schema::ro_string; + +struct choice_pimpl: choice_pskel +{ + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } + + virtual void + c (string const& v) + { + cout << " c = " << v << endl; + } + + virtual void + d (string const& v) + { + cout << " d = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } + + virtual void + c (char* v) + { + cout << " c = " << v << endl; + delete[] v; + } + + virtual void + d (char* v) + { + cout << " d = " << v << endl; + delete[] v; + } +#endif + + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (ro_string const& ns, ro_string const& name) +#else + _start_any_element (ro_string const& ns, ro_string const& name, const char*) +#endif + { + cout << " any: " << ns << "#" << name << endl + << " {" << endl; + } + + virtual void + _any_characters (ro_string const& v) + { + cout << " chars = " << v << endl; + } + + virtual void + _end_any_element (ro_string const&, ro_string const&) + { + cout << " }" << endl; + } + + virtual void + post_choice () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + choice_pimpl choice_p; + type_pimpl type_p; + + choice_p.parsers (string_p, string_p, string_p, string_p); + type_p.parsers (choice_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + try + { + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cout << " " << e.line () << ":" << e.column () << " " << e << endl + << "}" << endl + << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/choice/makefile b/tests/cxx/parser/validation/choice/makefile new file mode 100644 index 0000000..0df0020 --- /dev/null +++ b/tests/cxx/parser/validation/choice/makefile @@ -0,0 +1,81 @@ +# file : tests/cxx/parser/validation/choice/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 := test.xsd +cxx := driver.cxx + +tests := 000 001 002 003 004 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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) \ No newline at end of file diff --git a/tests/cxx/parser/validation/choice/test-000.std b/tests/cxx/parser/validation/choice/test-000.std new file mode 100644 index 0000000..856b7f5 --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-000.std @@ -0,0 +1,22 @@ +{ + a = a + b = b +} + +{ + c = c + d = d + any: other#any + { + chars = any + } + a = a +} + +{ + c = c + d = d + d = d + a = a +} + diff --git a/tests/cxx/parser/validation/choice/test-000.xml b/tests/cxx/parser/validation/choice/test-000.xml new file mode 100644 index 0000000..39b9614 --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-000.xml @@ -0,0 +1,30 @@ + + + + a + + b + + + + c + d + + any + + a + + + + c + d + + d + + a + + + diff --git a/tests/cxx/parser/validation/choice/test-001.std b/tests/cxx/parser/validation/choice/test-001.std new file mode 100644 index 0000000..3be2413 --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-001.std @@ -0,0 +1,4 @@ +{ + 8:11 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/choice/test-001.xml b/tests/cxx/parser/validation/choice/test-001.xml new file mode 100644 index 0000000..c509e0d --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-001.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/tests/cxx/parser/validation/choice/test-002.std b/tests/cxx/parser/validation/choice/test-002.std new file mode 100644 index 0000000..0de284d --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-002.std @@ -0,0 +1,11 @@ +{ + c = c + d = d + any: other#any + { + chars = any + } + a = a + 14:7 unexpected element encountered +} + diff --git a/tests/cxx/parser/validation/choice/test-002.xml b/tests/cxx/parser/validation/choice/test-002.xml new file mode 100644 index 0000000..3b7e663 --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-002.xml @@ -0,0 +1,17 @@ + + + + + c + d + + any + + a + b + + + diff --git a/tests/cxx/parser/validation/choice/test-003.std b/tests/cxx/parser/validation/choice/test-003.std new file mode 100644 index 0000000..8ecfdc2 --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-003.std @@ -0,0 +1,5 @@ +{ + c = c + 9:11 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/choice/test-003.xml b/tests/cxx/parser/validation/choice/test-003.xml new file mode 100644 index 0000000..ba15c7e --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-003.xml @@ -0,0 +1,11 @@ + + + + + c + + + diff --git a/tests/cxx/parser/validation/choice/test-004.std b/tests/cxx/parser/validation/choice/test-004.std new file mode 100644 index 0000000..400577a --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-004.std @@ -0,0 +1,4 @@ +{ + 8:7 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/choice/test-004.xml b/tests/cxx/parser/validation/choice/test-004.xml new file mode 100644 index 0000000..f6960dd --- /dev/null +++ b/tests/cxx/parser/validation/choice/test-004.xml @@ -0,0 +1,11 @@ + + + + + x + + + diff --git a/tests/cxx/parser/validation/choice/test.xsd b/tests/cxx/parser/validation/choice/test.xsd new file mode 100644 index 0000000..8132bbb --- /dev/null +++ b/tests/cxx/parser/validation/choice/test.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/makefile b/tests/cxx/parser/validation/makefile new file mode 100644 index 0000000..e2f798c --- /dev/null +++ b/tests/cxx/parser/validation/makefile @@ -0,0 +1,26 @@ +# file : tests/cxx/parser/validation/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 + +tests := built-in + +ifeq ($(xsde_iostream),y) +ifeq ($(xsde_exceptions),y) +tests += all any attribute choice restriction sequence +endif +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/parser/validation/restriction/driver.cxx b/tests/cxx/parser/validation/restriction/driver.cxx new file mode 100644 index 0000000..0088893 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/driver.cxx @@ -0,0 +1,122 @@ +// file : tests/cxx/parser/validation/restriction/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the restriction compositor validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; + +struct base_a_pimpl: base_a_pskel +{ +}; + +struct restriction_a_pimpl: restriction_a_pskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + restriction_a_pimpl () + : restriction_a_pskel (0) + { + } +#endif +}; + +struct extension_b_pimpl: extension_b_pskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + extension_b_pimpl () + : extension_b_pskel (0) + { + } +#endif +}; + +struct restriction_b_pimpl: restriction_b_pskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + restriction_b_pimpl () + : restriction_b_pskel (0) + { + } +#endif +}; + +struct type_b_pimpl: type_b_pskel +{ +}; + +struct type_r_pimpl: type_r_pskel +{ +}; + + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + base_a_pimpl base_a_p; + restriction_a_pimpl restriction_a_p; + extension_b_pimpl extension_b_p; + restriction_b_pimpl restriction_b_p; + type_b_pimpl type_b_p; + type_r_pimpl type_r_p; + + base_a_p.parsers (string_p, string_p, string_p, + string_p, string_p, string_p); + + restriction_a_p.parsers (string_p, string_p, string_p, + string_p, string_p, string_p); + + extension_b_p.parsers (string_p, string_p, string_p, + string_p, string_p); + + restriction_b_p.parsers (string_p, string_p, string_p, + string_p, string_p); + + type_b_p.parsers (base_a_p, extension_b_p); + type_r_p.parsers (restriction_a_p, restriction_b_p); + + xml_schema::document_pimpl doc_b_p (type_b_p, "test", "root"); + xml_schema::document_pimpl doc_r_p (type_r_p, "test", "root"); + + type_b_p.pre (); + doc_b_p.parse (argv[1]); + type_b_p.post_type_b (); + + try + { + type_r_p.pre (); + doc_r_p.parse (argv[1]); + type_r_p.post_type_r (); + } + catch (xml_schema::parser_exception const& e) + { + cout << e.line () << ":" << e.column () << " " << e << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/restriction/makefile b/tests/cxx/parser/validation/restriction/makefile new file mode 100644 index 0000000..ba9dcff --- /dev/null +++ b/tests/cxx/parser/validation/restriction/makefile @@ -0,0 +1,81 @@ +# file : tests/cxx/parser/validation/restriction/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 := test.xsd +cxx := driver.cxx + +tests := 000 001 002 003 004 005 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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) \ No newline at end of file diff --git a/tests/cxx/parser/validation/restriction/test-000.std b/tests/cxx/parser/validation/restriction/test-000.std new file mode 100644 index 0000000..e69de29 diff --git a/tests/cxx/parser/validation/restriction/test-000.xml b/tests/cxx/parser/validation/restriction/test-000.xml new file mode 100644 index 0000000..21402b4 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-000.xml @@ -0,0 +1,31 @@ + + + + a + b + c + + + + a + b + c + + + + a + b + + + + a + c + + + + a + + + diff --git a/tests/cxx/parser/validation/restriction/test-001.std b/tests/cxx/parser/validation/restriction/test-001.std new file mode 100644 index 0000000..1666695 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-001.std @@ -0,0 +1 @@ +7:7 expected element not encountered diff --git a/tests/cxx/parser/validation/restriction/test-001.xml b/tests/cxx/parser/validation/restriction/test-001.xml new file mode 100644 index 0000000..4015302 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-001.xml @@ -0,0 +1,11 @@ + + + + + b + c + + + diff --git a/tests/cxx/parser/validation/restriction/test-002.std b/tests/cxx/parser/validation/restriction/test-002.std new file mode 100644 index 0000000..a261ba8 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-002.std @@ -0,0 +1 @@ +10:18 expected attribute not encountered diff --git a/tests/cxx/parser/validation/restriction/test-002.xml b/tests/cxx/parser/validation/restriction/test-002.xml new file mode 100644 index 0000000..eb7684c --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-002.xml @@ -0,0 +1,12 @@ + + + + + a + b + c + + + diff --git a/tests/cxx/parser/validation/restriction/test-003.std b/tests/cxx/parser/validation/restriction/test-003.std new file mode 100644 index 0000000..c13bef2 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-003.std @@ -0,0 +1 @@ +11:7 unexpected element encountered diff --git a/tests/cxx/parser/validation/restriction/test-003.xml b/tests/cxx/parser/validation/restriction/test-003.xml new file mode 100644 index 0000000..49f18c7 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-003.xml @@ -0,0 +1,16 @@ + + + + + a + b + c + + a + b + c + + + diff --git a/tests/cxx/parser/validation/restriction/test-004.std b/tests/cxx/parser/validation/restriction/test-004.std new file mode 100644 index 0000000..1666695 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-004.std @@ -0,0 +1 @@ +7:7 expected element not encountered diff --git a/tests/cxx/parser/validation/restriction/test-004.xml b/tests/cxx/parser/validation/restriction/test-004.xml new file mode 100644 index 0000000..115cd38 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-004.xml @@ -0,0 +1,10 @@ + + + + + b + + + diff --git a/tests/cxx/parser/validation/restriction/test-005.std b/tests/cxx/parser/validation/restriction/test-005.std new file mode 100644 index 0000000..b2ee79e --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-005.std @@ -0,0 +1 @@ +9:18 expected attribute not encountered diff --git a/tests/cxx/parser/validation/restriction/test-005.xml b/tests/cxx/parser/validation/restriction/test-005.xml new file mode 100644 index 0000000..e9ab7d9 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test-005.xml @@ -0,0 +1,11 @@ + + + + + a + b + + + diff --git a/tests/cxx/parser/validation/restriction/test.xsd b/tests/cxx/parser/validation/restriction/test.xsd new file mode 100644 index 0000000..158ded5 --- /dev/null +++ b/tests/cxx/parser/validation/restriction/test.xsd @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/parser/validation/sequence/driver.cxx b/tests/cxx/parser/validation/sequence/driver.cxx new file mode 100644 index 0000000..60cef37 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/driver.cxx @@ -0,0 +1,185 @@ +// file : tests/cxx/parser/validation/sequence/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the sequence compositor validation. +// + +#include +#include + +#include "test-pskel.hxx" + +using namespace std; +using namespace test; +using xml_schema::ro_string; + +struct sequence_pimpl: sequence_pskel +{ + virtual void + pre () + { + cout << "{" << endl; + } + +#ifdef XSDE_STL + virtual void + a (string const& v) + { + cout << " a = " << v << endl; + } + + virtual void + b (string const& v) + { + cout << " b = " << v << endl; + } + + virtual void + c (string const& v) + { + cout << " c = " << v << endl; + } + + virtual void + d (string const& v) + { + cout << " d = " << v << endl; + } + + virtual void + e (string const& v) + { + cout << " e = " << v << endl; + } + + virtual void + f (string const& v) + { + cout << " f = " << v << endl; + } +#else + virtual void + a (char* v) + { + cout << " a = " << v << endl; + delete[] v; + } + + virtual void + b (char* v) + { + cout << " b = " << v << endl; + delete[] v; + } + + virtual void + c (char* v) + { + cout << " c = " << v << endl; + delete[] v; + } + + virtual void + d (char* v) + { + cout << " d = " << v << endl; + delete[] v; + } + + virtual void + e (char* v) + { + cout << " e = " << v << endl; + delete[] v; + } + + virtual void + f (char* v) + { + cout << " f = " << v << endl; + delete[] v; + } +#endif + + virtual void +#ifndef XSDE_POLYMORPHIC + _start_any_element (ro_string const& ns, ro_string const& name) +#else + _start_any_element (ro_string const& ns, ro_string const& name, const char*) +#endif + { + cout << " any: " << ns << "#" << name << endl + << " {" << endl; + } + + virtual void + _any_characters (ro_string const& v) + { + cout << " chars = " << v << endl; + } + + virtual void + _end_any_element (ro_string const&, ro_string const&) + { + cout << " }" << endl; + } + + virtual void + post_sequence () + { + cout << "}" << endl + << endl; + } +}; + +struct type_pimpl: type_pskel +{ +}; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + try + { + xml_schema::string_pimpl string_p; + sequence_pimpl sequence_p; + type_pimpl type_p; + + sequence_p.parsers (string_p, string_p, string_p, + string_p, string_p, string_p); + type_p.parsers (sequence_p); + + xml_schema::document_pimpl doc_p (type_p, "test", "root"); + + try + { + type_p.pre (); + doc_p.parse (argv[1]); + type_p.post_type (); + } + catch (xml_schema::parser_exception const& e) + { + cout << " " << e.line () << ":" << e.column () << " " << e << endl + << "}" << endl + << endl; + } + } + catch (xml_schema::parser_exception const& e) + { + cerr << e << endl; + return 1; + } + catch (ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/parser/validation/sequence/makefile b/tests/cxx/parser/validation/sequence/makefile new file mode 100644 index 0000000..f7ee5a9 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/makefile @@ -0,0 +1,81 @@ +# file : tests/cxx/parser/validation/sequence/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 := test.xsd +cxx := driver.cxx + +tests := 000 001 002 003 004 005 006 + +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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +test_targets := $(addprefix $(out_base)/.test-,$(tests)) + +.PHONY: $(test) +$(test): $(test_targets) + + +$(test_targets): driver := $(driver) + +.PHONY: $(out_base)/.test-% +$(out_base)/.test-%: $(driver) $(src_base)/test.xsd $(src_base)/test-%.xml $(src_base)/test-%.std + $(call message,test $(out_base)/$*,$(driver) $(src_base)/test-$*.xml | diff -u $(src_base)/test-$*.std -) + + +# 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) \ No newline at end of file diff --git a/tests/cxx/parser/validation/sequence/test-000.std b/tests/cxx/parser/validation/sequence/test-000.std new file mode 100644 index 0000000..8a44762 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-000.std @@ -0,0 +1,56 @@ +{ + c = c + d = d + any: test#any + { + chars = aaa + any: #a + { + chars = bbb + } + chars = ccc + } + f = f + e = e +} + +{ + a = a + b = b + c = c + d = d + d = d + d = d + any: other#any + { + chars = any + } + f = f + e = e + e = e +} + +{ + a = a + b = b + c = c + d = d + d = d + d = d + any: other#any + { + chars = any + } + f = f + e = e + e = e + c = c + d = d + any: test#any + { + chars = any + } + f = f + e = e +} + diff --git a/tests/cxx/parser/validation/sequence/test-000.xml b/tests/cxx/parser/validation/sequence/test-000.xml new file mode 100644 index 0000000..9bcbd7e --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-000.xml @@ -0,0 +1,46 @@ + + + + c + d + aaabbbccc + f + e + + + + a + b + c + d + d + d + any + f + e + e + + + + a + b + c + d + d + d + any + f + e + e + + c + d + any + f + e + + + diff --git a/tests/cxx/parser/validation/sequence/test-001.std b/tests/cxx/parser/validation/sequence/test-001.std new file mode 100644 index 0000000..733078a --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-001.std @@ -0,0 +1,4 @@ +{ + 8:13 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-001.xml b/tests/cxx/parser/validation/sequence/test-001.xml new file mode 100644 index 0000000..67d33ce --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-001.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/tests/cxx/parser/validation/sequence/test-002.std b/tests/cxx/parser/validation/sequence/test-002.std new file mode 100644 index 0000000..d58d744 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-002.std @@ -0,0 +1,20 @@ +{ + c = c + d = d + any: test#any + { + chars = any + } + f = f + e = e + c = c + d = d + any: test#any + { + chars = any + } + f = f + e = e + 20:7 unexpected element encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-002.xml b/tests/cxx/parser/validation/sequence/test-002.xml new file mode 100644 index 0000000..be25fcf --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-002.xml @@ -0,0 +1,27 @@ + + + + + c + d + any + f + e + + c + d + any + f + e + + c + d + any + f + e + + + diff --git a/tests/cxx/parser/validation/sequence/test-003.std b/tests/cxx/parser/validation/sequence/test-003.std new file mode 100644 index 0000000..db09f17 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-003.std @@ -0,0 +1,5 @@ +{ + a = a + 9:7 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-003.xml b/tests/cxx/parser/validation/sequence/test-003.xml new file mode 100644 index 0000000..af7d21d --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-003.xml @@ -0,0 +1,17 @@ + + + + + a + a + c + d + any + f + e + + + diff --git a/tests/cxx/parser/validation/sequence/test-004.std b/tests/cxx/parser/validation/sequence/test-004.std new file mode 100644 index 0000000..400577a --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-004.std @@ -0,0 +1,4 @@ +{ + 8:7 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-004.xml b/tests/cxx/parser/validation/sequence/test-004.xml new file mode 100644 index 0000000..a58b6d4 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-004.xml @@ -0,0 +1,14 @@ + + + + + d + any + f + e + + + diff --git a/tests/cxx/parser/validation/sequence/test-005.std b/tests/cxx/parser/validation/sequence/test-005.std new file mode 100644 index 0000000..9603e0f --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-005.std @@ -0,0 +1,6 @@ +{ + c = c + d = d + 10:12 expected element not encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-005.xml b/tests/cxx/parser/validation/sequence/test-005.xml new file mode 100644 index 0000000..e3dd03d --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-005.xml @@ -0,0 +1,15 @@ + + + + + c + d + any + f + e + + + diff --git a/tests/cxx/parser/validation/sequence/test-006.std b/tests/cxx/parser/validation/sequence/test-006.std new file mode 100644 index 0000000..d39b1b4 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-006.std @@ -0,0 +1,13 @@ +{ + c = c + d = d + any: test#any + { + chars = any + } + f = f + e = e + e = e + 14:7 unexpected element encountered +} + diff --git a/tests/cxx/parser/validation/sequence/test-006.xml b/tests/cxx/parser/validation/sequence/test-006.xml new file mode 100644 index 0000000..e1ecd69 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test-006.xml @@ -0,0 +1,17 @@ + + + + + c + d + any + f + e + e + e + + + diff --git a/tests/cxx/parser/validation/sequence/test.xsd b/tests/cxx/parser/validation/sequence/test.xsd new file mode 100644 index 0000000..8753f54 --- /dev/null +++ b/tests/cxx/parser/validation/sequence/test.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/all/driver.cxx b/tests/cxx/serializer/all/driver.cxx new file mode 100644 index 0000000..f781b94 --- /dev/null +++ b/tests/cxx/serializer/all/driver.cxx @@ -0,0 +1,108 @@ +// file : tests/cxx/serializer/all/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the all compositor serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: test_1_sskel +{ + virtual int + a () + { + return 123; + } + + virtual bool + b_present () + { + return true; + } + + virtual int + b () + { + return 234; + } +}; + +struct test_2_simpl: test_2_sskel +{ + test_2_simpl () + : i_ (0) + { + } + + virtual bool + all_present () + { + return i_++; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int i_; +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + n1_ = 0; + n2_ = 0; + } + + virtual bool + test_1_next () + { + return n1_++ < 1; + } + + virtual bool + test_2_next () + { + return n2_++ < 2; + } + +private: + int n1_, n2_; +}; + +int +main () +{ + xml_schema::int_simpl int_s; + test_1_simpl test_1_s; + test_2_simpl test_2_s; + root_simpl root_s; + + test_1_s.serializers (int_s, int_s); + test_2_s.serializers (int_s, int_s); + root_s.serializers (test_1_s, test_2_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/all/makefile b/tests/cxx/serializer/all/makefile new file mode 100644 index 0000000..d73444a --- /dev/null +++ b/tests/cxx/serializer/all/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/all/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/all/output b/tests/cxx/serializer/all/output new file mode 100644 index 0000000..ec04b95 --- /dev/null +++ b/tests/cxx/serializer/all/output @@ -0,0 +1 @@ +123234123234 \ No newline at end of file diff --git a/tests/cxx/serializer/all/test.xsd b/tests/cxx/serializer/all/test.xsd new file mode 100644 index 0000000..7d369f5 --- /dev/null +++ b/tests/cxx/serializer/all/test.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/built-in/driver.cxx b/tests/cxx/serializer/built-in/driver.cxx new file mode 100644 index 0000000..f1d17a1 --- /dev/null +++ b/tests/cxx/serializer/built-in/driver.cxx @@ -0,0 +1,1304 @@ +// file : tests/cxx/serializer/built-in/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test built-in type serialization. +// + +#include // strtof, strtod +#include // memcpy +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct any_type_simpl: xml_schema::any_type_simpl +{ + virtual void + _serialize_attributes () + { + _attribute ("foo", "one"); + _attribute ("test", "foo", "two"); + } + + virtual void + _serialize_content () + { + _start_element ("test", "inner"); + _characters ("hello"); + _end_element (); + } +}; + +struct any_simple_type_simpl: xml_schema::any_simple_type_simpl +{ + virtual void + _serialize_content () + { + _characters ("hello"); + } +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + boolean_ = 0; + byte_ = 0; + unsigned_byte_ = 0; + short__ = 0; + unsigned_short_ = 0; + int__ = 0; + unsigned_int_ = 0; + long__ = 0; + unsigned_long_ = 0; + + integer_ = 0; + negative_integer_ = 0; + non_positive_integer_ = 0; + positive_integer_ = 0; + non_negative_integer_ = 0; + + float__ = 0; + double__ = 0; + decimal_ = 0; + + string_ = 0; + normalized_string_ = 0; + token_ = 0; + name_ = 0; + nmtoken_ = 0; + nmtokens_ = 0; + ncname_ = 0; + id_ = 0; + idref_ = 0; + idrefs_ = 0; + language_ = 0; + uri_ = 0; + qname_ = 0; + + base64_binary_ = 0; + hex_binary_ = 0; + + gday_ = 0; + gmonth_ = 0; + gyear_ = 0; + gmonth_day_ = 0; + gyear_month_ = 0; + date_ = 0; + time_ = 0; + date_time_ = 0; + duration_ = 0; + } + + virtual bool + boolean_next () + { + return boolean_ < 2; + } + + virtual bool + boolean () + { + static const bool v[] = {true, false}; + return v[boolean_++]; + } + + virtual bool + byte_next () + { + return byte_ < 4; + } + + virtual signed char + byte () + { + static const signed char v[] = {-128, -123, 0, 127}; + return v[byte_++]; + } + + virtual bool + unsigned_byte_next () + { + return unsigned_byte_ < 3; + } + + virtual unsigned char + unsigned_byte () + { + static const unsigned char v[] = {0, 123, 255}; + return v[unsigned_byte_++]; + } + + virtual bool + short__next () + { + return short__ < 4; + } + + virtual short + short_ () + { + static const short v[] = {-32768, -12345, 0, 32767}; + return v[short__++]; + } + + virtual bool + unsigned_short_next () + { + return unsigned_short_ < 3; + } + + virtual unsigned short + unsigned_short () + { + static const unsigned short v[] = {0, 12345, 65535}; + return v[unsigned_short_++]; + } + + virtual bool + int__next () + { + return int__ < 4; + } + + virtual int + int_ () + { + static const int v[] = {-2147483648, -1234567890, 0, 2147483647}; + return v[int__++]; + } + + virtual bool + unsigned_int_next () + { + return unsigned_int_ < 3; + } + + virtual unsigned int + unsigned_int () + { + static const unsigned int v[] = {0, 1234567890, 4294967295}; + return v[unsigned_int_++]; + } + + virtual bool + long__next () + { + return long__ < 4; + } + + virtual bool + unsigned_long_next () + { + return unsigned_long_ < 3; + } + +#ifdef XSDE_LONGLONG + virtual long long + long_ () + { + static const long long v[] = + { + -9223372036854775807LL, -1234567890123456789LL, + 0LL, 9223372036854775807LL + }; + + return long__ == 0 ? (v[long__++] - 1) : v[long__++]; + } + + virtual unsigned long long + unsigned_long () + { + static const unsigned long long v[] = + { + 0ULL, 12345678901234567890ULL, 18446744073709551615ULL + }; + + return v[unsigned_long_++]; + } +#else + virtual long + long_ () + { + static const long v[] = {-2147483647L, -1234567890L, 0L, 2147483647L}; + return long__ == 0 ? (v[long__++] - 1) : v[long__++]; + } + + virtual unsigned long + unsigned_long () + { + static const unsigned long v[] = {0UL, 1234567890UL, 4294967295UL}; + return v[unsigned_long_++]; + } +#endif + + // + // + virtual bool + integer_next () + { + return integer_ < 4; + } + + virtual long + integer () + { + static const long v[] = {-2147483647L, -1234567890L, 0L, 2147483647L}; + return integer_ == 0 ? (v[integer_++] - 1) : v[integer_++]; + } + + virtual bool + negative_integer_next () + { + return negative_integer_ < 2; + } + + virtual long + negative_integer () + { + static const long v[] = {-2147483647L, -1234567890L}; + return negative_integer_ == 0 + ? (v[negative_integer_++] - 1) + : v[negative_integer_++]; + } + + virtual bool + non_positive_integer_next () + { + return non_positive_integer_ < 3; + } + + virtual long + non_positive_integer () + { + static const long v[] = {-2147483647L, -1234567890L, 0L}; + return non_positive_integer_ == 0 + ? (v[non_positive_integer_++] - 1) + : v[non_positive_integer_++]; + } + + virtual bool + positive_integer_next () + { + return positive_integer_ < 2; + } + + virtual unsigned long + positive_integer () + { + static const unsigned long v[] = {1234567890UL, 4294967295UL}; + return v[positive_integer_++]; + } + + virtual bool + non_negative_integer_next () + { + return non_negative_integer_ < 3; + } + + virtual unsigned long + non_negative_integer () + { + static const unsigned long v[] = {0UL, 1234567890UL, 4294967295UL}; + return v[non_negative_integer_++]; + } + + // + // + virtual bool + float__next () + { + return float__ < 9; + } + + virtual float + float_ () + { + static const float v[] = {0.0, 0.0, 0.0, 0.0, 1.0, -1.0, + 123.567, -123.567e5, -0.45e-5}; + + switch (float__) + { + case 0: + { + float__++; + return strtof ("INF", 0); + } + case 1: + { + float__++; + return strtof ("-INF", 0); + } + case 2: + { + float__++; + return strtof ("NAN", 0); + } + default: + { + return v[float__++]; + } + } + } + + virtual bool + double__next () + { + return double__ < 9; + } + + virtual double + double_ () + { + static const double v[] = {0.0, 0.0, 0.0, 0.0, 1.0, -1.0, + 123.56789, -123.56789e8, -0.45E-5}; + + switch (double__) + { + case 0: + { + double__++; + return strtod ("INF", 0); + } + case 1: + { + double__++; + return strtod ("-INF", 0); + } + case 2: + { + double__++; + return strtod ("NAN", 0); + } + default: + { + return v[double__++]; + } + } + } + + virtual bool + decimal_next () + { + return decimal_ < 5; + } + + virtual double + decimal () + { + static const double v[] = {0.0, 1.0, -1.0, 123.56789, -123.56789}; + return v[decimal_++]; + } + + // + // + +#ifdef XSDE_STL + + virtual bool + string_next () + { + return string_++ < 1; + } + + virtual std::string + string () + { + return " test \n string "; + } + + virtual bool + normalized_string_next () + { + return normalized_string_++ < 1; + } + + virtual std::string + normalized_string () + { + return "test normalized string"; + } + + virtual bool + token_next () + { + return token_++ < 1; + } + + virtual std::string + token () + { + return "test token"; + } + + virtual bool + name_next () + { + return name_++ < 1; + } + + virtual std::string + name () + { + return "as123:345-.abs"; + } + + virtual bool + nmtoken_next () + { + return nmtoken_++ < 1; + } + + virtual std::string + nmtoken () + { + return "1as123:345-.abs"; + } + + virtual bool + nmtokens_next () + { + return nmtokens_ < 2; + } + + virtual xml_schema::string_sequence* + nmtokens () + { + using xml_schema::string_sequence; + + switch (nmtokens_++) + { + case 0: + { + string_sequence* r = new string_sequence; + r->push_back ("one"); + return r; + } + case 1: + { + string_sequence* r = new string_sequence; + r->push_back ("one"); + r->push_back ("two"); + r->push_back ("three"); + return r; + } + default: + return 0; + } + } + + virtual bool + ncname_next () + { + return ncname_++ < 1; + } + + virtual std::string + ncname () + { + return "as123_345-.abs"; + } + + virtual bool + id_next () + { + return id_ < 4; + } + + virtual std::string + id () + { + static const char* v[] = {"as123_345-.abs", "one", "two", "three"}; + return v[id_++]; + } + + virtual bool + idref_next () + { + return idref_++ < 1; + } + + virtual std::string + idref () + { + return "as123_345-.abs"; + } + + virtual bool + idrefs_next () + { + return idrefs_ < 2; + } + + virtual xml_schema::string_sequence* + idrefs () + { + using xml_schema::string_sequence; + + switch (idrefs_++) + { + case 0: + { + string_sequence* r = new string_sequence; + r->push_back ("one"); + return r; + } + case 1: + { + string_sequence* r = new string_sequence; + r->push_back ("two"); + r->push_back ("three"); + return r; + } + default: + return 0; + } + } + + virtual bool + language_next () + { + return language_++ < 1; + } + + virtual std::string + language () + { + return "en-us"; + } + + virtual bool + uri_next () + { + return uri_++ < 1; + } + + virtual std::string + uri () + { + return "http://www.example.com/foo#bar"; + } + + virtual bool + qname_next () + { + return qname_ < 2; + } + + virtual xml_schema::qname + qname () + { + using xml_schema::qname; + + switch (qname_++) + { + case 0: + { + qname r ("g1", "qname"); + return r; + } + case 1: + { + qname r ("qname"); + return r; + } + default: + return qname ("bad"); + } + } + +#else + + virtual bool + string_next () + { + return string_++ < 1; + } + + virtual const char* + string () + { + return " test \n string "; + } + + virtual bool + normalized_string_next () + { + return normalized_string_++ < 1; + } + + virtual const char* + normalized_string () + { + return "test normalized string"; + } + + virtual bool + token_next () + { + return token_++ < 1; + } + + virtual const char* + token () + { + return "test token"; + } + + virtual bool + name_next () + { + return name_++ < 1; + } + + virtual const char* + name () + { + return "as123:345-.abs"; + } + + virtual bool + nmtoken_next () + { + return nmtoken_++ < 1; + } + + virtual const char* + nmtoken () + { + return "1as123:345-.abs"; + } + + virtual bool + nmtokens_next () + { + return nmtokens_ < 2; + } + + virtual const xml_schema::string_sequence* + nmtokens () + { + using xml_schema::string_sequence; + + switch (nmtokens_++) + { + case 0: + { + string_sequence* r = new string_sequence (); + r->push_back_copy ("one"); + return r; + } + case 1: + { + string_sequence* r = new string_sequence (); + r->push_back_copy ("one"); + r->push_back_copy ("two"); + r->push_back_copy ("three"); + return r; + } + default: + return 0; + } + } + + virtual bool + ncname_next () + { + return ncname_++ < 1; + } + + virtual const char* + ncname () + { + return "as123_345-.abs"; + } + + virtual bool + id_next () + { + return id_ < 4; + } + + virtual const char* + id () + { + static const char* v[] = {"as123_345-.abs", "one", "two", "three"}; + return v[id_++]; + } + + virtual bool + idref_next () + { + return idref_++ < 1; + } + + virtual const char* + idref () + { + return "as123_345-.abs"; + } + + virtual bool + idrefs_next () + { + return idrefs_ < 2; + } + + virtual const xml_schema::string_sequence* + idrefs () + { + using xml_schema::string_sequence; + + switch (idrefs_++) + { + case 0: + { + string_sequence* r = new string_sequence (); + r->push_back_copy ("one"); + return r; + } + case 1: + { + string_sequence* r = new string_sequence (); + r->push_back_copy ("two"); + r->push_back_copy ("three"); + return r; + } + default: + return 0; + } + } + + virtual bool + language_next () + { + return language_++ < 1; + } + + virtual const char* + language () + { + return "en-us"; + } + + virtual bool + uri_next () + { + return uri_++ < 1; + } + + virtual const char* + uri () + { + return "http://www.example.com/foo#bar"; + } + + virtual bool + qname_next () + { + return qname_ < 2; + } + + virtual const xml_schema::qname* + qname () + { + using xml_schema::qname; + + switch (qname_++) + { + case 0: + { + qname* r = new qname (); + r->prefix_copy ("g1"); + r->name_copy ("qname"); + return r; + } + case 1: + { + qname* r = new qname (); + r->name_copy ("qname"); + return r; + } + default: + return 0; + } + } +#endif + + // + // + virtual bool + base64_binary_next () + { + return base64_binary_ < 6; + } + + virtual const xml_schema::buffer* + base64_binary () + { + xml_schema::buffer* r = new xml_schema::buffer (); + + switch (base64_binary_++) + { + case 0: + { + // Empty buffer. + // + break; + } + case 1: + { + const char data[] = "12345abcjk"; + const size_t size = sizeof (data) - 1; + r->size (size); + memcpy (r->data (), data, size); + break; + } + case 2: + { + const char data[] = "a"; + const size_t size = sizeof (data) - 1; + r->size (size); + memcpy (r->data (), data, size); + break; + } + case 3: + { + const char data[] = "ab"; + const size_t size = sizeof (data) -1; + r->size (size); + memcpy (r->data (), data, size); + break; + } + case 4: + { + const char data[] = "abc"; + const size_t size = sizeof (data) - 1; + r->size (size); + memcpy (r->data (), data, size); + break; + } + case 5: + { + const size_t size = 345; + + r->size (size); + unsigned char v = 0; + + for (size_t i = 0; i < size; ++i) + { + r->data ()[i] = static_cast (v++); + } + + break; + } + } + + return r; + } + + virtual bool + hex_binary_next () + { + return hex_binary_ < 3; + } + + virtual const xml_schema::buffer* + hex_binary () + { + xml_schema::buffer* r = new xml_schema::buffer (); + + switch (hex_binary_++) + { + case 0: + { + // Empty buffer. + // + break; + } + case 1: + { + const char data[] = "12345abcjk"; + const size_t size = sizeof (data) - 1; + r->size (size); + memcpy (r->data (), data, size); + break; + } + case 2: + { + const size_t size = 345; + + r->size (size); + unsigned char v = 0; + + for (size_t i = 0; i < size; ++i) + { + r->data ()[i] = static_cast (v++); + } + + break; + } + } + + return r; + } + + virtual bool + gday_next () + { + return gday_ < 3; + } + + virtual xml_schema::gday + gday () + { + using xml_schema::gday; + + switch (gday_++) + { + case 0: + return gday (23); + case 1: + return gday (31, 2, 30); + case 2: + return gday (15, 0, 0); + } + } + + virtual bool + gmonth_next () + { + return gmonth_ < 2; + } + + virtual ::xml_schema::gmonth + gmonth () + { + using xml_schema::gmonth; + + switch (gmonth_++) + { + case 0: + return gmonth (6); + case 1: + return gmonth (12, 2, 30); + } + } + + virtual bool + gyear_next () + { + return gyear_ < 2; + } + + virtual ::xml_schema::gyear + gyear () + { + using xml_schema::gyear; + + switch (gyear_++) + { + case 0: + return gyear (2007); + case 1: + return gyear (-2007, -2, -30); + } + } + + virtual bool + gmonth_day_next () + { + return gmonth_day_ < 2; + } + + virtual ::xml_schema::gmonth_day + gmonth_day () + { + using xml_schema::gmonth_day; + + switch (gmonth_day_++) + { + case 0: + return gmonth_day (6, 15); + case 1: + return gmonth_day (12, 31, 2, 30); + } + } + + virtual bool + gyear_month_next () + { + return gyear_month_ < 2; + } + + virtual ::xml_schema::gyear_month + gyear_month () + { + using xml_schema::gyear_month; + + switch (gyear_month_++) + { + case 0: + return gyear_month (2007, 10); + case 1: + return gyear_month (-2007, 12, -2, -30); + } + } + + virtual bool + date_next () + { + return date_ < 2; + } + + virtual ::xml_schema::date + date () + { + using xml_schema::date; + + switch (date_++) + { + case 0: + return date (2007, 6, 15); + case 1: + return date (-2007, 12, 31, -2, -30); + } + } + + virtual bool + time_next () + { + return time_ < 2; + } + + virtual ::xml_schema::time + time () + { + using xml_schema::time; + + switch (time_++) + { + case 0: + return time (12, 30, 30.0); + case 1: + return time (23, 59, 59.55, 2, 30); + } + } + + virtual bool + date_time_next () + { + return date_time_ < 2; + } + + virtual ::xml_schema::date_time + date_time () + { + using xml_schema::date_time; + + switch (date_time_++) + { + case 0: + return date_time (2007, 6, 15, 12, 30, 30.0); + case 1: + return date_time (-2007, 12, 31, 23, 59, 59.55, -2, -30); + } + } + + virtual bool + duration_next () + { + return duration_ < 7; + } + + virtual ::xml_schema::duration + duration () + { + using xml_schema::duration; + + switch (duration_++) + { + case 0: + return duration (false, 1, 0, 0, 0, 0, 0.0); + case 1: + return duration (true, 0, 1, 0, 0, 0, 0.0); + case 2: + return duration (false, 0, 0, 1, 0, 0, 0.0); + case 3: + return duration (true, 0, 0, 0, 1, 0, 0.0); + case 4: + return duration (false, 0, 0, 0, 0, 1, 0.0); + case 5: + return duration (true, 0, 0, 0, 0, 0, 1.1); + case 6: + return duration (false, 1, 2, 3, 4, 5, 6.7); + } + } + +private: + int boolean_; + int byte_; + int unsigned_byte_; + int short__; + int unsigned_short_; + int int__; + int unsigned_int_; + int long__; + int unsigned_long_; + + int integer_; + int negative_integer_; + int non_positive_integer_; + int positive_integer_; + int non_negative_integer_; + + int float__; + int double__; + int decimal_; + + int string_; + int normalized_string_; + int token_; + int name_; + int nmtoken_; + int nmtokens_; + int ncname_; + int id_; + int idref_; + int idrefs_; + int language_; + int uri_; + int qname_; + + int base64_binary_; + int hex_binary_; + + int gday_; + int gmonth_; + int gyear_; + int gmonth_day_; + int gyear_month_; + int date_; + int time_; + int date_time_; + int duration_; +}; + +int +main () +{ + any_type_simpl any_type_s; + any_simple_type_simpl any_simple_type_s; + + xml_schema::boolean_simpl boolean_s; + + xml_schema::byte_simpl byte_s; + xml_schema::unsigned_byte_simpl unsigned_byte_s; + xml_schema::short_simpl short_s; + xml_schema::unsigned_short_simpl unsigned_short_s; + xml_schema::int_simpl int_s; + xml_schema::unsigned_int_simpl unsigned_int_s; + xml_schema::long_simpl long_s; + xml_schema::unsigned_long_simpl unsigned_long_s; + + xml_schema::integer_simpl integer_s; + xml_schema::negative_integer_simpl negative_integer_s; + xml_schema::non_positive_integer_simpl non_sositive_integer_s; + xml_schema::positive_integer_simpl positive_integer_s; + xml_schema::non_negative_integer_simpl non_negative_integer_s; + + xml_schema::float_simpl float_s; + xml_schema::double_simpl double_s; + xml_schema::decimal_simpl decimal_s; + + xml_schema::string_simpl string_s; + xml_schema::normalized_string_simpl normalized_string_s; + xml_schema::token_simpl token_s; + xml_schema::name_simpl name_s; + xml_schema::nmtoken_simpl nmtoken_s; + xml_schema::ncname_simpl ncname_s; + xml_schema::id_simpl id_s; + xml_schema::idref_simpl idref_s; + + xml_schema::language_simpl language_s; + xml_schema::uri_simpl uri_s; + +#ifdef XSDE_STL + xml_schema::qname_simpl qname_s; +#else + xml_schema::qname_simpl qname_s (true); +#endif + + xml_schema::idrefs_simpl idrefs_s (true); + xml_schema::nmtokens_simpl nmtokens_s (true); + + xml_schema::base64_binary_simpl base64_binary_s (true); + xml_schema::hex_binary_simpl hex_binary_s (true); + + xml_schema::gday_simpl gday_s; + xml_schema::gmonth_simpl gmonth_s; + xml_schema::gyear_simpl gyear_s; + xml_schema::gmonth_day_simpl gmonth_day_s; + xml_schema::gyear_month_simpl gyear_month_s; + xml_schema::date_simpl date_s; + xml_schema::time_simpl time_s; + xml_schema::date_time_simpl date_time_s; + xml_schema::duration_simpl duration_s; + + root_simpl root_s; + + root_s.serializers (any_type_s, + any_simple_type_s, + boolean_s, + byte_s, + unsigned_byte_s, + short_s, + unsigned_short_s, + int_s, + unsigned_int_s, + long_s, + unsigned_long_s, + integer_s, + negative_integer_s, + non_sositive_integer_s, + positive_integer_s, + non_negative_integer_s, + float_s, + double_s, + decimal_s, + string_s, + normalized_string_s, + token_s, + name_s, + nmtoken_s, + nmtokens_s, + ncname_s, + id_s, + idref_s, + idrefs_s, + language_s, + uri_s, + qname_s, + base64_binary_s, + hex_binary_s, + gday_s, + gmonth_s, + gyear_s, + gmonth_day_s, + gyear_month_s, + date_s, + time_s, + date_time_s, + duration_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/built-in/makefile b/tests/cxx/serializer/built-in/makefile new file mode 100644 index 0000000..78a2055 --- /dev/null +++ b/tests/cxx/serializer/built-in/makefile @@ -0,0 +1,79 @@ +# file : tests/cxx/serializer/built-in/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) + +ifeq ($(xsde_longlong),y) +$(test): $(driver) $(src_base)/output-long-long + $(call message,test $$1,$$1 | diff -u $(src_base)/output-long-long -,$(driver)) +else +$(test): $(driver) $(src_base)/output-long + $(call message,test $$1,$$1 | diff -u $(src_base)/output-long -,$(driver)) +endif + + +# 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/tests/cxx/serializer/built-in/output-long b/tests/cxx/serializer/built-in/output-long new file mode 100644 index 0000000..7333c2d --- /dev/null +++ b/tests/cxx/serializer/built-in/output-long @@ -0,0 +1,13 @@ +hellohellotruefalse-128-12301270123255-32768-1234503276701234565535-2147483648-123456789002147483647012345678904294967295-2147483648-123456789002147483647012345678904294967295-2147483648-123456789002147483647-2147483648-1234567890-2147483648-1234567890012345678904294967295012345678904294967295INF-INFNaN01-1123.567-1.23567e+07-4.5e-06INF-INFNaN01-1123.56789-12356789000-4.5e-0601-1123.567890000000006-123.567890000000006 test + string test normalized stringtest tokenas123:345-.abs1as123:345-.absoneone two threeas123_345-.absas123_345-.absonetwothreeas123_345-.absonetwo threeen-ushttp://www.example.com/foo#barg1:qnameqnameMTIzNDVhYmNqaw== +YQ== +YWI= +YWJj +AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4 +OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx +cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq +q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj +5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhsc +HR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RV +VldY +31323334356162636A6B000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758---23---31+02:30---15Z--06--12+02:302007-2007-02:30--06-15--12-31+02:302007-10-2007-12-02:302007-06-15-2007-12-31-02:302007-06-15T12:30:30-2007-12-31T23:59:59.55-02:30P1Y-P1MP1D-PT1HPT1M-PT1.1SP1Y2M3DT4H5M6.7S \ No newline at end of file diff --git a/tests/cxx/serializer/built-in/output-long-long b/tests/cxx/serializer/built-in/output-long-long new file mode 100644 index 0000000..b0f36cc --- /dev/null +++ b/tests/cxx/serializer/built-in/output-long-long @@ -0,0 +1,13 @@ +hellohellotruefalse-128-12301270123255-32768-1234503276701234565535-2147483648-123456789002147483647012345678904294967295-9223372036854775808-12345678901234567890922337203685477580701234567890123456789018446744073709551615-2147483648-123456789002147483647-2147483648-1234567890-2147483648-1234567890012345678904294967295012345678904294967295INF-INFNaN01-1123.567-1.23567e+07-4.5e-06INF-INFNaN01-1123.56789-12356789000-4.5e-0601-1123.567890000000006-123.567890000000006 test + string test normalized stringtest tokenas123:345-.abs1as123:345-.absoneone two threeas123_345-.absas123_345-.absonetwothreeas123_345-.absonetwo threeen-ushttp://www.example.com/foo#barg1:qnameqnameMTIzNDVhYmNqaw== +YQ== +YWI= +YWJj +AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4 +OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx +cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq +q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj +5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhsc +HR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RV +VldY +31323334356162636A6B000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758---23---31+02:30---15Z--06--12+02:302007-2007-02:30--06-15--12-31+02:302007-10-2007-12-02:302007-06-15-2007-12-31-02:302007-06-15T12:30:30-2007-12-31T23:59:59.55-02:30P1Y-P1MP1D-PT1HPT1M-PT1.1SP1Y2M3DT4H5M6.7S \ No newline at end of file diff --git a/tests/cxx/serializer/built-in/test.xsd b/tests/cxx/serializer/built-in/test.xsd new file mode 100644 index 0000000..070e62d --- /dev/null +++ b/tests/cxx/serializer/built-in/test.xsd @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/choice/driver.cxx b/tests/cxx/serializer/choice/driver.cxx new file mode 100644 index 0000000..684f14d --- /dev/null +++ b/tests/cxx/serializer/choice/driver.cxx @@ -0,0 +1,253 @@ +// file : tests/cxx/serializer/choice/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the choice compositor serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: test_1_sskel +{ + test_1_simpl () + : i_ (0) + { + } + + virtual void + pre () + { + j_ = 0; + } + + virtual choice_arm_tag + choice_arm () + { + return static_cast (i_++); + } + + virtual int + a () + { + return 123; + } + + virtual bool + b_present () + { + return true; + } + + virtual int + b () + { + return 234; + } + + virtual bool + c_next () + { + return j_++ < 3; + } + + virtual int + c () + { + return j_; + } + +private: + int i_, j_; +}; + +struct test_2_simpl: test_2_sskel +{ + test_2_simpl () + : i_ (0) + { + } + + virtual bool + choice_present () + { + return i_++; + } + + virtual choice_arm_tag + choice_arm () + { + return b_tag; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int i_; +}; + +struct test_3_simpl: test_3_sskel +{ + virtual void + pre () + { + i_ = 0; + } + + virtual bool + choice_next () + { + return i_++ < 4; + } + + virtual choice_arm_tag + choice_arm () + { + return i_ % 2 ? a_tag : b_tag; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int i_; +}; + +struct test_4_simpl: test_4_sskel +{ + test_4_simpl () + : i_ (0) + { + } + + virtual choice_arm_tag + choice_arm () + { + return static_cast (i_++); + } + + virtual int + a () + { + return 123; + } + + virtual choice1_arm_tag + choice1_arm () + { + return c_tag; + } + + virtual int + b () + { + return 0; + } + + virtual int + c () + { + return 234; + } + + virtual int + d () + { + return 345; + } + + virtual int + e () + { + return 456; + } + +private: + int i_; +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + n1_ = 0; + n2_ = 0; + n3_ = 0; + n4_ = 0; + } + + virtual bool + test_1_next () + { + return n1_++ < 3; + } + + virtual bool + test_2_next () + { + return n2_++ < 2; + } + + virtual bool + test_3_next () + { + return n3_++ < 1; + } + + virtual bool + test_4_next () + { + return n4_++ < 3; + } + +private: + int n1_, n2_, n3_, n4_; +}; + +int +main () +{ + xml_schema::int_simpl int_s; + test_1_simpl test_1_s; + test_2_simpl test_2_s; + test_3_simpl test_3_s; + test_4_simpl test_4_s; + root_simpl root_s; + + test_1_s.serializers (int_s, int_s, int_s); + test_2_s.serializers (int_s, int_s); + test_3_s.serializers (int_s, int_s); + test_4_s.serializers (int_s, int_s, int_s, int_s, int_s); + root_s.serializers (test_1_s, test_2_s, test_3_s, test_4_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/choice/makefile b/tests/cxx/serializer/choice/makefile new file mode 100644 index 0000000..41df081 --- /dev/null +++ b/tests/cxx/serializer/choice/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/choice/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/choice/output b/tests/cxx/serializer/choice/output new file mode 100644 index 0000000..78a615a --- /dev/null +++ b/tests/cxx/serializer/choice/output @@ -0,0 +1 @@ +123234123234123234123234123234345456 \ No newline at end of file diff --git a/tests/cxx/serializer/choice/test.xsd b/tests/cxx/serializer/choice/test.xsd new file mode 100644 index 0000000..2d7e33d --- /dev/null +++ b/tests/cxx/serializer/choice/test.xsd @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/complex/driver.cxx b/tests/cxx/serializer/complex/driver.cxx new file mode 100644 index 0000000..d27aee1 --- /dev/null +++ b/tests/cxx/serializer/complex/driver.cxx @@ -0,0 +1,87 @@ +// file : tests/cxx/serializer/complex/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test complex types serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct base_simpl: virtual base_sskel +{ + virtual int + x () + { + return 123; + } + + virtual int + y () + { + return 234; + } + + virtual int + a () + { + return -123; + } + + virtual int + b () + { + return -234; + } +}; + +struct derived_simpl: derived_sskel +{ + derived_simpl () + : derived_sskel (&base_impl_) + { + } + + virtual int + z () + { + return 345; + } + + virtual int + c () + { + return -345; + } + +private: + base_simpl base_impl_; +}; + +struct root_simpl: virtual root_sskel +{ +}; + +int +main () +{ + xml_schema::int_simpl int_s; + base_simpl base_s; + derived_simpl derived_s; + root_simpl root_s; + + base_s.serializers (int_s, int_s, int_s, int_s); + derived_s.serializers (int_s, int_s, int_s, int_s, int_s, int_s); + root_s.serializers (base_s, derived_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/complex/makefile b/tests/cxx/serializer/complex/makefile new file mode 100644 index 0000000..75da9e3 --- /dev/null +++ b/tests/cxx/serializer/complex/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/complex/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/complex/output b/tests/cxx/serializer/complex/output new file mode 100644 index 0000000..82a19b6 --- /dev/null +++ b/tests/cxx/serializer/complex/output @@ -0,0 +1 @@ +-123-234-123-234-345 \ No newline at end of file diff --git a/tests/cxx/serializer/complex/test.xsd b/tests/cxx/serializer/complex/test.xsd new file mode 100644 index 0000000..c209b92 --- /dev/null +++ b/tests/cxx/serializer/complex/test.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/enumeration/boolean.hxx b/tests/cxx/serializer/enumeration/boolean.hxx new file mode 100644 index 0000000..b648a56 --- /dev/null +++ b/tests/cxx/serializer/enumeration/boolean.hxx @@ -0,0 +1,15 @@ +// file : tests/cxx/serializer/enumeration/boolean.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef BOOLEAN_HXX +#define BOOLEAN_HXX + +enum boolean +{ + FALSE, + TRUE +}; + +#endif // BOOLEAN_HXX diff --git a/tests/cxx/serializer/enumeration/driver.cxx b/tests/cxx/serializer/enumeration/driver.cxx new file mode 100644 index 0000000..ae200ae --- /dev/null +++ b/tests/cxx/serializer/enumeration/driver.cxx @@ -0,0 +1,74 @@ +// file : tests/cxx/serializer/enumeration/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test enumeration type serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct digit_simpl: digit_sskel +{ + digit_simpl () + : digit_sskel (&base_impl_) + { + } + +private: + xml_schema::int_simpl base_impl_; +}; + +struct boolean_simpl: boolean_sskel +{ + boolean_simpl () + : boolean_sskel (&base_impl_) + { + } + + virtual void + pre (boolean b) + { + int i = b; + base_impl_.pre (i); + } + +private: + xml_schema::int_simpl base_impl_; +}; + +struct root_simpl: root_sskel +{ + virtual int + digit () + { + return 7; + } + + virtual ::boolean + boolean () + { + return TRUE; + } +}; + +int +main () +{ + digit_simpl digit_s; + boolean_simpl boolean_s; + root_simpl root_s; + + root_s.serializers (digit_s, boolean_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/enumeration/makefile b/tests/cxx/serializer/enumeration/makefile new file mode 100644 index 0000000..2ccb073 --- /dev/null +++ b/tests/cxx/serializer/enumeration/makefile @@ -0,0 +1,75 @@ +# file : tests/cxx/serializer/enumeration/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 := test.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 +test := $(out_base)/.test +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)/test.map + +$(skel): $(out_root)/xsde/xsde $(src_base)/test.map + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/enumeration/output b/tests/cxx/serializer/enumeration/output new file mode 100644 index 0000000..4907042 --- /dev/null +++ b/tests/cxx/serializer/enumeration/output @@ -0,0 +1 @@ +71 \ No newline at end of file diff --git a/tests/cxx/serializer/enumeration/test.map b/tests/cxx/serializer/enumeration/test.map new file mode 100644 index 0000000..73f5d25 --- /dev/null +++ b/tests/cxx/serializer/enumeration/test.map @@ -0,0 +1,7 @@ +namespace test +{ + include "boolean.hxx"; + + digit int int; + boolean ::boolean ::boolean; +} diff --git a/tests/cxx/serializer/enumeration/test.xsd b/tests/cxx/serializer/enumeration/test.xsd new file mode 100644 index 0000000..c130f75 --- /dev/null +++ b/tests/cxx/serializer/enumeration/test.xsd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/error-handling/codes/driver.cxx b/tests/cxx/serializer/error-handling/codes/driver.cxx new file mode 100644 index 0000000..ba1f6cd --- /dev/null +++ b/tests/cxx/serializer/error-handling/codes/driver.cxx @@ -0,0 +1,327 @@ +// file : tests/cxx/serializer/error-handling/codes/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test error reporting with error codes. +// + +#include +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +// bool fail = true; + +struct test_simpl: virtual test_sskel +{ + test_simpl (int c) + : case_ (c) + { + } + + virtual void + pre () + { + if (case_ == 6) + _app_error (case_); + + n_ = 0; + } + + virtual void + _pre () + { + if (case_ == 7) + _app_error (case_); + + if (case_ == 19) + _end_element (); + } + + // Attributes. + // + virtual bool + x_present () + { + if (case_ == 8) + { + _app_error (case_); + return false; + } + + return true; + } + + virtual int + x () + { + if (case_ == 9) + _app_error (case_); + + return -1; + } + + virtual int + y () + { + if (case_ == 10) + _app_error (case_); + + return -2; + } + + // Elements. + // + virtual int + a () + { + if (case_ == 11) + _app_error (case_); + + return 1; + } + + virtual bool + b_present () + { + if (case_ == 12) + { + _app_error (case_); + return false; + } + + return true; + } + + virtual int + b () + { + if (case_ == 13) + _app_error (case_); + + return 2; + } + + virtual bool + c_next () + { + if (case_ == 14) + { + _app_error (case_); + return false; + } + + return n_++ < 3; + } + + virtual int + c () + { + if (case_ == 15) + _app_error (case_); + + return 2 + n_; + } + + virtual void + _post () + { + if (case_ == 16) + _app_error (case_); + } + + virtual void + post () + { + if (case_ == 17) + _app_error (case_); + } + +private: + int case_; + int n_; +}; + +struct root_simpl: root_sskel +{ + root_simpl (int c) + : case_ (c) + { + } + + virtual void + pre () + { + if (case_ == 1) + _app_error (case_); + } + + virtual void + _pre () + { + if (case_ == 2) + _app_error (case_); + } + + virtual void + test () + { + if (case_ == 3) + _app_error (case_); + } + + virtual void + _post () + { + if (case_ == 4) + _app_error (case_); + } + + virtual void + post () + { + if (case_ == 5) + _app_error (case_); + } + +private: + int case_; +}; + +struct writer: xml_schema::writer +{ + virtual bool + write (const char*, size_t) + { + return false; + } + + virtual bool + flush () + { + return false; + } +}; + + +void +print (xml_schema::serializer_error e) +{ + typedef xml_schema::serializer_error error; + + switch (e.type ()) + { + case error::sys: + { + cout << "sys: " << e.sys_code () << ": " << e.sys_text () << endl; + break; + } + case error::xml: + { + cout << "xml: " << e.xml_code () << ": " << e.xml_text () << endl; + break; + } +#ifdef XSDE_SERIALIZER_VALIDATION + case error::schema: + { + cout << "schema: " << e.schema_code () << ": " << e.schema_text () + << endl; + break; + } +#endif + case error::app: + { + cout << "app: " << e.app_code () << endl; + break; + } + default: + { + cout << "no error" << endl; + } + } +} + +int +main () +{ + typedef xml_schema::serializer_error error; + + /* + string output ("" + "12345"); + */ + + // 1-5 : app errors in the root element serializer + // 6-17: app errors in the sub element serializer + // 18 : xml error in document serializer + // 19 : xml error in sub element serializer + // 20 : sys error + // + for (int i (1); i <= 20; ++i) + { + xml_schema::int_simpl int_s; + test_simpl test_s (i); + root_simpl root_s (i); + + test_s.serializers (int_s, int_s, int_s, int_s, int_s); + root_s.serializers (test_s); + + xml_schema::document_simpl doc_s ( + root_s, + "test", + (i == 18 ? "bad name" : "root")); + + root_s.pre (); + + if (error e = root_s._error ()) + print (e); + else + { + ostringstream os; + + if (i == 20) + { + writer w; + doc_s.serialize (w); + } + else + doc_s.serialize (os); + + if (error e = doc_s._error ()) + print (e); + else + { + root_s.post (); + + if (error e = root_s._error ()) + print (e); + } + } + + /* + { + fail = false; + + ostringstream os; + + root_s.pre (); + assert (!root_s.error ()); + + doc_s.serialize (os); + assert (!doc_s._error ()); + + root_s.post (); + assert (!root_s.error ()); + + assert (os.str () == output); + + fail = true; + } + */ + } +} diff --git a/tests/cxx/serializer/error-handling/codes/makefile b/tests/cxx/serializer/error-handling/codes/makefile new file mode 100644 index 0000000..bdaca6c --- /dev/null +++ b/tests/cxx/serializer/error-handling/codes/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/error-handling/codes/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/error-handling/codes/output b/tests/cxx/serializer/error-handling/codes/output new file mode 100644 index 0000000..c01aab9 --- /dev/null +++ b/tests/cxx/serializer/error-handling/codes/output @@ -0,0 +1,20 @@ +app: 1 +app: 2 +app: 3 +app: 4 +app: 5 +app: 6 +app: 7 +app: 8 +app: 9 +app: 10 +app: 11 +app: 12 +app: 13 +app: 14 +app: 15 +app: 16 +app: 17 +xml: 3: illegal name +xml: 8: call out of sequence +sys: 4: write failed diff --git a/tests/cxx/serializer/error-handling/codes/test.xsd b/tests/cxx/serializer/error-handling/codes/test.xsd new file mode 100644 index 0000000..530118c --- /dev/null +++ b/tests/cxx/serializer/error-handling/codes/test.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/error-handling/exceptions/driver.cxx b/tests/cxx/serializer/error-handling/exceptions/driver.cxx new file mode 100644 index 0000000..3a7437b --- /dev/null +++ b/tests/cxx/serializer/error-handling/exceptions/driver.cxx @@ -0,0 +1,285 @@ +// file : tests/cxx/serializer/error-handling/exceptions/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test error reporting with exceptions. +// + +#include +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct app +{ + app (int code) + : code_ (code) + { + } + + int + code () const + { + return code_; + } + +private: + int code_; +}; + +struct test_simpl: virtual test_sskel +{ + test_simpl (int c) + : case_ (c) + { + } + + virtual void + pre () + { + if (case_ == 6) + throw app (case_); + + n_ = 0; + } + + virtual void + _pre () + { + if (case_ == 7) + throw app (case_); + + if (case_ == 19) + _end_element (); + } + + // Attributes. + // + virtual bool + x_present () + { + if (case_ == 8) + { + throw app (case_); + return false; + } + + return true; + } + + virtual int + x () + { + if (case_ == 9) + throw app (case_); + + return -1; + } + + virtual int + y () + { + if (case_ == 10) + throw app (case_); + + return -2; + } + + // Elements. + // + virtual int + a () + { + if (case_ == 11) + throw app (case_); + + return 1; + } + + virtual bool + b_present () + { + if (case_ == 12) + { + throw app (case_); + return false; + } + + return true; + } + + virtual int + b () + { + if (case_ == 13) + throw app (case_); + + return 2; + } + + virtual bool + c_next () + { + if (case_ == 14) + { + throw app (case_); + return false; + } + + return n_++ < 3; + } + + virtual int + c () + { + if (case_ == 15) + throw app (case_); + + return 2 + n_; + } + + virtual void + _post () + { + if (case_ == 16) + throw app (case_); + } + + virtual void + post () + { + if (case_ == 17) + throw app (case_); + } + +private: + int case_; + int n_; +}; + +struct root_simpl: root_sskel +{ + root_simpl (int c) + : case_ (c) + { + } + + virtual void + pre () + { + if (case_ == 1) + throw app (case_); + } + + virtual void + _pre () + { + if (case_ == 2) + throw app (case_); + } + + virtual void + test () + { + if (case_ == 3) + throw app (case_); + } + + virtual void + _post () + { + if (case_ == 4) + throw app (case_); + } + + virtual void + post () + { + if (case_ == 5) + throw app (case_); + } + +private: + int case_; +}; + +struct writer: xml_schema::writer +{ + virtual void + write (const char*, size_t) + { + throw ios_base::failure ("write failed"); + } + + virtual void + flush () + { + throw ios_base::failure ("write failed"); + } +}; + +int +main () +{ + + // 1-5 : app errors in the root element serializer + // 6-17: app errors in the sub element serializer + // 18 : xml error in document serializer + // 19 : xml error in sub element serializer + // 20 : sys error + // + for (int i (1); i <= 20; ++i) + { + try + { + xml_schema::int_simpl int_s; + test_simpl test_s (i); + root_simpl root_s (i); + + test_s.serializers (int_s, int_s, int_s, int_s, int_s); + root_s.serializers (test_s); + + xml_schema::document_simpl doc_s ( + root_s, + "test", + (i == 18 ? "bad name" : "root")); + + root_s.pre (); + + ostringstream os; + + if (i == 20) + { + writer w; + doc_s.serialize (w); + } + else + doc_s.serialize (os); + + root_s.post (); + } + catch (ios_base::failure const&) + { + cout << "sys: write failed" << endl; + } + catch (xml_schema::serializer_xml const& e) + { + cout << "xml: " << e.text () << endl; + } +#ifdef XSDE_SERIALIZER_VALIDATION + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + } +#endif + catch (app const& e) + { + cout << "app: " << e.code () << endl; + } + } +} diff --git a/tests/cxx/serializer/error-handling/exceptions/makefile b/tests/cxx/serializer/error-handling/exceptions/makefile new file mode 100644 index 0000000..19027cc --- /dev/null +++ b/tests/cxx/serializer/error-handling/exceptions/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/error-handling/exceptions/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/error-handling/exceptions/output b/tests/cxx/serializer/error-handling/exceptions/output new file mode 100644 index 0000000..e640bd6 --- /dev/null +++ b/tests/cxx/serializer/error-handling/exceptions/output @@ -0,0 +1,20 @@ +app: 1 +app: 2 +app: 3 +app: 4 +app: 5 +app: 6 +app: 7 +app: 8 +app: 9 +app: 10 +app: 11 +app: 12 +app: 13 +app: 14 +app: 15 +app: 16 +app: 17 +xml: illegal name +xml: call out of sequence +sys: write failed diff --git a/tests/cxx/serializer/error-handling/exceptions/test.xsd b/tests/cxx/serializer/error-handling/exceptions/test.xsd new file mode 100644 index 0000000..530118c --- /dev/null +++ b/tests/cxx/serializer/error-handling/exceptions/test.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/error-handling/makefile b/tests/cxx/serializer/error-handling/makefile new file mode 100644 index 0000000..03597f5 --- /dev/null +++ b/tests/cxx/serializer/error-handling/makefile @@ -0,0 +1,24 @@ +# file : tests/cxx/serializer/error-handling/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 + +ifeq ($(xsde_exceptions),y) +tests := exceptions +else +tests := codes +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/serializer/generated-driver/makefile b/tests/cxx/serializer/generated-driver/makefile new file mode 100644 index 0000000..08957fa --- /dev/null +++ b/tests/cxx/serializer/generated-driver/makefile @@ -0,0 +1,75 @@ +# file : tests/cxx/serializer/generated-driver/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 := test.xsd + +obj := $(addprefix $(out_base)/,$(xsd:.xsd=-sskel.o) $(xsd:.xsd=-simpl.o) $(xsd:.xsd=-sdriver.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=-sdriver) +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.ixx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-sdriver.cxx) + +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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) + +xsd_simpl_suffix := -simpl +$(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/tests/cxx/serializer/generated-driver/output b/tests/cxx/serializer/generated-driver/output new file mode 100644 index 0000000..d544e67 --- /dev/null +++ b/tests/cxx/serializer/generated-driver/output @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/tests/cxx/serializer/generated-driver/test-simpl.cxx b/tests/cxx/serializer/generated-driver/test-simpl.cxx new file mode 100644 index 0000000..7acda2c --- /dev/null +++ b/tests/cxx/serializer/generated-driver/test-simpl.cxx @@ -0,0 +1,28 @@ +// file : tests/cxx/serializer/generated-driver/test-simpl.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include "test-simpl.hxx" + +namespace test +{ + // type_simpl + // + + void type_simpl:: + pre () + { + } + + int type_simpl:: + value () + { + return 123; + } + + void type_simpl:: + post () + { + } +} diff --git a/tests/cxx/serializer/generated-driver/test-simpl.hxx b/tests/cxx/serializer/generated-driver/test-simpl.hxx new file mode 100644 index 0000000..4700a9f --- /dev/null +++ b/tests/cxx/serializer/generated-driver/test-simpl.hxx @@ -0,0 +1,27 @@ +// file : tests/cxx/serializer/generated-driver/test-simpl.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef TEST_SIMPL_HXX +#define TEST_SIMPL_HXX + +#include "test-sskel.hxx" + +namespace test +{ + class type_simpl: public virtual type_sskel + { + public: + virtual void + pre (); + + virtual int + value (); + + virtual void + post (); + }; +} + +#endif // TEST_SIMPL_HXX diff --git a/tests/cxx/serializer/generated-driver/test.xsd b/tests/cxx/serializer/generated-driver/test.xsd new file mode 100644 index 0000000..7ceb607 --- /dev/null +++ b/tests/cxx/serializer/generated-driver/test.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/cxx/serializer/generated-impl/makefile b/tests/cxx/serializer/generated-impl/makefile new file mode 100644 index 0000000..fc6c6b9 --- /dev/null +++ b/tests/cxx/serializer/generated-impl/makefile @@ -0,0 +1,84 @@ +# file : tests/cxx/serializer/generated-impl/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 + +# Note that this test only checks compilation of the generated empty +# implementation and test driver. It may not work with some compilers +# (missing return statements). +# + +xsd := test.xsd + +obj := $(addprefix $(out_base)/,$(xsd:.xsd=-sskel.o) $(xsd:.xsd=-simpl.o) $(xsd:.xsd=-sdriver.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=-sdriver) +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +gen := $(out_base)/$(xsd:.xsd=-sskel.hxx) \ + $(out_base)/$(xsd:.xsd=-sskel.ixx) \ + $(out_base)/$(xsd:.xsd=-sskel.cxx) \ + $(out_base)/$(xsd:.xsd=-simpl.hxx) \ + $(out_base)/$(xsd:.xsd=-simpl.cxx) \ + $(out_base)/$(xsd:.xsd=-sdriver.cxx) + +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-empty-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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,:,$(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)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=-simpl.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_simpl_suffix := -simpl +$(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/tests/cxx/serializer/generated-impl/test.xsd b/tests/cxx/serializer/generated-impl/test.xsd new file mode 100644 index 0000000..f38c005 --- /dev/null +++ b/tests/cxx/serializer/generated-impl/test.xsd @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/list/driver.cxx b/tests/cxx/serializer/list/driver.cxx new file mode 100644 index 0000000..7ed5ee1 --- /dev/null +++ b/tests/cxx/serializer/list/driver.cxx @@ -0,0 +1,114 @@ +// file : tests/cxx/serializer/list/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test list type serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct int_list_simpl: int_list_sskel +{ + int_list_simpl () + : n_ (0) + { + } + + virtual void + pre () + { + i_ = 0; + n_++; + } + + virtual bool + item_next () + { + switch (n_) + { + case 1: + return false; + case 2: + return i_++ < 1; + case 3: + return i_++ < 3; + default: + return false; + } + } + + virtual int + item () + { + return i_; + } + +private: + int n_, i_; +}; + +struct int_list_base_simpl: int_list_base_sskel +{ + int_list_base_simpl () + : int_list_base_sskel (&base_impl_) + { + } + + virtual int + base () + { + return 123; + } + +private: + int_list_simpl base_impl_; +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + n_ = 0; + } + + virtual bool + int_list_next () + { + return n_++ < 3; + } + + virtual bool + int_list_base_next () + { + return n_++ < 7; + } + +private: + int n_; +}; + +int +main () +{ + xml_schema::int_simpl int_s; + int_list_simpl int_list_s; + int_list_base_simpl int_list_base_s; + root_simpl root_s; + + int_list_s.serializers (int_s); + int_list_base_s.serializers (int_s, int_s); + root_s.serializers (int_list_s, int_list_base_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/list/makefile b/tests/cxx/serializer/list/makefile new file mode 100644 index 0000000..6d5a876 --- /dev/null +++ b/tests/cxx/serializer/list/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/list/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/list/output b/tests/cxx/serializer/list/output new file mode 100644 index 0000000..c1ef004 --- /dev/null +++ b/tests/cxx/serializer/list/output @@ -0,0 +1 @@ +11 2 311 2 3 \ No newline at end of file diff --git a/tests/cxx/serializer/list/test.xsd b/tests/cxx/serializer/list/test.xsd new file mode 100644 index 0000000..d4aff01 --- /dev/null +++ b/tests/cxx/serializer/list/test.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/makefile b/tests/cxx/serializer/makefile new file mode 100644 index 0000000..8d72167 --- /dev/null +++ b/tests/cxx/serializer/makefile @@ -0,0 +1,52 @@ +# file : tests/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 + +tests := generated-driver generated-impl + +ifeq ($(xsde_iostream),y) + +tests += \ +all \ +built-in \ +choice \ +error-handling \ +recursive \ +reset \ +restriction \ +sequence \ +test-template \ +wildcard + +ifeq ($(xsde_reuse_style),tiein) +tests += \ +complex \ +enumeration \ +list \ +union +endif + +ifeq ($(xsde_polymorphic),y) +tests += polymorphism +endif + +endif # xsde_iostream + +ifeq ($(xsde_serializer_validation),y) +tests += validation +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/serializer/polymorphism/driver.cxx b/tests/cxx/serializer/polymorphism/driver.cxx new file mode 100644 index 0000000..ebb0244 --- /dev/null +++ b/tests/cxx/serializer/polymorphism/driver.cxx @@ -0,0 +1,203 @@ +// file : tests/cxx/serializer/polymorphism/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test substitution groups and xsi:type support. +// +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct base_simpl: base_sskel +{ + virtual int + a () + { + return 1; + } +}; + +struct interm_type_simpl: interm_type_sskel +{ + interm_type_simpl () + : interm_type_sskel (&base_impl_) + { + } + + virtual int + b () + { + return 2; + } + + base_simpl base_impl_; +}; + +struct interm_simpl: interm_sskel +{ + interm_simpl () + : interm_sskel (&base_impl_) + { + } + + virtual int + b () + { + return 2; + } + + base_simpl base_impl_; +}; + +struct derived_type_simpl: derived_type_sskel +{ + derived_type_simpl () + : derived_type_sskel (&base_impl_) + { + } + + virtual int + c () + { + return 3; + } + + interm_type_simpl base_impl_; +}; + +struct derived_simpl: derived_sskel +{ + derived_simpl () + : derived_sskel (&base_impl_) + { + } + + virtual int + c () + { + return 3; + } + + interm_simpl base_impl_; +}; + +struct type_simpl: type_sskel +{ + virtual void + pre () + { + i_ = 0; + } + + virtual bool + base_next () + { + return i_ < 5; + } + + virtual void + base () + { + xml_schema::serializer_context& ctx = _context (); + + switch (i_++) + { + case 0: + { + ctx.type_id (base_sskel::_static_type ()); + break; + } + case 1: + { + ctx.type_id (interm_type_sskel::_static_type ()); + break; + } + case 2: + { + ctx.type_id (interm_sskel::_static_type ()); + break; + } + case 3: + { + ctx.type_id (derived_type_sskel::_static_type ()); + break; + } + case 4: + { + ctx.type_id (derived_sskel::_static_type ()); + break; + } + } + } + +private: + int i_; +}; + +int +main () +{ +#ifdef XSDE_EXCEPTIONS + try + { +#endif + xml_schema::int_simpl int_s; + + base_simpl base_s; + interm_type_simpl interm_type_s; + interm_simpl interm_s; + derived_type_simpl derived_type_s; + derived_simpl derived_s; + + xml_schema::serializer_map_impl map (7); + type_simpl type_s; + + base_s.serializers (int_s); + interm_type_s.serializers (int_s, int_s); + interm_s.serializers (int_s, int_s); + derived_s.serializers (int_s, int_s, int_s); + derived_type_s.serializers (int_s, int_s, int_s); + + map.insert (base_s); + map.insert (interm_type_s); + map.insert (interm_s); + map.insert (derived_s); + map.insert (derived_type_s); + + type_s.base_serializer (map); + + xml_schema::document_simpl doc_s (type_s, "test", "root", true); + + doc_s.add_prefix ("t", "test"); + doc_s.add_prefix ("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + + type_s.pre (); + doc_s.serialize (cout); + +#ifndef XSDE_EXCEPTIONS + if (doc_s._error ()) + { + cerr << "error" << endl; + return 1; + } +#endif + + type_s.post (); + + // Test serializer resetting. + // + doc_s.reset (); + +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_exception const& e) + { + cerr << e << endl; + return 1; + } +#endif +} diff --git a/tests/cxx/serializer/polymorphism/makefile b/tests/cxx/serializer/polymorphism/makefile new file mode 100644 index 0000000..ff2ccbe --- /dev/null +++ b/tests/cxx/serializer/polymorphism/makefile @@ -0,0 +1,73 @@ +# file : tests/cxx/serializer/polymorphism/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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 +$(skel): $(out_root)/xsde/xsde + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/polymorphism/output b/tests/cxx/serializer/polymorphism/output new file mode 100644 index 0000000..5107439 --- /dev/null +++ b/tests/cxx/serializer/polymorphism/output @@ -0,0 +1 @@ +11212123123 \ No newline at end of file diff --git a/tests/cxx/serializer/polymorphism/test.xsd b/tests/cxx/serializer/polymorphism/test.xsd new file mode 100644 index 0000000..d6aa1e3 --- /dev/null +++ b/tests/cxx/serializer/polymorphism/test.xsd @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/recursive/driver.cxx b/tests/cxx/serializer/recursive/driver.cxx new file mode 100644 index 0000000..c474191 --- /dev/null +++ b/tests/cxx/serializer/recursive/driver.cxx @@ -0,0 +1,135 @@ +// file : tests/cxx/serializer/recursive/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test recursive type serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; + +struct sub_type_simpl: virtual sub_type_sskel +{ + sub_type_simpl () + : n_ (0) + { + } + + virtual void + pre () + { + n_++; + } + + // Attributes. + // + virtual bool + name_present () + { + return true; + } + + virtual int + name () + { + return n_; + } + + // Elements. + // + virtual bool + sub_present () + { + return n_ == 1; + } + + virtual bool + indir_present () + { + return n_ == 1; + } + + virtual bool + sub2_present () + { + return n_ == 1; + } + + virtual void + post () + { + n_--; + } + +private: + int n_; +}; + +struct indir_type_simpl: virtual indir_type_sskel +{ + // Attributes. + // + virtual bool + name_present () + { + return true; + } + + virtual int + name () + { + return 123; + } + + // Elements. + // + virtual bool + sub_present () + { + return true; + } +}; + +struct test_type_simpl: virtual test_type_sskel +{ + // Attributes. + // + virtual bool + name_present () + { + return true; + } + + virtual int + name () + { + return 234; + } +}; + +int +main () +{ + xml_schema::int_simpl int_s; + sub_type_simpl sub_s; + indir_type_simpl indir_s; + test_type_simpl test_s; + + sub_s.serializers (int_s, sub_s, indir_s, sub_s); + indir_s.serializers (int_s, sub_s); + test_s.serializers (int_s, sub_s); + + xml_schema::document_simpl doc_s (test_s, "test", "root"); + + test_s.pre (); + doc_s.serialize (cout); + test_s.post (); + + // Test serializer resetting. + // + doc_s.reset (); +} diff --git a/tests/cxx/serializer/recursive/makefile b/tests/cxx/serializer/recursive/makefile new file mode 100644 index 0000000..4de9d93 --- /dev/null +++ b/tests/cxx/serializer/recursive/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/recursive/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/recursive/output b/tests/cxx/serializer/recursive/output new file mode 100644 index 0000000..717654f --- /dev/null +++ b/tests/cxx/serializer/recursive/output @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/cxx/serializer/recursive/test.xsd b/tests/cxx/serializer/recursive/test.xsd new file mode 100644 index 0000000..0e915c9 --- /dev/null +++ b/tests/cxx/serializer/recursive/test.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/reset/driver.cxx b/tests/cxx/serializer/reset/driver.cxx new file mode 100644 index 0000000..49e5d32 --- /dev/null +++ b/tests/cxx/serializer/reset/driver.cxx @@ -0,0 +1,281 @@ +// file : tests/cxx/serializer/reset/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test serializer resetting. +// + +#include + +#include +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +bool fail = true; + +struct error {}; + +#ifdef XSDE_REUSE_STYLE_MIXIN +struct base_simpl: virtual base_sskel +#else +struct base_simpl: base_sskel +#endif +{ + base_simpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { +#ifndef XSDE_EXCEPTIONS + assert (!_error ()); +#endif + + if (fail && i_ == 3) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: + unsigned long i_; +}; + +#ifdef XSDE_REUSE_STYLE_MIXIN +struct inner_simpl: inner_sskel, base_simpl +#else +struct inner_simpl: inner_sskel +#endif +{ + inner_simpl (unsigned long i) +#ifdef XSDE_REUSE_STYLE_MIXIN + : base_simpl (i), i_ (i) +#else + : inner_sskel (&base_impl_), base_impl_ (i), i_ (i) +#endif + { + } + + virtual void + _pre () + { + n_ = 0; + } + + virtual bool + b_next () + { + if (fail && i_ == 6) + { +#ifdef XSDE_SERIALIZER_VALIDATION + return false; +#else +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + return true; +#endif + } + + return n_++ == 0; + } + + virtual int + b () + { + if (fail && i_ == 4) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + + return 1; + } + + virtual void + post () + { + if (fail && i_ == 5) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: +#ifdef XSDE_REUSE_STYLE_TIEIN + base_simpl base_impl_; +#endif + unsigned long i_; + unsigned long n_; +}; + +struct type_simpl: type_sskel +{ + type_simpl (unsigned long i) + : i_ (i) + { + } + + virtual void + pre () + { + if (fail && i_ == 0) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + + virtual void + a () + { + if (fail && i_ == 1) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + + virtual void + post () + { + if (fail && i_ == 2) + { +#ifdef XSDE_EXCEPTIONS + throw error (); +#else + _app_error (1); +#endif + } + } + +private: + unsigned long i_; +}; + +int +main () +{ + try + { + for (unsigned long i (0); i < 7; ++i) + { + xml_schema::int_simpl int_s; + inner_simpl inner_s (i); + type_simpl type_s (i); + + inner_s.serializers (int_s); + type_s.serializers (inner_s); + + xml_schema::document_simpl doc_s (type_s, "test", "root"); + + doc_s.add_prefix ("t", "test"); + doc_s.add_schema ("test", "test.xsd"); + + ostringstream ostr; + + cout << i << ": "; + +#ifdef XSDE_EXCEPTIONS + try + { + fail = true; + + type_s.pre (); + doc_s.serialize (ostr); + type_s.post (); + assert (false); + } + catch (error const&) + { + } + catch (xml_schema::serializer_exception const&) + { + } + + fail = false; + doc_s.reset (); + + type_s.pre (); + doc_s.serialize (cout); + type_s.post (); +#else + do + { + fail = true; + + type_s.pre (); + + if (type_s._error ()) + break; + + doc_s.serialize (ostr); + + if (doc_s._error ()) + break; + + type_s.post (); + + if (type_s._error ()) + break; + + assert (false); + } + while (false); + + fail = false; + doc_s.reset (); + + type_s.pre (); + assert (!type_s._error ()); + + doc_s.serialize (cout); + assert (!doc_s._error ()); + + type_s.post (); + assert (!type_s._error ()); +#endif + + cout << endl; + } + } +#ifdef XSDE_EXCEPTIONS + catch (xml_schema::serializer_exception const& e) + { + cerr << e << endl; + return 1; + } +#endif + catch (std::ios_base::failure const&) + { + cerr << "io failure" << endl; + return 1; + } +} diff --git a/tests/cxx/serializer/reset/makefile b/tests/cxx/serializer/reset/makefile new file mode 100644 index 0000000..2d87e58 --- /dev/null +++ b/tests/cxx/serializer/reset/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/reset/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/reset/output b/tests/cxx/serializer/reset/output new file mode 100644 index 0000000..8e0b569 --- /dev/null +++ b/tests/cxx/serializer/reset/output @@ -0,0 +1,7 @@ +0: 1 +1: 1 +2: 1 +3: 1 +4: 1 +5: 1 +6: 1 diff --git a/tests/cxx/serializer/reset/test.xsd b/tests/cxx/serializer/reset/test.xsd new file mode 100644 index 0000000..f368fa0 --- /dev/null +++ b/tests/cxx/serializer/reset/test.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/restriction/driver.cxx b/tests/cxx/serializer/restriction/driver.cxx new file mode 100644 index 0000000..0430765 --- /dev/null +++ b/tests/cxx/serializer/restriction/driver.cxx @@ -0,0 +1,246 @@ +// file : tests/cxx/serializer/restriction/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test inheritance-by-restriction serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: test_1_sskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + test_1_simpl () + : test_1_sskel (0) + { + } +#endif + + virtual int + optional () + { + return 123; + } + + virtual int + required () + { + return 234; + } +}; + +struct test_2_simpl: test_2_sskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + test_2_simpl () + : test_2_sskel (0) + { + } +#endif + + virtual void + pre () + { + i_ = 0; + } + + virtual int + a () + { + return 1; + } + + virtual bool + sequence_next () + { + return i_++ < 1; + } + + virtual int + b () + { + return 2; + } + + virtual int + c () + { + return 3; + } + + virtual choice_arm_tag + choice_arm () + { + return e_tag; + } + + virtual int + d () + { + return 4; + } + + virtual int + e () + { + return 5; + } + +private: + int i_; +}; + +struct test_3_simpl: test_3_sskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + test_3_simpl () + : test_3_sskel (0) + { + } +#endif + + virtual int + a () + { + return 1; + } + + virtual int + b () + { + return 2; + } + + virtual int + c () + { + return 3; + } + + virtual int + d () + { + return 4; + } + + virtual choice_arm_tag + choice_arm () + { + return g_tag; + } + + virtual int + e () + { + return 5; + } + + virtual int + f () + { + return 6; + } + + virtual int + g () + { + return 7; + } + +private: + int i_; +}; + +struct test_4_simpl: test_4_sskel +{ +#ifdef XSDE_REUSE_STYLE_TIEIN + test_4_simpl () + : test_4_sskel (0) + { + } +#endif + + virtual int + a () + { + return 1; + } + + virtual int + b () + { + return 2; + } + + virtual int + c () + { + return 3; + } + + virtual int + d () + { + return 4; + } + + virtual choice_arm_tag + choice_arm () + { + return g_tag; + } + + virtual int + e () + { + return 5; + } + + virtual int + f () + { + return 6; + } + + virtual int + g () + { + return 7; + } + +private: + int i_; +}; + +struct root_simpl: root_sskel +{ +}; + +int +main () +{ + xml_schema::int_simpl int_s; + test_1_simpl test_1_s; + test_2_simpl test_2_s; + test_3_simpl test_3_s; + test_4_simpl test_4_s; + root_simpl root_s; + + test_1_s.serializers (int_s, int_s); + test_2_s.serializers (int_s, int_s, int_s, int_s, int_s); + test_3_s.serializers (int_s, int_s, int_s, int_s, int_s, int_s, int_s); + test_4_s.serializers (int_s, int_s, int_s, int_s, int_s, int_s, int_s); + root_s.serializers (test_1_s, test_2_s, test_3_s, test_4_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/restriction/makefile b/tests/cxx/serializer/restriction/makefile new file mode 100644 index 0000000..0a4f081 --- /dev/null +++ b/tests/cxx/serializer/restriction/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/restriction/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/restriction/output b/tests/cxx/serializer/restriction/output new file mode 100644 index 0000000..6cb29b4 --- /dev/null +++ b/tests/cxx/serializer/restriction/output @@ -0,0 +1 @@ +12352727 \ No newline at end of file diff --git a/tests/cxx/serializer/restriction/test.xsd b/tests/cxx/serializer/restriction/test.xsd new file mode 100644 index 0000000..0557e5e --- /dev/null +++ b/tests/cxx/serializer/restriction/test.xsd @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/sequence/driver.cxx b/tests/cxx/serializer/sequence/driver.cxx new file mode 100644 index 0000000..ed6c5fb --- /dev/null +++ b/tests/cxx/serializer/sequence/driver.cxx @@ -0,0 +1,231 @@ +// file : tests/cxx/serializer/sequence/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the sequence compositor serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: test_1_sskel +{ + virtual void + pre () + { + i_ = 0; + } + + virtual int + a () + { + return 123; + } + + virtual bool + b_present () + { + return true; + } + + virtual int + b () + { + return 234; + } + + virtual bool + c_next () + { + return i_++ < 3; + } + + virtual int + c () + { + return i_; + } + +private: + int i_; +}; + +struct test_2_simpl: test_2_sskel +{ + test_2_simpl () + : i_ (0) + { + } + + virtual bool + sequence_present () + { + return i_++; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int i_; +}; + +struct test_3_simpl: test_3_sskel +{ + virtual void + pre () + { + i_ = 0; + } + + virtual bool + sequence_next () + { + return i_++ < 3; + } + + virtual int + a () + { + return 123 + i_; + } + + virtual int + b () + { + return 234 + i_; + } + +private: + int i_; +}; + +struct test_4_simpl: test_4_sskel +{ + virtual void + pre () + { + i_ = 0; + } + + virtual int + a () + { + return 123; + } + + virtual choice_arm_tag + choice_arm () + { + return c_tag; + } + + virtual int + b () + { + return 0; + } + + virtual int + c () + { + return 234; + } + + virtual bool + sequence_next () + { + return i_++ < 3; + } + + virtual int + d () + { + return 345 + i_; + } + + virtual int + e () + { + return 456 + i_; + } + +private: + int i_; +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + n1_ = 0; + n2_ = 0; + n3_ = 0; + n4_ = 0; + } + + virtual bool + test_1_next () + { + return n1_++ < 1; + } + + virtual bool + test_2_next () + { + return n2_++ < 2; + } + + virtual bool + test_3_next () + { + return n3_++ < 1; + } + + virtual bool + test_4_next () + { + return n4_++ < 1; + } + +private: + int n1_, n2_, n3_, n4_; +}; + +int +main () +{ + xml_schema::int_simpl int_s; + test_1_simpl test_1_s; + test_2_simpl test_2_s; + test_3_simpl test_3_s; + test_4_simpl test_4_s; + root_simpl root_s; + + test_1_s.serializers (int_s, int_s, int_s); + test_2_s.serializers (int_s, int_s); + test_3_s.serializers (int_s, int_s); + test_4_s.serializers (int_s, int_s, int_s, int_s, int_s); + root_s.serializers (test_1_s, test_2_s, test_3_s, test_4_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/sequence/makefile b/tests/cxx/serializer/sequence/makefile new file mode 100644 index 0000000..a3a109e --- /dev/null +++ b/tests/cxx/serializer/sequence/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/sequence/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/sequence/output b/tests/cxx/serializer/sequence/output new file mode 100644 index 0000000..a76f191 --- /dev/null +++ b/tests/cxx/serializer/sequence/output @@ -0,0 +1 @@ +123234123123234124235125236126237123234346457347458348459 \ No newline at end of file diff --git a/tests/cxx/serializer/sequence/test.xsd b/tests/cxx/serializer/sequence/test.xsd new file mode 100644 index 0000000..696a1f2 --- /dev/null +++ b/tests/cxx/serializer/sequence/test.xsd @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/test-template/driver.cxx b/tests/cxx/serializer/test-template/driver.cxx new file mode 100644 index 0000000..784f223 --- /dev/null +++ b/tests/cxx/serializer/test-template/driver.cxx @@ -0,0 +1,48 @@ +// file : tests/cxx/serializer/test-template/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Insert test description here. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + } + + virtual int + a () + { + return 1234; + } + + virtual void + post_type () + { + } +}; + +int +main () +{ + xml_schema::int_simpl int_s; + root_simpl root_s; + + root_s.serializers (int_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/test-template/makefile b/tests/cxx/serializer/test-template/makefile new file mode 100644 index 0000000..28e1f5f --- /dev/null +++ b/tests/cxx/serializer/test-template/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/test-template/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/test-template/output b/tests/cxx/serializer/test-template/output new file mode 100644 index 0000000..509a8ed --- /dev/null +++ b/tests/cxx/serializer/test-template/output @@ -0,0 +1 @@ +1234 \ No newline at end of file diff --git a/tests/cxx/serializer/test-template/test.xsd b/tests/cxx/serializer/test-template/test.xsd new file mode 100644 index 0000000..164b72c --- /dev/null +++ b/tests/cxx/serializer/test-template/test.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/cxx/serializer/union/driver.cxx b/tests/cxx/serializer/union/driver.cxx new file mode 100644 index 0000000..566b681 --- /dev/null +++ b/tests/cxx/serializer/union/driver.cxx @@ -0,0 +1,93 @@ +// file : tests/cxx/serializer/union/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test union type serialization. +// + +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct int_bool_union_simpl: virtual int_bool_union_sskel +{ + int_bool_union_simpl () + : n_ (0) + { + } + + virtual void + _serialize_content () + { + if (n_++ == 0) + _characters ("123"); + else + _characters ("false"); + } + +private: + int n_; +}; + +struct int_bool_base_simpl: int_bool_base_sskel +{ + int_bool_base_simpl () + : int_bool_base_sskel (&base_impl_) + { + } + + virtual int + base () + { + return 123; + } + +private: + int_bool_union_simpl base_impl_; +}; + +struct root_simpl: root_sskel +{ + virtual void + pre () + { + n_ = 0; + } + + virtual bool + int_bool_union_next () + { + return n_++ < 2; + } + + virtual bool + int_bool_base_next () + { + return n_++ < 5; + } + +private: + int n_; +}; + +int +main () +{ + xml_schema::int_simpl int_s; + int_bool_union_simpl int_bool_union_s; + int_bool_base_simpl int_bool_base_s; + root_simpl root_s; + + int_bool_base_s.serializers (int_s); + root_s.serializers (int_bool_union_s, int_bool_base_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/union/makefile b/tests/cxx/serializer/union/makefile new file mode 100644 index 0000000..f361564 --- /dev/null +++ b/tests/cxx/serializer/union/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/union/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/union/output b/tests/cxx/serializer/union/output new file mode 100644 index 0000000..70363b0 --- /dev/null +++ b/tests/cxx/serializer/union/output @@ -0,0 +1 @@ +123false123false \ No newline at end of file diff --git a/tests/cxx/serializer/union/test.xsd b/tests/cxx/serializer/union/test.xsd new file mode 100644 index 0000000..b5b7707 --- /dev/null +++ b/tests/cxx/serializer/union/test.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/validation/any/driver.cxx b/tests/cxx/serializer/validation/any/driver.cxx new file mode 100644 index 0000000..ecdf7f8 --- /dev/null +++ b/tests/cxx/serializer/validation/any/driver.cxx @@ -0,0 +1,317 @@ +// file : tests/cxx/serializer/validation/any/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test any validation. +// + +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: virtual test_1_sskel +{ + virtual bool + any_next () + { + return false; + } + + virtual void +#ifdef XSDE_STL + any (std::string&, std::string&) + { +#else + any (const char*&, const char*&, bool&) + { +#endif + } + + virtual void + serialize_any () + { + } +}; + +// ##any +// +struct test_2_simpl: virtual test_2_sskel +{ + virtual void +#ifdef XSDE_STL + any (std::string& ns, std::string& name) + { +#else + any (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + ns = "foo"; + name = ""; + } + + virtual void + serialize_any () + { + } +}; + +// ##other +// +struct test_3_simpl: virtual test_3_sskel +{ + test_3_simpl (int state) + : state_ (state) + { + } + + virtual void +#ifdef XSDE_STL + any (std::string& ns, std::string& name) + { +#else + any (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_) + { + case 2: + { + // target + // + ns = "test"; + name = "x"; + break; + } + case 3: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + + virtual void + serialize_any () + { + } + +private: + int state_; +}; + +// ##local +// +struct test_4_simpl: virtual test_4_sskel +{ + virtual void +#ifdef XSDE_STL + any (std::string& ns, std::string& name) + { +#else + any (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + ns = "foo"; + name = "x"; + } + + virtual void + serialize_any () + { + } +}; + +// ##targetNamespace +// +struct test_5_simpl: virtual test_5_sskel +{ + test_5_simpl (int state) + : state_ (state) + { + } + + virtual void +#ifdef XSDE_STL + any (std::string& ns, std::string& name) + { +#else + any (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_++) + { + case 5: + { + // target + // + ns = "foo"; + name = "x"; + break; + } + case 6: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + + virtual void + serialize_any () + { + } + +private: + int state_; +}; + +// foo +// +struct test_6_simpl: virtual test_6_sskel +{ + test_6_simpl (int state) + : state_ (state) + { + } + + virtual void +#ifdef XSDE_STL + any (std::string& ns, std::string& name) + { +#else + any (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_++) + { + case 7: + { + // bar + // + ns = "bar"; + name = "x"; + break; + } + case 8: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + + virtual void + serialize_any () + { + } + +private: + int state_; +}; + +struct root_simpl: root_sskel +{ + root_simpl (int state) + : state_ (state) + { + } + + virtual choice_arm_tag + choice_arm () + { + switch (state_) + { + case 0: + return test_1_tag; + case 1: + return test_2_tag; + case 2: + case 3: + return test_3_tag; + case 4: + return test_4_tag; + case 5: + case 6: + return test_5_tag; + case 7: + case 8: + return test_5_tag; + default: + return choice_arm_tag (state_); + } + } + +private: + int state_; +}; + +int +main () +{ + for (int i = 0; i < 9; ++i) + { +#ifdef XSDE_EXCEPTIONS + try + { +#endif + test_1_simpl test_1_s; + test_2_simpl test_2_s; + test_3_simpl test_3_s (i); + test_4_simpl test_4_s; + test_5_simpl test_5_s (i); + test_6_simpl test_6_s (i); + root_simpl root_s (i); + + root_s.serializers (test_1_s, test_2_s, test_3_s, test_4_s, + test_5_s, test_6_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + + ostringstream os; + doc_s.serialize (os); + +#ifndef XSDE_EXCEPTIONS + if (xml_schema::serializer_error e = doc_s._error ()) + { + if (e.type () == xml_schema::serializer_error::schema) + { + cout << "schema: " << e.schema_text () << endl; + continue; + } + } +#endif + + root_s.post (); +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + continue; + } +#endif + + cout << "no error" << endl; + } +} diff --git a/tests/cxx/serializer/validation/any/makefile b/tests/cxx/serializer/validation/any/makefile new file mode 100644 index 0000000..2365ef1 --- /dev/null +++ b/tests/cxx/serializer/validation/any/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/validation/any/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/validation/any/output b/tests/cxx/serializer/validation/any/output new file mode 100644 index 0000000..cf16193 --- /dev/null +++ b/tests/cxx/serializer/validation/any/output @@ -0,0 +1,9 @@ +schema: expected element not encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered +schema: unexpected element encountered diff --git a/tests/cxx/serializer/validation/any/test.xsd b/tests/cxx/serializer/validation/any/test.xsd new file mode 100644 index 0000000..4457d58 --- /dev/null +++ b/tests/cxx/serializer/validation/any/test.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/validation/attribute/driver.cxx b/tests/cxx/serializer/validation/attribute/driver.cxx new file mode 100644 index 0000000..96a4629 --- /dev/null +++ b/tests/cxx/serializer/validation/attribute/driver.cxx @@ -0,0 +1,247 @@ +// file : tests/cxx/serializer/validation/attribute/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test attribute and anyAttribute validation. +// + +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: virtual test_1_sskel +{ + test_1_simpl (int state) + : state_ (state) + { + } + + virtual int + x () + { + if (state_ == 0) + state_ ++; + + return 123; + } + + // ##any + // + virtual bool + any_attribute_next () + { + return state_ == 1; + } + + virtual void +#ifdef XSDE_STL + any_attribute (std::string& ns, std::string& name) + { +#else + any_attribute (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + state_++; + ns = "foo"; + name = ""; + } + + // ##other + // + virtual bool + any_attribute1_next () + { + return state_ > 1 && state_ < 4; + } + + virtual void +#ifdef XSDE_STL + any_attribute1 (std::string& ns, std::string& name) + { +#else + any_attribute1 (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_++) + { + case 2: + { + // target + // + ns = "test"; + name = "x"; + break; + } + case 3: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + + // ##local + // + virtual bool + any_attribute2_next () + { + return state_ == 4; + } + + virtual void +#ifdef XSDE_STL + any_attribute2 (std::string& ns, std::string& name) + { +#else + any_attribute2 (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + state_++; + ns = "foo"; + name = "x"; + } + + // ##targetNamespace + // + virtual bool + any_attribute3_next () + { + return state_ > 4 && state_ < 7; + } + + virtual void +#ifdef XSDE_STL + any_attribute3 (std::string& ns, std::string& name) + { +#else + any_attribute3 (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_++) + { + case 5: + { + // target + // + ns = "foo"; + name = "x"; + break; + } + case 6: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + + // foo + // + virtual bool + any_attribute4_next () + { + return state_ > 6 && state_ < 9; + } + + virtual void +#ifdef XSDE_STL + any_attribute4 (std::string& ns, std::string& name) + { +#else + any_attribute4 (const char*& ns, const char*& name, bool& free) + { + free = false; +#endif + switch (state_++) + { + case 7: + { + // bar + // + ns = "bar"; + name = "x"; + break; + } + case 8: + { + // local + // + ns = ""; + name = "x"; + break; + } + } + } + +private: + int state_; +}; + +struct root_simpl: root_sskel +{ +}; + +int +main () +{ + for (int i = 0; i < 9; ++i) + { +#ifdef XSDE_EXCEPTIONS + try + { +#endif + xml_schema::int_simpl int_s; + test_1_simpl test_1_s (i); + root_simpl root_s; + + if (i != 0) + test_1_s.serializers (int_s); + + root_s.serializers (test_1_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + + ostringstream os; + doc_s.serialize (os); + +#ifndef XSDE_EXCEPTIONS + if (xml_schema::serializer_error e = doc_s._error ()) + { + if (e.type () == xml_schema::serializer_error::schema) + { + cout << "schema: " << e.schema_text () << endl; + continue; + } + } +#endif + + root_s.post (); +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + continue; + } +#endif + + cout << "no error" << endl; + } +} diff --git a/tests/cxx/serializer/validation/attribute/makefile b/tests/cxx/serializer/validation/attribute/makefile new file mode 100644 index 0000000..586b957 --- /dev/null +++ b/tests/cxx/serializer/validation/attribute/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/validation/attribute/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/validation/attribute/output b/tests/cxx/serializer/validation/attribute/output new file mode 100644 index 0000000..2b9de1e --- /dev/null +++ b/tests/cxx/serializer/validation/attribute/output @@ -0,0 +1,9 @@ +schema: expected attribute not encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered +schema: unexpected attribute encountered diff --git a/tests/cxx/serializer/validation/attribute/test.xsd b/tests/cxx/serializer/validation/attribute/test.xsd new file mode 100644 index 0000000..deb3f3b --- /dev/null +++ b/tests/cxx/serializer/validation/attribute/test.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/validation/built-in/date-time/driver.cxx b/tests/cxx/serializer/validation/built-in/date-time/driver.cxx new file mode 100644 index 0000000..bdc196e --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/date-time/driver.cxx @@ -0,0 +1,398 @@ +// file : tests/cxx/serializer/validation/built-in/date-time/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in date and time types validation. +// +#include + +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::serializer; +using namespace xsde::cxx::serializer::validating; + +int +main () +{ + using xsde::cxx::time; // Conflicts with system time. + + // gday & time zone + // + { + gday_simpl s; + context c (0); + s.pre (gday (0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (32)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (15, 15, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (15, 12, 60)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (15, -12, 30)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (15, 12, -30)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + { + gday_simpl s; + context c (0); + s.pre (gday (15, 14, 1)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gday_value); + } + + // gmonth + // + { + gmonth_simpl s; + context c (0); + s.pre (gmonth (0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + { + gmonth_simpl s; + context c (0); + s.pre (gmonth (13)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_value); + } + + // gyear + // + { + gyear_simpl s; + context c (0); + s.pre (gyear (0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gyear_value); + } + + // gmonth_day + // + { + gmonth_day_simpl s; + context c (0); + s.pre (gmonth_day (0, 15)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + gmonth_day_simpl s; + context c (0); + s.pre (gmonth_day (6, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + gmonth_day_simpl s; + context c (0); + s.pre (gmonth_day (13, 15)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + { + gmonth_day_simpl s; + context c (0); + s.pre (gmonth_day (6, 32)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gmonth_day_value); + } + + // gyear_month + // + { + gyear_month_simpl s; + context c (0); + s.pre (gyear_month (0, 6)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + gyear_month_simpl s; + context c (0); + s.pre (gyear_month (2007, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + { + gyear_month_simpl s; + context c (0); + s.pre (gyear_month (2007, 32)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_gyear_month_value); + } + + // date + // + { + date_simpl s; + context c (0); + s.pre (date (0, 6, 15)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + date_simpl s; + context c (0); + s.pre (date (2007, 0, 15)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + date_simpl s; + context c (0); + s.pre (date (2007, 13, 15)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + date_simpl s; + context c (0); + s.pre (date (2007, 6, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + { + date_simpl s; + context c (0); + s.pre (date (2007, 6, 32)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_value); + } + + // time + // + { + time_simpl s; + context c (0); + s.pre (time (25, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + time_simpl s; + context c (0); + s.pre (time (24, 1, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + time_simpl s; + context c (0); + s.pre (time (24, 0, 0.1)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + time_simpl s; + context c (0); + s.pre (time (12, 60, 30)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + time_simpl s; + context c (0); + s.pre (time (12, 30, 60.1)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + { + time_simpl s; + context c (0); + s.pre (time (12, 30, -30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_time_value); + } + + // date_time + // + { + date_time_simpl s; + context c (0); + s.pre (date_time (0, 6, 32, 12, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 0, 32, 12, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 13, 32, 12, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 0, 12, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 32, 12, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 25, 30, 30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 24, 1, 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 24, 0, 0.1)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 12, 60, 30)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 12, 30, 60.1)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + { + date_time_simpl s; + context c (0); + s.pre (date_time (2007, 6, 15, 12, 30, -30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_date_time_value); + } + + // duration + // + { + duration_simpl s; + context c (0); + s.pre (duration (false, 2007, 6, 15, 12, 30, -30.0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_duration_value); + } +} diff --git a/tests/cxx/serializer/validation/built-in/date-time/makefile b/tests/cxx/serializer/validation/built-in/date-time/makefile new file mode 100644 index 0000000..aa45e21 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/date-time/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/serializer/validation/built-in/date-time/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/serializer/validation/built-in/decimal/driver.cxx b/tests/cxx/serializer/validation/built-in/decimal/driver.cxx new file mode 100644 index 0000000..9349e6b --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/decimal/driver.cxx @@ -0,0 +1,46 @@ +// file : tests/cxx/serializer/validation/built-in/decimal/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in decimal type validation. +// +#include // strtod +#include + +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::serializer; +using namespace xsde::cxx::serializer::validating; + +int +main () +{ + { + decimal_simpl s; + context c (0); + s.pre (strtod ("NAN", 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_decimal_value); + } + + { + decimal_simpl s; + context c (0); + s.pre (strtod ("INF", 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_decimal_value); + } + + { + decimal_simpl s; + context c (0); + s.pre (strtod ("-INF", 0)); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_decimal_value); + } +} diff --git a/tests/cxx/serializer/validation/built-in/decimal/makefile b/tests/cxx/serializer/validation/built-in/decimal/makefile new file mode 100644 index 0000000..e4517b6 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/decimal/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/serializer/validation/built-in/decimal/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/serializer/validation/built-in/integer/driver.cxx b/tests/cxx/serializer/validation/built-in/integer/driver.cxx new file mode 100644 index 0000000..e20a561 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/integer/driver.cxx @@ -0,0 +1,63 @@ +// file : tests/cxx/serializer/validation/built-in/int/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in integer & friends types validation. +// + +#include + +#include +#include +#include + +using namespace xsde::cxx::serializer; +using namespace xsde::cxx::serializer::validating; +using namespace std; + +int +main () +{ + // negative_integer + // + { + negative_integer_simpl s; + context c (0); + s.pre (0); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error ()); + } + + { + negative_integer_simpl s; + context c (0); + s.pre (1); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error ()); + } + + // non_positive_integer + // + { + non_positive_integer_simpl s; + context c (0); + s.pre (1); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error ()); + } + + // positive_integer + // + { + positive_integer_simpl s; + context c (0); + s.pre (0); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error ()); + } +} diff --git a/tests/cxx/serializer/validation/built-in/integer/makefile b/tests/cxx/serializer/validation/built-in/integer/makefile new file mode 100644 index 0000000..37bd439 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/integer/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/serializer/validation/built-in/integer/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/serializer/validation/built-in/makefile b/tests/cxx/serializer/validation/built-in/makefile new file mode 100644 index 0000000..7fdeec7 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/makefile @@ -0,0 +1,20 @@ +# file : tests/cxx/serializer/validation/built-in/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 + +tests := date-time decimal integer qname string + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/serializer/validation/built-in/qname/driver.cxx b/tests/cxx/serializer/validation/built-in/qname/driver.cxx new file mode 100644 index 0000000..33ccdc1 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/qname/driver.cxx @@ -0,0 +1,70 @@ +// file : tests/cxx/serializer/validation/built-in/qname/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in QName type validation. +// +#include + +#include + +// Let the runtime header sort out which version (stl/no-stl) to +// include. +// +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::serializer; +using namespace xsde::cxx::serializer::validating; + +int +main () +{ + { + qname_simpl s; + context c (0); +#ifdef XSDE_STL + s.pre (qname ("a b")); +#else + qname qn; + qn.name_copy ("a b"); + s.pre (&qn); +#endif + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + qname_simpl s; + context c (0); +#ifdef XSDE_STL + s.pre (qname ("ab", "a b")); +#else + qname qn; + qn.name_copy ("a b"); + qn.prefix_copy ("ab"); + s.pre (&qn); +#endif + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } + + { + qname_simpl s; + context c (0); +#ifdef XSDE_STL + s.pre (qname ("a b", "ab")); +#else + qname qn; + qn.name_copy ("ab"); + qn.prefix_copy ("a b"); + s.pre (&qn); +#endif + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_qname_value); + } +} diff --git a/tests/cxx/serializer/validation/built-in/qname/makefile b/tests/cxx/serializer/validation/built-in/qname/makefile new file mode 100644 index 0000000..ec2d802 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/qname/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/serializer/validation/built-in/qname/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/serializer/validation/built-in/string/driver.cxx b/tests/cxx/serializer/validation/built-in/string/driver.cxx new file mode 100644 index 0000000..c1cfe21 --- /dev/null +++ b/tests/cxx/serializer/validation/built-in/string/driver.cxx @@ -0,0 +1,485 @@ +// file : tests/cxx/serializer/validation/built-in/string/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test the built-in string & friends types validation. +// +#include +#include + +#include + +// Let the runtime header sort out which version (stl/no-stl) to +// include. +// +#include + +using namespace xsde::cxx; +using namespace xsde::cxx::serializer; +using namespace xsde::cxx::serializer::validating; + +int +main () +{ + // normalized_string + // + { + normalized_string_simpl s; + context c (0); + s.pre ("aaa\nbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_normalized_string_value); + } + + { + normalized_string_simpl s; + context c (0); + s.pre ("aaa\tbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_normalized_string_value); + } + + { + normalized_string_simpl s; + context c (0); + s.pre ("aaa\rbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_normalized_string_value); + } + + // token + // + { + token_simpl s; + context c (0); + s.pre ("aaa\nbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + { + token_simpl s; + context c (0); + s.pre ("aaa\tbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + { + token_simpl s; + context c (0); + s.pre ("aaa\rbbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + { + token_simpl s; + context c (0); + s.pre ("aaa bbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + { + token_simpl s; + context c (0); + s.pre (" aaa bbb"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + { + token_simpl s; + context c (0); + s.pre ("aaa bbb "); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_token_value); + } + + // name + // + { + name_simpl s; + context c (0); + s.pre (""); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre (".a"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre ("-a"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre ("1a"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre (" a"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre ("a,b"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre ("a b"); + s._pre_impl (c); + s._serialize_content (); + assert (c.schema_error () == schema_error::invalid_name_value); + } + + { + name_simpl s; + context c (0); + s.pre ("a +# 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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/serializer/validation/choice/driver.cxx b/tests/cxx/serializer/validation/choice/driver.cxx new file mode 100644 index 0000000..11e1aaa --- /dev/null +++ b/tests/cxx/serializer/validation/choice/driver.cxx @@ -0,0 +1,114 @@ +// file : tests/cxx/serializer/validation/choice/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test choice validation. +// + +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: virtual test_1_sskel +{ + test_1_simpl (int state) + : state_ (state) + { + } + + virtual bool + choice_next () + { + return true; + } + + virtual choice_arm_tag + choice_arm () + { + return static_cast (state_); + } + + // + // + virtual bool + choice1_next () + { + return false; + } + + virtual choice1_arm_tag + choice1_arm () + { + return a_tag; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int state_; +}; + +struct root_simpl: root_sskel +{ +}; + +int +main () +{ + for (int i = 0; i < 2; ++i) + { +#ifdef XSDE_EXCEPTIONS + try + { +#endif + test_1_simpl test_1_s (i); + root_simpl root_s; + + root_s.serializers (test_1_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + + ostringstream os; + doc_s.serialize (os); + +#ifndef XSDE_EXCEPTIONS + if (xml_schema::serializer_error e = doc_s._error ()) + { + if (e.type () == xml_schema::serializer_error::schema) + { + cout << "schema: " << e.schema_text () << endl; + continue; + } + } +#endif + + root_s.post (); +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + continue; + } +#endif + + cout << "no error" << endl; + } +} diff --git a/tests/cxx/serializer/validation/choice/makefile b/tests/cxx/serializer/validation/choice/makefile new file mode 100644 index 0000000..79d45eb --- /dev/null +++ b/tests/cxx/serializer/validation/choice/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/validation/choice/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/validation/choice/output b/tests/cxx/serializer/validation/choice/output new file mode 100644 index 0000000..7ec90f4 --- /dev/null +++ b/tests/cxx/serializer/validation/choice/output @@ -0,0 +1,2 @@ +schema: expected element not encountered +schema: unexpected element encountered diff --git a/tests/cxx/serializer/validation/choice/test.xsd b/tests/cxx/serializer/validation/choice/test.xsd new file mode 100644 index 0000000..b87d638 --- /dev/null +++ b/tests/cxx/serializer/validation/choice/test.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/validation/element/driver.cxx b/tests/cxx/serializer/validation/element/driver.cxx new file mode 100644 index 0000000..b0ff7ed --- /dev/null +++ b/tests/cxx/serializer/validation/element/driver.cxx @@ -0,0 +1,106 @@ +// file : tests/cxx/serializer/validation/element/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test element validation. +// + +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: virtual test_1_sskel +{ + test_1_simpl (int state) + : state_ (state) + { + } + + virtual bool + a_next () + { + if (state_ == 0) + { + state_++; + return true; + } + + return false; + } + + virtual int + a () + { + return 123; + } + + virtual bool + b_next () + { + return false; + } + + virtual int + b () + { + return 234; + } + +private: + int state_; +}; + +struct root_simpl: root_sskel +{ +}; + +int +main () +{ + for (int i = 0; i < 2; ++i) + { +#ifdef XSDE_EXCEPTIONS + try + { +#endif + test_1_simpl test_1_s (i); + root_simpl root_s; + + root_s.serializers (test_1_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + + ostringstream os; + doc_s.serialize (os); + +#ifndef XSDE_EXCEPTIONS + if (xml_schema::serializer_error e = doc_s._error ()) + { + if (e.type () == xml_schema::serializer_error::schema) + { + cout << "schema: " << e.schema_text () << endl; + continue; + } + } +#endif + + root_s.post (); +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + continue; + } +#endif + + cout << "no error" << endl; + } +} diff --git a/tests/cxx/serializer/validation/element/makefile b/tests/cxx/serializer/validation/element/makefile new file mode 100644 index 0000000..ef916ed --- /dev/null +++ b/tests/cxx/serializer/validation/element/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/validation/element/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/validation/element/output b/tests/cxx/serializer/validation/element/output new file mode 100644 index 0000000..e8e09d0 --- /dev/null +++ b/tests/cxx/serializer/validation/element/output @@ -0,0 +1,2 @@ +schema: expected element not encountered +schema: expected element not encountered diff --git a/tests/cxx/serializer/validation/element/test.xsd b/tests/cxx/serializer/validation/element/test.xsd new file mode 100644 index 0000000..7f20008 --- /dev/null +++ b/tests/cxx/serializer/validation/element/test.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/validation/makefile b/tests/cxx/serializer/validation/makefile new file mode 100644 index 0000000..1304574 --- /dev/null +++ b/tests/cxx/serializer/validation/makefile @@ -0,0 +1,24 @@ +# file : tests/cxx/serializer/validation/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 + +tests := built-in + +ifeq ($(xsde_iostream),y) +tests += any attribute choice element sequence +endif + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/cxx/serializer/validation/sequence/driver.cxx b/tests/cxx/serializer/validation/sequence/driver.cxx new file mode 100644 index 0000000..562874c --- /dev/null +++ b/tests/cxx/serializer/validation/sequence/driver.cxx @@ -0,0 +1,102 @@ +// file : tests/cxx/serializer/validation/sequence/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test sequence validation. +// + +#include +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct test_1_simpl: virtual test_1_sskel +{ + test_1_simpl (int state) + : state_ (state) + { + } + + virtual bool + sequence_next () + { + return true; + } + + // + // + virtual bool + sequence1_next () + { + return false; + } + + virtual int + a () + { + return 123; + } + + virtual int + b () + { + return 234; + } + +private: + int state_; +}; + +struct root_simpl: root_sskel +{ +}; + +int +main () +{ + for (int i = 0; i < 1; ++i) + { +#ifdef XSDE_EXCEPTIONS + try + { +#endif + test_1_simpl test_1_s (i); + root_simpl root_s; + + root_s.serializers (test_1_s); + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + + ostringstream os; + doc_s.serialize (os); + +#ifndef XSDE_EXCEPTIONS + if (xml_schema::serializer_error e = doc_s._error ()) + { + if (e.type () == xml_schema::serializer_error::schema) + { + cout << "schema: " << e.schema_text () << endl; + continue; + } + } +#endif + + root_s.post (); +#ifdef XSDE_EXCEPTIONS + } + catch (xml_schema::serializer_schema const& e) + { + cout << "schema: " << e.text () << endl; + continue; + } +#endif + + cout << "no error" << endl; + } +} diff --git a/tests/cxx/serializer/validation/sequence/makefile b/tests/cxx/serializer/validation/sequence/makefile new file mode 100644 index 0000000..e16d8bf --- /dev/null +++ b/tests/cxx/serializer/validation/sequence/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/validation/sequence/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/validation/sequence/output b/tests/cxx/serializer/validation/sequence/output new file mode 100644 index 0000000..3333a0c --- /dev/null +++ b/tests/cxx/serializer/validation/sequence/output @@ -0,0 +1 @@ +schema: expected element not encountered diff --git a/tests/cxx/serializer/validation/sequence/test.xsd b/tests/cxx/serializer/validation/sequence/test.xsd new file mode 100644 index 0000000..d7b2517 --- /dev/null +++ b/tests/cxx/serializer/validation/sequence/test.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/serializer/wildcard/driver.cxx b/tests/cxx/serializer/wildcard/driver.cxx new file mode 100644 index 0000000..195c6a0 --- /dev/null +++ b/tests/cxx/serializer/wildcard/driver.cxx @@ -0,0 +1,237 @@ +// file : tests/cxx/serializer/wildcard/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test wildcard (any & anyAttribute) serialization. +// + +#include // strcpy +#include + +#include "test-sskel.hxx" + +using namespace std; +using namespace test; + +struct content_simpl: virtual content_sskel +{ + virtual int + x () + { + return 123; + } + + virtual int + a () + { + return 321; + } +}; + +struct root_simpl: virtual root_sskel +{ + virtual void + pre () + { + aa1_ = 0; + aa2_ = 0; + choice_ = 0; + ae1_ = 0; + } + + // anyAttribute + // + virtual bool + any_attribute_next () + { + return aa2_++ < 1; + } + +#ifdef XSDE_STL + virtual void + any_attribute (std::string& ns, std::string& name) + { + ns = "foo"; + name = "x"; + } +#else + virtual void + any_attribute (const char*& ns, const char*& name, bool& free) + { + char* ns_ = new char[4]; + char* name_ = new char[2]; + + strcpy (ns_, "foo"); + strcpy (name_, "x"); + + ns = ns_; + name = name_; + free = true; + } +#endif + + virtual void + serialize_any_attribute () + { + _characters ("foo#x"); + } + + virtual bool + any_attribute1_next () + { + return aa1_++ < 1; + } + +#ifdef XSDE_STL + virtual void + any_attribute1 (std::string& ns, std::string& name) + { + ns = ""; + name = "x"; + } +#else + virtual void + any_attribute1 (const char*& ns, const char*& name, bool& free) + { + ns = ""; + name = "x"; + free = false; + } +#endif + + virtual void + serialize_any_attribute1 () + { + _characters ("##local#x"); + } + + // any + // +#ifdef XSDE_STL + virtual void + any (std::string& ns, std::string& name) + { + ns = ""; + name = "a"; + } +#else + virtual void + any (const char*& ns, const char*& name, bool& free) + { + ns = ""; + name = "a"; + free = false; + } +#endif + + + virtual void + serialize_any () + { + xml_schema::int_simpl int_s; + content_simpl content_s; + + content_s.serializers (int_s, int_s); + + content_s.pre (); + content_s._pre_impl (_context ()); + content_s._serialize_attributes (); + content_s._serialize_content (); + content_s._post_impl (); + content_s.post (); + } + + virtual bool + choice_next () + { + return choice_ < 2; + } + + virtual choice_arm_tag + choice_arm () + { + return static_cast (choice_++); + } + + virtual bool + any1_next () + { + return ae1_ < 3; + } + +#ifdef XSDE_STL + virtual void + any1 (::std::string& ns, ::std::string& name) + { + ns = "foo"; + name = "a"; + } +#else + virtual void + any1 (const char*& ns, const char*& name, bool& free) + { + ns = "foo"; + name = "a"; + free = false; + } +#endif + + virtual void + serialize_any1 () + { + xml_schema::int_simpl s; + + s.pre (ae1_++); + s._pre_impl (_context ()); + s._serialize_content (); + s._post_impl (); + s.post (); + } + + virtual bool + any2_present () + { + return true; + } + +#ifdef XSDE_STL + virtual void + any2 (std::string& ns, std::string& name) + { + ns = "bar"; + name = "b"; + } +#else + virtual void + any2 (const char*& ns, const char*& name, bool& free) + { + ns = "bar"; + name = "b"; + free = false; + } +#endif + + virtual void + serialize_any2 () + { + _characters ("bar#b"); + } + +private: + int aa1_, aa2_; + int choice_; + int ae1_; +}; + +int +main () +{ + root_simpl root_s; + + xml_schema::document_simpl doc_s (root_s, "test", "root"); + + root_s.pre (); + doc_s.serialize (cout); + root_s.post (); +} diff --git a/tests/cxx/serializer/wildcard/makefile b/tests/cxx/serializer/wildcard/makefile new file mode 100644 index 0000000..44db0ef --- /dev/null +++ b/tests/cxx/serializer/wildcard/makefile @@ -0,0 +1,72 @@ +# file : tests/cxx/serializer/wildcard/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 := test.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(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) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output + $(call message,test $$1,$$1 | diff -u $(src_base)/output -,$(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/tests/cxx/serializer/wildcard/output b/tests/cxx/serializer/wildcard/output new file mode 100644 index 0000000..a55bc57 --- /dev/null +++ b/tests/cxx/serializer/wildcard/output @@ -0,0 +1 @@ +321012bar#b \ No newline at end of file diff --git a/tests/cxx/serializer/wildcard/test.xsd b/tests/cxx/serializer/wildcard/test.xsd new file mode 100644 index 0000000..074679f --- /dev/null +++ b/tests/cxx/serializer/wildcard/test.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/string/driver.cxx b/tests/cxx/string/driver.cxx new file mode 100644 index 0000000..4b8484a --- /dev/null +++ b/tests/cxx/string/driver.cxx @@ -0,0 +1,102 @@ +// file : tests/cxx/string/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test xsde::cxx::string string type. +// +#include + +#include + +using xsde::cxx::string; + +int +main () +{ + // Start with un-initialized string. + // + { + string s; + assert (s.data () == 0 && s.size () == 0 && s.capacity () == 0); + } + + // Test initialization with an empty string. + // + { + string s; + s.assign ("", 0); + assert (s.size () == 0 && s.capacity () == 64 && s == ""); + } + + // String starts with at least 64 bytes. + // + { + string s; + s.assign ("aaa"); + assert (s.size () == 3 && s == "aaa" && s.capacity () == 64); + } + + + // If we grow beyond 32 it should be greater of new size and 2*64. + // + { + const char v[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 32 + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "cccccccccccccccccccccccccccccccc"; + + string s; + s.assign ("aaa"); + s.assign (v); + assert (s.size () == 96 && s == v && s.capacity () == 128); + } + + // If we grow beyond 32 it should be greater of new size and 2*32. + // + { + const char v[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 32 + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "cccccccccccccccccccccccccccccccc" + "dddddddddddddddddddddddddddddddd" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + + string s; + s.assign ("aaa"); + s.assign (v); + assert (s.size () == 159 && s == v && s.capacity () == 160); + } + + // Make sure the new capacity is even. + // + { + const char v[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 32 + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "cccccccccccccccccccccccccccccccc" + "dddddddddddddddddddddddddddddddd" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + + string s; + s.assign ("aaa"); + s.assign (v); + assert (s.size () == 160 && s == v && s.capacity () == 162); + } + + // Test append + // + { + const char v[] = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 32 + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "cccccccccccccccccccccccccccccccc" + "dddddddddddddddddddddddddddddddd" + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + + string s; + s.assign ("aaa"); + s.append (&v[3]); + assert (s.size () == 160 && s == v && s.capacity () == 162); + } +} diff --git a/tests/cxx/string/makefile b/tests/cxx/string/makefile new file mode 100644 index 0000000..f9b239a --- /dev/null +++ b/tests/cxx/string/makefile @@ -0,0 +1,61 @@ +# file : tests/cxx/string/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 + +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.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 +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) + $(call message,test $$1,$$1,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) + + +# 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) + + +# Dependencies. +# +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/makefile b/tests/makefile new file mode 100644 index 0000000..f966c5c --- /dev/null +++ b/tests/makefile @@ -0,0 +1,18 @@ +# file : tests/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 + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +.PHONY: $(default) $(test) $(clean) + +$(default): $(out_base)/cxx/ +$(test): $(out_base)/cxx/.test +$(clean): $(out_base)/cxx/.clean + +$(call import,$(src_base)/cxx/makefile) diff --git a/tests/type-map/driver.cxx b/tests/type-map/driver.cxx new file mode 100644 index 0000000..ce54b86 --- /dev/null +++ b/tests/type-map/driver.cxx @@ -0,0 +1,47 @@ + std::ifstream is (argv[1]); + TypeMap::Lexer l (is, argv[1]); + + /* + for (TypeMap::Lexer::Token t (l.next ()); + t.type () != TypeMap::Lexer::Token::eos; + t = l.next ()) + { + e << t.line () << ": " << t.lexeme () << endl; + } + */ + + TypeMap::Parser p (l, argv[1]); + + TypeMap::Namespaces ns; + + if (!p.parse (ns)) + { + e << "failed" << endl; + return 1; + } + + for (TypeMap::Namespaces::ConstIterator n (type_map.begin ()); + n != type_map.end (); ++n) + { + wcerr << "namespace " << n->xsd_name () << " " << n->cxx_name () << endl + << "{" << endl; + + for (TypeMap::Namespace::IncludesIterator i (n->includes_begin ()); + i != n->includes_end (); ++i) + { + wcerr << "include " << *i << ";" << endl; + } + + for (TypeMap::Namespace::TypesIterator t (n->types_begin ()); + t != n->types_end (); ++t) + { + wcerr << "type " << t->xsd_name () << " " << t->cxx_ret_name (); + + if (t->cxx_arg_name ()) + wcerr << " " << t->cxx_arg_name (); + + wcerr << ";" << endl; + } + + wcerr << "}" << endl; + } diff --git a/version b/version new file mode 100644 index 0000000..4a36342 --- /dev/null +++ b/version @@ -0,0 +1 @@ +3.0.0 diff --git a/xsde/cxx/elements.cxx b/xsde/cxx/elements.cxx new file mode 100644 index 0000000..6116856 --- /dev/null +++ b/xsde/cxx/elements.cxx @@ -0,0 +1,1089 @@ +// file : xsde/cxx/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include +#include +#include + +using std::wcerr; +using std::endl; + +namespace CXX +{ + // + // + wchar_t + upcase (wchar_t c) + { + return std::toupper (c); + } + + // Context + // + + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + Char const* name_key, + NarrowString const& char_type__, + Boolean include_with_brackets__, + NarrowString const& include_prefix__, + NarrowString const& esymbol, + Containers::Vector const& nsm, + Containers::Vector const& nsr, + Boolean trace_namespace_regex_, + Containers::Vector const& ir, + Boolean trace_include_regex_, + Boolean inline_, + Containers::Vector const& reserved_name) + : os (o), + schema_root (root), + ename_key (ename_key_), + char_type (char_type_), + L (L_), + string_type (string_type_), + include_with_brackets (include_with_brackets_), + include_prefix (include_prefix_), + type_exp (type_exp_), + inst_exp (inst_exp_), + inl (inl_), + ns_mapping_cache (ns_mapping_cache_), + xs_ns_ (0), + ename_key_ (name_key), + char_type_ (char_type__), + L_ (char_type == L"wchar_t" ? L"L" : L""), + include_with_brackets_ (include_with_brackets__), + include_prefix_ (include_prefix__), + type_exp_ (esymbol ? esymbol + " " : esymbol), + inst_exp_ (esymbol ? esymbol + "\n" : esymbol), + inl_ (inline_ ? L"inline\n" : L""), + cxx_id_expr_ (L"^(::)?([a-zA-Z_]\\w*)(::[a-zA-Z_]\\w*)*$"), + cxx_id_expr (cxx_id_expr_), + trace_namespace_regex (trace_namespace_regex_), + nsr_mapping (nsr_mapping_), + nsm_mapping (nsm_mapping_), + include_mapping (include_mapping_), + trace_include_regex (trace_include_regex_), + reserved_name_map (reserved_name_map_) + { + // Resolve and cache XML Schema namespace. + // + { + SemanticGraph::Nameable* n; + + if (schema_root.names_begin ()->name () == + L"http://www.w3.org/2001/XMLSchema") + { + // schema_root is the XML Schema itself. + // + n = &schema_root.names_begin ()->named (); + } + else + { + // Otherwise, the first used schema is implied XML Schema. + // + SemanticGraph::Uses& u = *schema_root.uses_begin (); + assert (u.is_a ()); + n = &u.schema ().names_begin ()->named (); + } + + xs_ns_ = dynamic_cast (n); + } + + // + // + if (char_type == L"char") + string_type_ = L"::std::string"; + else if (char_type == L"wchar_t") + string_type_ = L"::std::wstring"; + else + string_type_ = L"::std::basic_string< " + char_type + L" >"; + + // Default mapping. + // + nsr_mapping_.push_back ( + Regex (L"#^.* (.*?/)??"L"(([a-zA-Z_]\\w*)(/[a-zA-Z_]\\w*)*)/?$#$2#")); + nsr_mapping_.push_back ( + Regex (L"#^.* http://www\\.w3\\.org/2001/XMLSchema$#xml_schema#")); + + // Custom regex mapping. + // + for (Containers::Vector::ConstIterator + i (nsr.begin ()), e (nsr.end ()); i != e; ++i) + { + nsr_mapping_.push_back (Regex (*i)); + } + + // Custom direct mapping. + // + for (Containers::Vector::ConstIterator + i (nsm.begin ()), e (nsm.end ()); i != e; ++i) + { + String s (*i); + + // Split the string in two parts at the last '='. + // + Size pos (s.rfind ('=')); + + if (pos == String::npos) + throw InvalidNamespaceMapping (s, "delimiter ('=') not found"); + + // Empty xml_ns designates the no-namespace case. + // + String xml_ns (s, 0, pos); + String cxx_ns (s, pos + 1); + + if (!cxx_ns.empty () && !cxx_id_expr.match (cxx_ns)) + throw InvalidNamespaceMapping (s, "invalid C++ identifier"); + + nsm_mapping_[xml_ns] = cxx_ns; + } + + // Include path regex + // + for (Containers::Vector::ConstIterator + i (ir.begin ()), e (ir.end ()); i != e; ++i) + { + include_mapping_.push_back (Regex (*i)); + } + + // Reserved names. + // + for (Containers::Vector::ConstIterator + i (reserved_name.begin ()), e (reserved_name.end ()); i != e; ++i) + { + String s (*i); + + // Split the string in two parts at '='. + // + Size pos (s.find ('=')); + + if (pos == String::npos) + reserved_name_map_[s] = L""; + else + reserved_name_map_[String (s, 0, pos)] = String (s, pos + 1); + } + } + + String Context:: + ns_name (SemanticGraph::Namespace& ns) const + { + using SemanticGraph::Schema; + using SemanticGraph::Includes; + using SemanticGraph::Imports; + using SemanticGraph::Implies; + using SemanticGraph::Sources; + + String tmp; + MapMapping::ConstIterator i (nsm_mapping.find (ns.name ())); + + if (i != nsm_mapping.end ()) + { + tmp = i->second; + } + else + { + SemanticGraph::Path path; + Schema& schema (dynamic_cast (ns.scope ())); + + if (schema.used ()) + { + SemanticGraph::Uses& u (*schema.used_begin ()); + path = u.path (); + } + + String pair; + + if (!path.empty ()) + { + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + try + { + pair = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + pair = path.native_file_string (); + } + } + + pair += L' ' + ns.name (); + + // Check cache first + // + MappingCache::ConstIterator i (ns_mapping_cache.find (pair)); + + if (i != ns_mapping_cache.end ()) + { + tmp = i->second; + } + else + { + if (trace_namespace_regex) + wcerr << "namespace: '" << pair << "'" << endl; + + Boolean found (false); + Regex colon (L"#/#::#"); + + for (RegexMapping::ConstReverseIterator e (nsr_mapping.rbegin ()); + e != nsr_mapping.rend (); ++e) + { + if (trace_namespace_regex) + wcerr << "try: '" << e->pattern () << "' : "; + + if (e->match (pair)) + { + tmp = e->merge (pair); + tmp = colon.merge (tmp); // replace `/' with `::' + + // Check the result. + // + found = cxx_id_expr.match (tmp); + + if (trace_namespace_regex) + wcerr << "'" << tmp << "' : "; + } + + if (trace_namespace_regex) + wcerr << (found ? '+' : '-') << endl; + + if (found) + break; + } + + if (!found) + { + // Check if the name is valid by itself. + // + if (ns.name ().empty ()) + { + // Empty name denotes a no-namespace case. + // + tmp = ns.name (); + } + else + { + tmp = colon.merge (ns.name ()); // replace `/' with `::' + + if (!cxx_id_expr.match (tmp)) + { + throw NoNamespaceMapping ( + ns.file (), ns.line (), ns.column (), ns.name ()); + } + } + } + + // Add the mapping to the cache. + // + ns_mapping_cache[pair] = tmp; + } + } + + + // Parse resulting namespace string and id() each name. + // + String r; + String::size_type b (0), e; + + do + { + e = tmp.find (L"::", b); + + String name (tmp, b, e == tmp.npos ? e : e - b); + + if (!name.empty ()) + r += L"::" + escape (name); + + b = e; + + if (b == tmp.npos) + break; + + b += 2; + + } while (true); + + return r; + } + + SemanticGraph::Namespace& Context:: + xs_ns () + { + return *xs_ns_; + } + + String Context:: + xs_ns_name () + { + return ns_name (*xs_ns_); + } + + SemanticGraph::Namespace& Context:: + namespace_ (SemanticGraph::Nameable& n) + { + // The basic idea goes like this: go up Names edges until you + // reach Namespace. There are, however, anonymous types which + // need special handling. In the case of an anonymous type we + // will go up the first Belongs edge (because the first edge + // is where the type was defined. + // + + if (n.named ()) + { + SemanticGraph::Scope& s (n.scope ()); + + SemanticGraph::Namespace* ns ( + dynamic_cast (&n)); + + return ns ? *ns : namespace_ (s); + } + else + { + SemanticGraph::Type& t (dynamic_cast (n)); + + SemanticGraph::Belongs& b (*t.classifies_begin ()); + + return namespace_ (b.instance ()); + } + } + + String Context:: + xml_ns_name (SemanticGraph::Nameable& n) + { + return namespace_ (n).name (); + } + + String Context:: + fq_name (SemanticGraph::Nameable& n, Char const* name_key) const + { + using namespace SemanticGraph; + + String r; + + if (dynamic_cast (&n)) + { + return L""; // Map to global namespace. + } + else if (SemanticGraph::Namespace* ns = + dynamic_cast (&n)) + { + r = ns_name (*ns); + } + else + { + r = fq_name (n.scope ()); + r += L"::"; + r += n.context ().get ( + name_key ? name_key : ename_key.c_str ()); + } + + return r; + } + + SemanticGraph::Type& Context:: + ultimate_base (SemanticGraph::Complex& c) + { + using namespace SemanticGraph; + + Type* b (&c.inherits ().base ()); + + while (true) + { + Complex* cb (dynamic_cast (b)); + + if (cb != 0 && cb->inherits_p ()) + { + b = &cb->inherits ().base (); + continue; + } + + break; + } + + return *b; + } + + // Restriction correspondance. + // + SemanticGraph::Element* Context:: + correspondent (SemanticGraph::Element& r) + { + SemanticGraph::Context& c (r.context ()); + + if (c.count ("xsd-frontend-restriction-correspondence")) + { + return c.get ( + "xsd-frontend-restriction-correspondence"); + } + + return 0; + } + + SemanticGraph::Any* Context:: + correspondent (SemanticGraph::Any& r) + { + SemanticGraph::Context& c (r.context ()); + + if (c.count ("xsd-frontend-restriction-correspondence")) + { + return c.get ( + "xsd-frontend-restriction-correspondence"); + } + + return 0; + } + + SemanticGraph::Compositor* Context:: + correspondent (SemanticGraph::Compositor& r) + { + SemanticGraph::Context& c (r.context ()); + + if (c.count ("xsd-frontend-restriction-correspondence")) + { + return c.get ( + "xsd-frontend-restriction-correspondence"); + } + + return 0; + } + + + // + // + namespace + { + WideChar const* keywords[] = { + L"NULL", + L"and", + L"asm", + L"auto", + L"bitand", + L"bitor", + L"bool", + L"break", + L"case", + L"catch", + L"char", + L"class", + L"compl", + L"const", + L"const_cast", + L"continue", + L"default", + L"delete", + L"do", + L"double", + L"dynamic_cast", + L"else", + L"end_eq", + L"enum", + L"explicit", + L"export", + L"extern", + L"false", + L"float", + L"for", + L"friend", + L"goto", + L"if", + L"inline", + L"int", + L"long", + L"mutable", + L"namespace", + L"new", + L"not", + L"not_eq", + L"operator", + L"or", + L"or_eq", + L"private", + L"protected", + L"public", + L"register", + L"reinterpret_cast", + L"return", + L"short", + L"signed", + L"sizeof", + L"static", + L"static_cast", + L"struct", + L"switch", + L"template", + L"this", + L"throw", + L"true", + L"try", + L"typedef", + L"typeid", + L"typename", + L"union", + L"unsigned", + L"using", + L"virtual", + L"void", + L"volatile", + L"wchar_t", + L"while", + L"xor", + L"xor_eq" + }; + } + + String Context:: + escape (String const& name) const + { + String r; + Size n (name.size ()); + + // In most common cases we will have that many chars. + // + r.reserve (n); + + for (Size i (0); i < n; ++i) + { + Boolean first (i == 0); + + UnsignedLong u (unicode_char (name, i)); // May advance i. + + if (first) + { + if (!((u >= 'a' && u <= 'z') || + (u >= 'A' && u <= 'Z') || + u == '_')) + r = (u >= '0' && u <= '9') ? L"cxx_" : L"cxx"; + } + + if (!((u >= 'a' && u <= 'z') || + (u >= 'A' && u <= 'Z') || + (u >= '0' && u <= '9') || + u == '_')) + r.push_back ('_'); + else + r.push_back (static_cast (u)); + } + + if (r.empty ()) + r = L"cxx"; + + // Custom reserved words. + // + ReservedNameMap::ConstIterator i (reserved_name_map.find (r)); + + if (i != reserved_name_map.end ()) + { + if (i->second) + return i->second; + else + r += L'_'; + } + + // Keywords + // + Size const size (sizeof (keywords) / sizeof (WideChar*)); + + if (std::binary_search (keywords, keywords + size, r)) + { + r += L'_'; + + // Re-run custom words. + // + i = reserved_name_map.find (r); + + if (i != reserved_name_map.end ()) + { + if (i->second) + return i->second; + else + r += L'_'; + } + } + + return r; + } + + // String escaping. + // + + String + charlit (UnsignedLong u) + { + String r ("\\x"); + Boolean lead (true); + + for (Long i (7); i >= 0; --i) + { + UnsignedLong x ((u >> (i * 4)) & 0x0F); + + if (lead) + { + if (x == 0) + continue; + + lead = false; + } + + r += x < 10 ? ('0' + x) : ('A' + x - 10); + } + + return r; + } + + const UnsignedLong utf8_first_char_mask[5] = + { + 0x00, 0x00, 0xC0, 0xE0, 0xF0 + }; + + String + strlit_utf8 (String const& str) + { + String r; + Size n (str.size ()); + + // In most common cases we will have that many chars. + // + r.reserve (n + 2); + + r += '"'; + + Boolean escape (false); + + for (Size i (0); i < n; ++i) + { + UnsignedLong u (Context::unicode_char (str, i)); // May advance i. + + // [128 - ] - UTF-8 + // 127 - \x7F + // [32 - 126] - as is + // [0 - 31] - \X or \xXX + // + + if (u < 32 || u == 127) + { + switch (u) + { + case L'\n': + { + r += L"\\n"; + break; + } + case L'\t': + { + r += L"\\t"; + break; + } + case L'\v': + { + r += L"\\v"; + break; + } + case L'\b': + { + r += L"\\b"; + break; + } + case L'\r': + { + r += L"\\r"; + break; + } + case L'\f': + { + r += L"\\f"; + break; + } + case L'\a': + { + r += L"\\a"; + break; + } + default: + { + r += charlit (u); + escape = true; + break; + } + } + } + else if (u < 127) + { + if (escape) + { + // Close and open the string so there are no clashes. + // + r += '"'; + r += '"'; + + escape = false; + } + + switch (u) + { + case L'"': + { + r += L"\\\""; + break; + } + case L'\\': + { + r += L"\\\\"; + break; + } + default: + { + r += static_cast (u); + break; + } + } + } + else + { + UnsignedLong count; + UnsignedLong tmp[4]; + + if (u < 0x800) + count = 2; + else if (u < 0x10000) + count = 3; + else if (u < 0x110000) + count = 4; + + switch (count) + { + case 4: + { + tmp[3] = (u | 0x80UL) & 0xBFUL; + u >>= 6; + } + case 3: + { + tmp[2] = (u | 0x80UL) & 0xBFUL; + u >>= 6; + } + case 2: + { + tmp[1] = (u | 0x80UL) & 0xBFUL; + u >>= 6; + } + case 1: + { + tmp[0] = u | utf8_first_char_mask[count]; + } + } + + for (UnsignedLong j (0); j < count; ++j) + r += charlit (tmp[j]); + + escape = true; + } + } + + r += '"'; + + return r; + } + + String + strlit_utf32 (String const& str) + { + String r; + Size n (str.size ()); + + // In most common cases we will have that many chars. + // + r.reserve (n + 2); + + r += '"'; + + Boolean escape (false); + + for (Size i (0); i < n; ++i) + { + UnsignedLong u (Context::unicode_char (str, i)); // May advance i. + + // [128 - ] - \xUUUUUUUU + // 127 - \x7F + // [32 - 126] - as is + // [0 - 31] - \X or \xXX + // + + if (u < 32 || u == 127) + { + switch (u) + { + case L'\n': + { + r += L"\\n"; + break; + } + case L'\t': + { + r += L"\\t"; + break; + } + case L'\v': + { + r += L"\\v"; + break; + } + case L'\b': + { + r += L"\\b"; + break; + } + case L'\r': + { + r += L"\\r"; + break; + } + case L'\f': + { + r += L"\\f"; + break; + } + case L'\a': + { + r += L"\\a"; + break; + } + default: + { + r += charlit (u); + escape = true; + break; + } + } + } + else if (u < 127) + { + if (escape) + { + // Close and open the string so there are no clashes. + // + r += '"'; + r += '"'; + + escape = false; + } + + switch (u) + { + case L'"': + { + r += L"\\\""; + break; + } + case L'\\': + { + r += L"\\\\"; + break; + } + default: + { + r += static_cast (u); + break; + } + } + } + else + { + r += charlit (u); + escape = true; + } + } + + r += '"'; + + return r; + } + + String Context:: + strlit (String const& str) + { + if (char_type == L"char") + return strlit_utf8 (str); + else + return strlit_utf32 (str); + } + + String Context:: + comment (String const& str) + { + String r; + + WideChar const* s (str.c_str ()); + Size size (str.size ()); + + // In most common cases we will have that many chars. + // + r.reserve (size); + + for (WideChar const* p (s); p < s + size; ++p) + { + UnsignedLong u (unicode_char (p)); // May advance p. + + // We are going to treat \v, \f and \n as unrepresentable + // here even though they can be present in C++ source code. + // + if (u > 127 || (u < 32 && u != '\t')) + r += L'?'; + else + r += static_cast (u); + } + + return r; + } + + String Context:: + process_include_path (String const& name) const + { + String path (include_prefix + name); + + if (trace_include_regex) + wcerr << "include: '" << path << "'" << endl; + + String r; + Boolean found (false); + + for (RegexMapping::ConstReverseIterator e (include_mapping.rbegin ()); + e != include_mapping.rend (); ++e) + { + if (trace_include_regex) + wcerr << "try: '" << e->pattern () << "' : "; + + if (e->match (path)) + { + r = e->merge (path); + found = true; + + if (trace_include_regex) + wcerr << "'" << r << "' : "; + } + + if (trace_include_regex) + wcerr << (found ? '+' : '-') << endl; + + if (found) + break; + } + + if (!found) + r = path; + + if (!r.empty () && r[0] != L'"' && r[0] != L'<') + { + WideChar op (include_with_brackets ? L'<' : L'"'); + WideChar cl (include_with_brackets ? L'>' : L'"'); + r = op + r + cl; + } + + return r; + } + + // Namespace + // + + Void Namespace:: + pre (Type& n) + { + String ns (ctx_.ns_name (n)); + + String::size_type b (0), e; + + if (st_) + st_->enter (L""); + + do + { + e = ns.find (L"::", b); + + String name (ns, b, e == ns.npos ? e : e - b); + + if (!name.empty ()) + { + ctx_.os << "namespace " << name << "{"; + + if (st_) + st_->enter (name); + } + + + b = e; + + if (b == ns.npos) + break; + + b += 2; + + } while (true); + } + + Void Namespace:: + post (Type& n) + { + String ns (ctx_.ns_name (n)); + + String::size_type b (0), e; + + do + { + e = ns.find (L"::", b); + + String name (ns, b, e == ns.npos ? e : e - b); + + if (!name.empty ()) + { + ctx_.os << "}"; + + if (st_) + st_->leave (); + } + + + b = e; + + if (b == ns.npos) + break; + + b += 2; + + } + while (true); + + if (st_) + st_->leave (); + } + + // Include + // + Void Includes:: + traverse (SemanticGraph::Path const& path) + { + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.native_file_string (); + } + + String hxx_path (expr_.merge (path_str)); + + ctx_.os << "#include " << ctx_.process_include_path (hxx_path) << endl + << endl; + } +} diff --git a/xsde/cxx/elements.hxx b/xsde/cxx/elements.hxx new file mode 100644 index 0000000..3125cd6 --- /dev/null +++ b/xsde/cxx/elements.hxx @@ -0,0 +1,599 @@ +// file : xsde/cxx/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_ELEMENTS_HXX +#define CXX_ELEMENTS_HXX + +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +namespace CXX +{ + using std::endl; + typedef WideString String; + + + // On some platforms std::toupper can be something other than a + // function with C++ linkage. + // + wchar_t + upcase (wchar_t c); + + + // Exceptions. + // + + struct NoNamespaceMapping + { + NoNamespaceMapping (SemanticGraph::Path const& file, + UnsignedLong line, + UnsignedLong column, + String const& ns) + : file_ (file), + line_ (line), + column_ (column), + ns_ (ns) + { + } + + SemanticGraph::Path const& + file () const + { + return file_; + } + + UnsignedLong + line () const + { + return line_; + } + + UnsignedLong + column () const + { + return column_; + } + + String const& + ns () const + { + return ns_; + } + + private: + SemanticGraph::Path file_; + UnsignedLong line_; + UnsignedLong column_; + String ns_; + }; + + struct InvalidNamespaceMapping + { + InvalidNamespaceMapping (String const& mapping, + String const& reason) + : mapping_ (mapping), reason_ (reason) + { + } + + String const& + mapping () const + { + return mapping_; + } + + String const& + reason () const + { + return reason_; + } + + private: + String mapping_; + String reason_; + }; + + + // + // + class Context + { + public: + typedef BackendElements::Regex::Pattern RegexPat; + typedef BackendElements::Regex::Expression Regex; + typedef Cult::Containers::Vector RegexMapping; + typedef Cult::Containers::Map MapMapping; + typedef Cult::Containers::Map MappingCache; + + typedef Cult::Containers::Map ReservedNameMap; + + public: + Context (std::wostream& o, + SemanticGraph::Schema& root, + Char const* name_key, + NarrowString const& char_type__, + Boolean include_with_brackets__, + NarrowString const& include_prefix__, + NarrowString const& esymbol, + Containers::Vector const& nsm, + Containers::Vector const& nsr, + Boolean trace_namespace_regex_, + Containers::Vector const& include_regex, + Boolean trace_include_regex_, + Boolean inline_, + Containers::Vector const& reserved_name); + + protected: + Context (Context& c) + : os (c.os), + schema_root (c.schema_root), + ename_key (c.ename_key), + char_type (c.char_type), + L (c.L), + string_type (c.string_type), + include_with_brackets (c.include_with_brackets), + include_prefix (c.include_prefix), + type_exp (c.type_exp), + inst_exp (c.inst_exp), + inl (c.inl), + ns_mapping_cache (c.ns_mapping_cache), + xs_ns_ (c.xs_ns_), + cxx_id_expr (c.cxx_id_expr), + trace_namespace_regex (c.trace_namespace_regex), + nsr_mapping (c.nsr_mapping), + nsm_mapping (c.nsm_mapping), + include_mapping (c.include_mapping), + trace_include_regex (c.trace_include_regex), + reserved_name_map (c.reserved_name_map) + { + } + + Context (Context& c, std::wostream& o) + : os (o), + schema_root (c.schema_root), + ename_key (c.ename_key), + char_type (c.char_type), + L (c.L), + string_type (c.string_type), + include_with_brackets (c.include_with_brackets), + include_prefix (c.include_prefix), + type_exp (c.type_exp), + inst_exp (c.inst_exp), + inl (c.inl), + ns_mapping_cache (c.ns_mapping_cache), + xs_ns_ (c.xs_ns_), + cxx_id_expr (c.cxx_id_expr), + trace_namespace_regex (c.trace_namespace_regex), + nsr_mapping (c.nsr_mapping), + nsm_mapping (c.nsm_mapping), + include_mapping (c.include_mapping), + trace_include_regex (c.trace_include_regex), + reserved_name_map (c.reserved_name_map) + { + } + + public: + static String + unclash (String const& name, String const& new_name) + { + return name == new_name ? (new_name + L'_') : new_name; + } + + public: + // Return UTF-32 character starting at this position. Position is + // advanced by 1 if this Unicode character takes more than one + // underlying character. + // + static UnsignedLong + unicode_char (String const& str, Size& pos); + + static UnsignedLong + unicode_char (WideChar const*& p); + + // Escape C++ keywords and illegal characters. + // + String + escape (String const&) const; + + // Create a string literal so that it can be used in C++ source + // code. It includes "". + // + String + strlit (String const&); + + // Escape the string so that it can be used in C++ comment. + // + String + comment (String const&); + + // Translate XML namespace name to a C++ identifier. + // + String + ns_name (SemanticGraph::Namespace&) const; + + // XML Schema namespace. + // + SemanticGraph::Namespace& + xs_ns (); + + // C++ namespace for XML Schema. + // + String + xs_ns_name (); + + // + // + SemanticGraph::Namespace& + namespace_ (SemanticGraph::Nameable& n); + + // Original XML namespace name. + // + String + xml_ns_name (SemanticGraph::Nameable& ns); + + + // Fully-qualified C++ name. + // + String + fq_name (SemanticGraph::Nameable& n, Char const* name_key = 0) const; + + public: + static SemanticGraph::Type& + ultimate_base (SemanticGraph::Complex&); + + public: + String + process_include_path (String const&) const; + + public: + static Boolean + anonymous (SemanticGraph::Type& t) + { + return t.context ().count ("anonymous"); + } + + // Restriction correspondance. + // + public: + static SemanticGraph::Element* + correspondent (SemanticGraph::Element& r); + + static SemanticGraph::Any* + correspondent (SemanticGraph::Any& r); + + static SemanticGraph::Compositor* + correspondent (SemanticGraph::Compositor& r); + + public: + // Get escaped name. + // + String const& + ename (SemanticGraph::Nameable const& n) const + { + return n.context ().get (ename_key.c_str ()); + } + + public: + std::wostream& os; + SemanticGraph::Schema& schema_root; + + NarrowString const& ename_key; + + String& char_type; + String& L; // string literal prefix + String& string_type; + + Boolean& include_with_brackets; + String& include_prefix; + + String& type_exp; + String& inst_exp; + String& inl; + + public: + MappingCache& ns_mapping_cache; + + private: + SemanticGraph::Namespace* xs_ns_; + + NarrowString const ename_key_; + + String char_type_; + String L_; + String string_type_; + + Boolean include_with_brackets_; + String include_prefix_; + + String type_exp_; + String inst_exp_; + String inl_; + + private: + RegexPat const cxx_id_expr_; + RegexPat const& cxx_id_expr; + Boolean trace_namespace_regex; + RegexMapping nsr_mapping_; + MapMapping nsm_mapping_; + RegexMapping const& nsr_mapping; + MapMapping const& nsm_mapping; + MappingCache ns_mapping_cache_; + + RegexMapping include_mapping_; + RegexMapping const& include_mapping; + Boolean trace_include_regex; + + ReservedNameMap const& reserved_name_map; + ReservedNameMap reserved_name_map_; + }; + + inline UnsignedLong Context:: + unicode_char (String const& str, Size& pos) + { + if (sizeof (WideChar) == 4) + { + return str[pos]; + } + else if (sizeof (WideChar) == 2) + { + WideChar x (str[pos]); + + if (x < 0xD800 || x > 0xDBFF) + return x; + else + return ((x - 0xD800) << 10) + (str[++pos] - 0xDC00) + 0x10000; + } + else + return 0; + } + + inline UnsignedLong Context:: + unicode_char (WideChar const*& p) + { + if (sizeof (WideChar) == 4) + { + return *p; + } + else if (sizeof (WideChar) == 2) + { + WideChar x (*p); + + if (x < 0xD800 || x > 0xDBFF) + return x; + else + return ((x - 0xD800) << 10) + (*(++p) - 0xDC00) + 0x10000; + } + else + return 0; + } + + // Usual namespace mapping. + // + struct Namespace : Traversal::Namespace + { + struct ScopeTracker + { + virtual + ~ScopeTracker () {} + + virtual Void + enter (String const&) = 0; + + virtual Void + leave () = 0; + }; + + + Namespace (Context& c, ScopeTracker* st = 0) + : ctx_ (c), st_ (st) + { + } + + Namespace (Context& c, ScopeTracker& st) + : ctx_ (c), st_ (&st) + { + } + + virtual Void + pre (Type&); + + virtual Void + post (Type&); + + private: + Context& ctx_; + ScopeTracker* st_; + }; + + + // + // + template + struct Has : X + { + Has (Boolean& result) + : result_ (result) + { + } + + virtual Void + traverse (typename X::Type&) + { + result_ = true; + } + + private: + Boolean& result_; + }; + + // Checks if scope 'Y' names any of 'X' + // + template + Boolean + has (Y& y) + { + using SemanticGraph::Scope; + + Boolean result (false); + Has t (result); + + for (Scope::NamesIterator i (y.names_begin ()), e (y.names_end ()); + !result && i != e; ++i) + t.dispatch (i->named ()); + + return result; + } + + // Checks if the compositor has any particle of 'X' + // + template + Boolean + has_particle (SemanticGraph::Compositor& y) + { + using SemanticGraph::Compositor; + + Boolean result (false); + Has t (result); + + for (Compositor::ContainsIterator i (y.contains_begin ()), + e (y.contains_end ()); !result && i != e; ++i) + { + SemanticGraph::Particle& p (i->particle ()); + + t.dispatch (p); + + if (!result && p.is_a ()) + result = has_particle (dynamic_cast (p)); + } + + return result; + } + + // Specialization for Complex + // + template + Boolean + has_particle (SemanticGraph::Complex& c) + { + return c.contains_compositor_p () && + has_particle (c.contains_compositor ().compositor ()); + } + + // Fundamental type mapping helper. + // + struct Fundamental : Traversal::Fundamental::Type, + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef + { + virtual Void + fundamental_type (SemanticGraph::Fundamental::Type& t) = 0; + + virtual Void + fundamental_template (SemanticGraph::Fundamental::Type& t) = 0; + + virtual Void + traverse (SemanticGraph::Fundamental::Type& t) + { + fundamental_type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + fundamental_template (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + fundamental_template (t); + } + }; + + // + // + struct Includes : Traversal::Imports, + Traversal::Includes + { + typedef BackendElements::Regex::Expression Regex; + + Includes (Context& c, Regex const& expr) + : ctx_ (c), expr_ (expr) + { + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + traverse (i.path ()); + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + traverse (i.path ()); + } + + Void + traverse (SemanticGraph::Path const&); + + private: + Context& ctx_; + Regex expr_; + }; +} + +#endif // CXX_TREE_ELEMENTS_HXX diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx new file mode 100644 index 0000000..57aa3d4 --- /dev/null +++ b/xsde/cxx/hybrid/cli.hxx @@ -0,0 +1,188 @@ +// file : xsde/cxx/hybrid/cli.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_CLI_HXX +#define CXX_HYBRID_CLI_HXX + +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace CLI + { + using namespace Cult::Types; + + typedef Char const Key[]; + + extern Key no_stl; + extern Key no_iostream; + extern Key no_exceptions; + extern Key no_long_long; + extern Key generate_parser; + extern Key generate_serializer; + extern Key generate_aggregate; + extern Key suppress_validation; + extern Key suppress_parser_val; + extern Key suppress_serializer_val; + extern Key generate_inline; + extern Key generate_forward; + extern Key generate_xml_schema; + extern Key extern_xml_schema; + extern Key suppress_reset; + extern Key reuse_style_mixin; + extern Key custom_data; + extern Key custom_parser; + extern Key custom_serializer; + extern Key root_element_first; + extern Key root_element_last; + extern Key root_element_all; + extern Key root_element_none; + extern Key root_element; + extern Key root_type; + extern Key output_dir; + extern Key pskel_type_suffix; + extern Key sskel_type_suffix; + extern Key pskel_file_suffix; + extern Key sskel_file_suffix; + extern Key pimpl_type_suffix; + extern Key simpl_type_suffix; + extern Key pimpl_file_suffix; + extern Key simpl_file_suffix; + extern Key paggr_type_suffix; + extern Key saggr_type_suffix; + extern Key namespace_map; + extern Key namespace_regex; + extern Key namespace_regex_trace; + extern Key reserved_name; + extern Key include_with_brackets; + extern Key include_prefix; + extern Key include_regex; + extern Key include_regex_trace; + extern Key guard_prefix; + extern Key hxx_suffix; + extern Key ixx_suffix; + extern Key cxx_suffix; + extern Key fwd_suffix; + extern Key hxx_regex; + extern Key ixx_regex; + extern Key cxx_regex; + extern Key fwd_regex; + extern Key hxx_prologue; + extern Key ixx_prologue; + extern Key cxx_prologue; + extern Key fwd_prologue; + extern Key prologue; + extern Key hxx_epilogue; + extern Key ixx_epilogue; + extern Key cxx_epilogue; + extern Key fwd_epilogue; + extern Key epilogue; + extern Key hxx_prologue_file; + extern Key ixx_prologue_file; + extern Key cxx_prologue_file; + extern Key fwd_prologue_file; + extern Key prologue_file; + extern Key hxx_epilogue_file; + extern Key ixx_epilogue_file; + extern Key cxx_epilogue_file; + extern Key fwd_epilogue_file; + extern Key epilogue_file; + extern Key show_anonymous; + extern Key show_sloc; + extern Key proprietary_license; + + typedef Cult::CLI::Options< + no_stl, Boolean, + no_iostream, Boolean, + no_exceptions, Boolean, + no_long_long, Boolean, + generate_parser, Boolean, + generate_serializer, Boolean, + generate_aggregate, Boolean, + suppress_validation, Boolean, + suppress_parser_val, Boolean, + suppress_serializer_val, Boolean, + generate_inline, Boolean, + generate_forward, Boolean, + generate_xml_schema, Boolean, + extern_xml_schema, NarrowString, + suppress_reset, Boolean, + reuse_style_mixin, Boolean, + custom_data, Cult::Containers::Vector, + custom_parser, Cult::Containers::Vector, + custom_serializer, Cult::Containers::Vector, + root_element_first, Boolean, + root_element_last, Boolean, + root_element_all, Boolean, + root_element_none, Boolean, + root_element, Cult::Containers::Vector, + root_type, Cult::Containers::Vector, + output_dir, NarrowString, + pskel_type_suffix, NarrowString, + sskel_type_suffix, NarrowString, + pskel_file_suffix, NarrowString, + sskel_file_suffix, NarrowString, + pimpl_type_suffix, NarrowString, + simpl_type_suffix, NarrowString, + pimpl_file_suffix, NarrowString, + simpl_file_suffix, NarrowString, + paggr_type_suffix, NarrowString, + saggr_type_suffix, NarrowString, + namespace_map, Cult::Containers::Vector, + namespace_regex, Cult::Containers::Vector, + namespace_regex_trace, Boolean, + reserved_name, Cult::Containers::Vector, + include_with_brackets, Boolean, + include_prefix, NarrowString, + include_regex, Cult::Containers::Vector, + include_regex_trace, Boolean, + guard_prefix, NarrowString, + hxx_suffix, NarrowString, + ixx_suffix, NarrowString, + cxx_suffix, NarrowString, + fwd_suffix, NarrowString, + hxx_regex, Cult::Containers::Vector, + ixx_regex, Cult::Containers::Vector, + cxx_regex, Cult::Containers::Vector, + fwd_regex, NarrowString, + hxx_prologue, Cult::Containers::Vector, + ixx_prologue, Cult::Containers::Vector, + cxx_prologue, Cult::Containers::Vector, + fwd_prologue, Cult::Containers::Vector, + prologue, Cult::Containers::Vector, + hxx_epilogue, Cult::Containers::Vector, + ixx_epilogue, Cult::Containers::Vector, + cxx_epilogue, Cult::Containers::Vector, + fwd_epilogue, Cult::Containers::Vector, + epilogue, Cult::Containers::Vector, + hxx_prologue_file, Cult::Containers::Vector, + ixx_prologue_file, Cult::Containers::Vector, + cxx_prologue_file, Cult::Containers::Vector, + fwd_prologue_file, NarrowString, + prologue_file, Cult::Containers::Vector, + hxx_epilogue_file, Cult::Containers::Vector, + ixx_epilogue_file, Cult::Containers::Vector, + cxx_epilogue_file, Cult::Containers::Vector, + fwd_epilogue_file, NarrowString, + epilogue_file, Cult::Containers::Vector, + show_anonymous, Boolean, + show_sloc, Boolean, + proprietary_license, Boolean + + > Options; + + struct OptionsSpec: Cult::CLI::OptionsSpec {}; + } + } +} + +#endif // CXX_HYBRID_CLI_HXX diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx new file mode 100644 index 0000000..454d0c3 --- /dev/null +++ b/xsde/cxx/hybrid/elements.cxx @@ -0,0 +1,493 @@ +// file : xsde/cxx/hybrid/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace CXX +{ + namespace Hybrid + { + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + CLI::Options const& ops, + Regex const* fe, + Regex const* he, + Regex const* ie) + : CXX::Context (o, + root, + "name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + options (ops), + exceptions (!ops.value ()), + stl (!ops.value ()), + poly_code (false), + poly_runtime (false), + reset (!ops.value ()), + mixin (ops.value ()), + tiein (!mixin), + fwd_expr (fe), + hxx_expr (he), + ixx_expr (ie), + ns_stack (ns_stack_) + { + String xs_ns (xs_ns_name ()); + + string_type = L"::xsde::cxx::ro_string"; + } + + // Parser + // + String const& Context:: + pret_type (SemanticGraph::Type& t) + { + return t.context ().get ("p:ret-type"); + } + + String const& Context:: + parg_type (SemanticGraph::Type& t) + { + return t.context ().get ("p:arg-type"); + } + + String const& Context:: + post_name (SemanticGraph::Type& t) + { + return t.context ().get ("p:post"); + } + + static String pre_impl ("pre_impl"); + + String const& Context:: + pre_impl_name (SemanticGraph::Type&) + { + // @@ Currently not assigned because we don't assign names to + // types in included/imported schemas which makes assigning + // this name correctly impossible. + // + return pre_impl; + // return t.context ().get ("ppre-impl"); + } + + String const& Context:: + epname (SemanticGraph::Particle& p) + { + return p.context ().get ("p:name"); + } + + String const& Context:: + epname (SemanticGraph::Attribute& a) + { + return a.context ().get ("p:name"); + } + + String const& Context:: + epimpl (SemanticGraph::Type& t) + { + // Use p:impl instead of pimpl because C++/Parser assigns impl + // names to the built-in types. + // + return t.context ().get ("p:impl"); + } + + String const& Context:: + epimpl_custom (SemanticGraph::Type& t) + { + SemanticGraph::Context& c (t.context ()); + + if (!c.count ("p:impl-base")) + return c.get ("p:impl"); + else + return c.get ("p:impl-base"); + } + + String const& Context:: + epstate (SemanticGraph::Type& t) + { + return t.context ().get ("pstate"); + } + + String const& Context:: + epstate_type (SemanticGraph::Type& t) + { + return t.context ().get ("pstate-type"); + } + + String const& Context:: + epstate_member (SemanticGraph::Type& t) + { + return t.context ().get ("pstate-member"); + } + + String const& Context:: + epstate_base (SemanticGraph::Type& t) + { + return t.context ().get ("pstate-base"); + } + + String const& Context:: + epstate_member (SemanticGraph::Compositor& c) + { + return c.context ().get ("pstate-member"); + } + + String const& Context:: + epskel (SemanticGraph::Type& t) + { + return t.context ().get ("p:name"); + } + + String const& Context:: + eppresent (SemanticGraph::Compositor& c) + { + return c.context ().get ("p:present"); + } + + String const& Context:: + epnext (SemanticGraph::Compositor& c) + { + return c.context ().get ("p:next"); + } + + String const& Context:: + eptag (SemanticGraph::Particle& p) + { + return p.context ().get ("p:tag"); + } + + String const& Context:: + eparm (SemanticGraph::Choice& c) + { + return c.context ().get ("p:arm"); + } + + String const& Context:: + eparm_tag (SemanticGraph::Choice& c) + { + return c.context ().get ("p:arm-tag"); + } + + // Serializer + // + String const& Context:: + sret_type (SemanticGraph::Type& t) + { + return t.context ().get ("s:ret-type"); + } + + String const& Context:: + sarg_type (SemanticGraph::Type& t) + { + return t.context ().get ("s:arg-type"); + } + + String const& Context:: + esname (SemanticGraph::Particle& p) + { + return p.context ().get ("s:name"); + } + + String const& Context:: + esname (SemanticGraph::Attribute& a) + { + return a.context ().get ("s:name"); + } + + String const& Context:: + esimpl (SemanticGraph::Type& t) + { + // Use s:impl instead of simpl because C++/Serializer assigns impl + // names to the built-in types. + // + return t.context ().get ("s:impl"); + } + + String const& Context:: + esimpl_custom (SemanticGraph::Type& t) + { + SemanticGraph::Context& c (t.context ()); + + if (!c.count ("s:impl-base")) + return c.get ("s:impl"); + else + return c.get ("s:impl-base"); + } + + String const& Context:: + esstate (SemanticGraph::Type& t) + { + return t.context ().get ("sstate"); + } + + String const& Context:: + esstate_type (SemanticGraph::Type& t) + { + return t.context ().get ("sstate-type"); + } + + String const& Context:: + esstate_member (SemanticGraph::Type& t) + { + return t.context ().get ("sstate-member"); + } + + String const& Context:: + esstate_member (SemanticGraph::Particle& p) + { + return p.context ().get ("sstate-member"); + } + + String const& Context:: + esstate_member_end (SemanticGraph::Particle& p) + { + return p.context ().get ("sstate-member-end"); + } + + String const& Context:: + esskel (SemanticGraph::Type& t) + { + return t.context ().get ("s:name"); + } + + String const& Context:: + espresent (SemanticGraph::Particle& p) + { + return p.context ().get ("s:present"); + } + + String const& Context:: + espresent (SemanticGraph::Attribute& a) + { + return a.context ().get ("s:present"); + } + + String const& Context:: + esnext (SemanticGraph::Particle& p) + { + return p.context ().get ("s:next"); + } + + String const& Context:: + estag (SemanticGraph::Particle& p) + { + return p.context ().get ("s:tag"); + } + + String const& Context:: + esarm (SemanticGraph::Choice& c) + { + return c.context ().get ("s:arm"); + } + + String const& Context:: + esarm_tag (SemanticGraph::Choice& c) + { + return c.context ().get ("s:arm-tag"); + } + + // + // + String Context:: + scope (SemanticGraph::Compositor& c, Boolean fq) const + { + using namespace SemanticGraph; + + String r; + + Compositor* p (&c); + + while (!p->contained_compositor_p ()) + { + p = &p->contained_particle ().compositor (); + + if (!p->context ().count ("type")) + continue; // See-through compositor. + + if (!r) + r = etype (*p); + else + { + String tmp; + tmp.swap (r); + r = etype (*p); + r += L"::"; + r += tmp; + } + } + + Complex& t ( + dynamic_cast ( + p->contained_compositor ().container ())); + + if (!r) + r = fq ? fq_name (t) : ename (t); + else + { + String tmp; + tmp.swap (r); + r = fq ? fq_name (t) : ename (t); + r += L"::"; + r += tmp; + } + + return r; + } + + String Context:: + scope (SemanticGraph::Element& e, Boolean fq) const + { + SemanticGraph::Compositor& c (e.contained_particle ().compositor ()); + + if (!c.context ().count ("type")) + return scope (c, fq); + else + return scope (c, fq) + L"::" + etype (c); + } + + String Context:: + scope (SemanticGraph::Attribute& a, Boolean fq) const + { + using SemanticGraph::Complex; + + Complex& t (dynamic_cast (a.scope ())); + return fq ? fq_name (t) : ename (t); + } + + Void Context:: + close_ns () + { + for (Size i (0), n (ns_stack.size () - 1); i < n; ++i) + os << "}"; + } + + Void Context:: + open_ns () + { + for (NamespaceStack::Iterator i (ns_stack.begin () + 1); + i != ns_stack.end (); + ++i) + { + os << "namespace " << *i + << "{"; + } + } + + // Namespace + // + Namespace:: + Namespace (Context& c, Boolean track_scope) + : CXX::Namespace (c, track_scope ? this : 0), ctx_ (c) + { + } + + Void Namespace:: + enter (String const& name) + { + ctx_.ns_stack.push_back (name); + } + + Void Namespace:: + leave () + { + ctx_.ns_stack.pop_back (); + } + + // Includes + // + Void TypeForward:: + traverse (SemanticGraph::Type& t) + { + os << "class " << ename (t) << ";"; + } + + Void Includes:: + traverse_ (SemanticGraph::Uses& u) + { + // Support for weak (forward) inclusion used in the file-per-type + // compilation model. + // + Type t (type_); + Boolean weak (u.context ().count ("weak")); + + if (weak && (t == header || t == impl_header)) + { + // Generate forward declarations. We don't really need them + // in the impl files. + // + if (t == impl_header) + return; + + if (forward_) + t = forward; + else + { + schema_.dispatch (u.schema ()); + return; + } + } + + if (t == source && !weak) + return; + + SemanticGraph::Path path (u.path ()); + + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.native_file_string (); + } + + String inc_path; + + switch (t) + { + case forward: + { + inc_path = ctx_.fwd_expr->merge (path_str); + break; + } + case header: + case impl_header: + case source: + { + inc_path = ctx_.hxx_expr->merge (path_str); + break; + } + case inline_: + { + if (weak) + { + inc_path = ctx_.hxx_expr->merge (path_str); + ctx_.os << "#include " << ctx_.process_include_path (inc_path) + << endl; + } + + inc_path = ctx_.ixx_expr->merge (path_str); + break; + } + } + + ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl + << endl; + } + } +} diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx new file mode 100644 index 0000000..816c80f --- /dev/null +++ b/xsde/cxx/hybrid/elements.hxx @@ -0,0 +1,1880 @@ +// file : xsde/cxx/hybrid/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_ELEMENTS_HXX +#define CXX_HYBRID_ELEMENTS_HXX + +#include + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + // + // + class Context: public CXX::Context + { + public: + typedef BackendElements::Regex::Expression Regex; + + public: + Context (std::wostream&, + SemanticGraph::Schema&, + CLI::Options const&, + Regex const* fwd_expr, + Regex const* hxx_expr, + Regex const* ixx_expr); + + protected: + Context (Context& c) + : CXX::Context (c), + options (c.options), + exceptions (c.exceptions), + stl (c.stl), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + fwd_expr (c.fwd_expr), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + ns_stack (c.ns_stack) + { + } + + Context (Context& c, std::wostream& o) + : CXX::Context (c, o), + options (c.options), + exceptions (c.exceptions), + stl (c.stl), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + fwd_expr (c.fwd_expr), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + ns_stack (c.ns_stack) + { + } + + public: + using CXX::Context::ename; + + static String const& + ename (SemanticGraph::Compositor& c) + { + return c.context ().get ("name"); + } + + static String const& + etype (SemanticGraph::Compositor& c) + { + return c.context ().get ("type"); + } + + static String const& + emember (SemanticGraph::Particle& p) + { + return p.context ().get ("member"); + } + + static String const& + emember (SemanticGraph::Attribute& a) + { + return a.context ().get ("member"); + } + + // Optional. + // + static String const& + epresent (SemanticGraph::Particle& p) + { + return p.context ().get ("present"); + } + + static String const& + epresent (SemanticGraph::Attribute& a) + { + return a.context ().get ("present"); + } + + static String const& + epresent_member (SemanticGraph::Particle& p) + { + return p.context ().get ("present-member"); + } + + static String const& + epresent_member (SemanticGraph::Attribute& a) + { + return a.context ().get ("present-member"); + } + + // Sequence. + // + static String const& + esequence (SemanticGraph::Element& e) + { + return e.context ().get ("sequence"); + } + + static String const& + esequence (SemanticGraph::Compositor& c) + { + return c.context ().get ("sequence"); + } + + static String const& + eiterator (SemanticGraph::Element& e) + { + return e.context ().get ("iterator"); + } + + static String const& + eiterator (SemanticGraph::Compositor& c) + { + return c.context ().get ("iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Element& e) + { + return e.context ().get ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Compositor& c) + { + return c.context ().get ("const-iterator"); + } + + // Choice. + // + static String const& + etag (SemanticGraph::Particle& p) + { + return p.context ().get ("tag"); + } + + static String const& + earm (SemanticGraph::Choice& c) + { + return c.context ().get ("arm"); + } + + static String const& + earm_tag (SemanticGraph::Choice& c) + { + return c.context ().get ("arm-tag"); + } + + static UnsignedLong const& + arm_tag_count (SemanticGraph::Choice& c) + { + return c.context ().get ("arm-tag-count"); + } + + static String const& + earm_member (SemanticGraph::Choice& c) + { + return c.context ().get ("arm-member"); + } + + // Custom data. + // + static String const& + ecd_name (SemanticGraph::Type& t) + { + return t.context ().get ("cd-name"); + } + + static String const& + ecd_name (SemanticGraph::Compositor& c) + { + return c.context ().get ("cd-name"); + } + + static String const& + ecd_member (SemanticGraph::Type& t) + { + return t.context ().get ("cd-member"); + } + + static String const& + ecd_member (SemanticGraph::Compositor& c) + { + return c.context ().get ("cd-member"); + } + + static String const& + ecd_sequence (SemanticGraph::Type& t) + { + return t.context ().get ("cd-sequence"); + } + + static String const& + ecd_sequence (SemanticGraph::Compositor& c) + { + return c.context ().get ("cd-sequence"); + } + + static String const& + ecd_iterator (SemanticGraph::Type& t) + { + return t.context ().get ("cd-iterator"); + } + + static String const& + ecd_iterator (SemanticGraph::Compositor& c) + { + return c.context ().get ("cd-iterator"); + } + + static String const& + ecd_const_iterator (SemanticGraph::Type& t) + { + return t.context ().get ("cd-const-iterator"); + } + + static String const& + ecd_const_iterator (SemanticGraph::Compositor& c) + { + return c.context ().get ("cd-const-iterator"); + } + + // Parser + // + public: + static String const& + pret_type (SemanticGraph::Type&); + + static String const& + parg_type (SemanticGraph::Type&); + + static String const& + post_name (SemanticGraph::Type&); + + static String const& + pre_impl_name (SemanticGraph::Type&); + + // Names + // + static String const& + epname (SemanticGraph::Particle&); + + static String const& + epname (SemanticGraph::Attribute&); + + static String const& + epimpl (SemanticGraph::Type&); + + static String const& + epimpl_custom (SemanticGraph::Type&); + + static String const& + epskel (SemanticGraph::Type&); + + // Optional. + // + static String const& + eppresent (SemanticGraph::Compositor&); + + // Sequence. + // + static String const& + epnext (SemanticGraph::Compositor&); + + // Choice. + // + static String const& + eptag (SemanticGraph::Particle&); + + static String const& + eparm (SemanticGraph::Choice&); + + static String const& + eparm_tag (SemanticGraph::Choice&); + + // State + // + static String const& + epstate (SemanticGraph::Type&); + + static String const& + epstate_type (SemanticGraph::Type&); + + static String const& + epstate_base (SemanticGraph::Type&); + + static String const& + epstate_member (SemanticGraph::Type&); + + static String const& + epstate_member (SemanticGraph::Compositor&); + + // Serializer + // + public: + static String const& + sret_type (SemanticGraph::Type&); + + static String const& + sarg_type (SemanticGraph::Type&); + + // Names + // + static String const& + esname (SemanticGraph::Particle&); + + static String const& + esname (SemanticGraph::Attribute&); + + static String const& + esimpl (SemanticGraph::Type&); + + static String const& + esimpl_custom (SemanticGraph::Type&); + + static String const& + esskel (SemanticGraph::Type&); + + // Optional. + // + static String const& + espresent (SemanticGraph::Particle&); + + static String const& + espresent (SemanticGraph::Attribute&); + + // Sequence. + // + static String const& + esnext (SemanticGraph::Particle&); + + // Choice. + // + static String const& + estag (SemanticGraph::Particle&); + + static String const& + esarm (SemanticGraph::Choice&); + + static String const& + esarm_tag (SemanticGraph::Choice&); + + // State + // + static String const& + esstate (SemanticGraph::Type&); + + static String const& + esstate_type (SemanticGraph::Type&); + + static String const& + esstate_member (SemanticGraph::Type&); + + static String const& + esstate_member (SemanticGraph::Particle&); + + static String const& + esstate_member_end (SemanticGraph::Particle&); + + public: + String + scope (SemanticGraph::Compositor& c) const + { + return scope (c, false); + } + + String + scope (SemanticGraph::Element& e) const + { + return scope (e, false); + } + + String + scope (SemanticGraph::Attribute& a) const + { + return scope (a, false); + } + + String + fq_scope (SemanticGraph::Compositor& c) const + { + return scope (c, true); + } + + String + fq_scope (SemanticGraph::Element& e) const + { + return scope (e, true); + } + + String + fq_scope (SemanticGraph::Attribute& a) const + { + return scope (a, true); + } + + private: + String + scope (SemanticGraph::Compositor&, Boolean fq) const; + + String + scope (SemanticGraph::Element&, Boolean fq) const; + + String + scope (SemanticGraph::Attribute&, Boolean fq) const; + + public: + Boolean + restriction_p (SemanticGraph::Complex& c) const + { + if (c.inherits_p () && + c.inherits ().is_a ()) + { + // Restriction of anyType is a special case. + // + return !c.inherits ().base ().is_a (); + } + + return false; + } + + public: + static Boolean + fixed_length (SemanticGraph::Type& t) + { + return t.context ().get ("fixed"); + } + + static Boolean + fixed_length (SemanticGraph::Compositor& c) + { + return c.context ().get ("fixed"); + } + + public: + Void + close_ns (); + + Void + open_ns (); + + public: + typedef + Cult::Containers::Deque + NamespaceStack; + + public: + CLI::Options const& options; + + Boolean exceptions; + Boolean stl; + Boolean poly_code; + Boolean poly_runtime; + Boolean reset; + Boolean mixin; + Boolean tiein; + + Regex const* fwd_expr; + Regex const* hxx_expr; + Regex const* ixx_expr; + + NamespaceStack& ns_stack; + + private: + NamespaceStack ns_stack_; + }; + + // + // + struct Namespace: CXX::Namespace, CXX::Namespace::ScopeTracker + { + Namespace (Context&, Boolean track_scope = false); + + protected: + virtual Void + enter (String const& name); + + virtual Void + leave (); + + protected: + Context& ctx_; + }; + + // + // + struct FundamentalType: Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal + + { + FundamentalType (Boolean& result) + : r_ (result) + { + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + r_ = true; + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&) + { + r_ = true; + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&) + { + r_ = true; + } + + private: + Boolean& r_; + }; + + // + // + struct StringType: Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::AnyURI, + Traversal::Fundamental::Entity + { + StringType (Boolean& result) + : r_ (result) + { + } + + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Id&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&) + { + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + r_ = true; + } + + private: + Boolean& r_; + }; + + + // + // + struct TypeName : Traversal::Type, + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + enum Use + { + base, + ro_ret, + ret, + arg, + var, + seq + }; + + TypeName (Context& c, Use use) + : Context (c), use_ (use) + { + if (use == base) + xs_ns_ = xs_ns_name (); + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + type (t); + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + type (t); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&) + { + if (use_ != base) + fund_type ("bool"); + else + os << xs_ns_ << "::boolean_base"; + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&) + { + if (use_ != base) + fund_type ("signed char"); + else + os << xs_ns_ << "::byte_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + if (use_ != base) + fund_type ("unsigned char"); + else + os << xs_ns_ << "::unsigned_byte_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short&) + { + if (use_ != base) + fund_type ("short"); + else + os << xs_ns_ << "::short_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + if (use_ != base) + fund_type ("unsigned short"); + else + os << xs_ns_ << "::unsigned_short_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int&) + { + if (use_ != base) + fund_type ("int"); + else + os << xs_ns_ << "::int_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + if (use_ != base) + fund_type ("unsigned int"); + else + os << xs_ns_ << "::unsigned_int_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long&) + { + if (use_ != base) + { + if (options.value ()) + fund_type ("long"); + else + fund_type ("long long"); + } + else + os << xs_ns_ << "::long_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + if (use_ != base) + { + if (options.value ()) + fund_type ("unsigned long"); + else + fund_type ("unsigned long long"); + } + else + os << xs_ns_ << "::unsigned_long_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&) + { + if (use_ != base) + fund_type ("long"); + else + os << xs_ns_ << "::integer_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + if (use_ != base) + fund_type ("long"); + else + os << xs_ns_ << "::non_positive_integer_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + if (use_ != base) + fund_type ("unsigned long"); + else + os << xs_ns_ << "::non_negative_integer_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + if (use_ != base) + fund_type ("unsigned long"); + else + os << xs_ns_ << "::positive_integer_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + if (use_ != base) + fund_type ("long"); + else + os << xs_ns_ << "::negative_integer_base"; + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&) + { + if (use_ != base) + fund_type ("float"); + else + os << xs_ns_ << "::float_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double&) + { + if (use_ != base) + fund_type ("double"); + else + os << xs_ns_ << "::double_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&) + { + if (use_ != base) + fund_type ("double"); + else + os << xs_ns_ << "::decimal_base"; + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::string_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::normalized_string_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::token_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::nmtoken_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::name_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::ncname_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::language_base"; + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + type (t); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::id_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::idref_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + type (t); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::uri_base"; + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + type (t); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + type (t); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + if (stl || use_ != base) + string_type (); + else + os << xs_ns_ << "::entity_base"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + type (t); + } + + private: + Void + type (SemanticGraph::Type& t) + { + String fq (fq_name (t)); + + switch (use_) + { + case base: + { + os << fq; + break; + } + case ro_ret: + { + os << "const " << fq << "&"; + break; + } + case ret: + { + os << fq << "&"; + break; + } + case arg: + { + if (fixed_length (t)) + os << "const " << fq << "&"; + else + os << fq << "*"; + + break; + } + case var: + { + if (fixed_length (t)) + os << fq; + else + os << fq << "*"; + + break; + } + case seq: + { + if (fixed_length (t)) + os << "::xsde::cxx::hybrid::fix_seq"; + else + os << "::xsde::cxx::hybrid::var_seq"; + + os << "< " << fq << " >"; + break; + } + } + } + + Void + fund_type (Char const* name) + { + switch (use_) + { + case ret: + { + os << name << "&"; + break; + } + case seq: + { + os << "::xsde::cxx::hybrid::pod_seq< " << name << " >"; + break; + } + default: + { + os << name; + break; + } + } + } + + Void + string_type () + { + switch (use_) + { + case base: + { + // Non-STL case is handled by the caller. + // + os << "::std::string"; + break; + } + case ro_ret: + { + if (stl) + os << "const ::std::string&"; + else + os << "const char*"; + break; + } + case ret: + { + if (stl) + os << "::std::string&"; + else + os << "char*"; + break; + } + case arg: + { + if (stl) + os << "const ::std::string&"; + else + os << "char*"; + break; + } + case var: + { + if (stl) + os << "::std::string"; + else + os << "char*"; + break; + } + case seq: + { + os << "::xsde::cxx::hybrid::str_seq"; + break; + } + } + } + + private: + Use use_; + String xs_ns_; + }; + + struct TypeOps: Traversal::Type, + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + enum Use + { + deref, + delete_ + }; + + TypeOps (Context& c, Use use) + : Context (c), use_ (use) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + type (t); + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + type (t); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&) + { + fund_type (); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + fund_type (); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double&) + { + fund_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&) + { + fund_type (); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + string_type (); + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + type (t); + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + type (t); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&) + { + string_type (); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + type (t); + } + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + type (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + type (t); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + string_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + type (t); + } + + private: + Void + type (SemanticGraph::Type& t) + { + switch (use_) + { + case deref: + { + if (!fixed_length (t)) + os << "*"; + + break; + } + case delete_: + { + os << "delete"; + break; + } + } + } + + Void + fund_type () + { + switch (use_) + { + case deref: + { + break; + } + case delete_: + { + os << "delete"; + break; + } + } + } + + Void + string_type () + { + switch (use_) + { + case deref: + { + break; + } + case delete_: + { + if (stl) + os << "delete"; + else + os << "delete[]"; + break; + } + } + } + + private: + Use use_; + }; + + // + // + struct TypeForward: Traversal::Type, Context + { + TypeForward (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t); + }; + + struct Includes : Traversal::Imports, + Traversal::Includes + { + enum Type + { + forward, + header, + impl_header, + inline_, + source + }; + + Includes (Context& c, Type type) + : ctx_ (c), + type_ (type), + forward_ (c.options.value ()), + namespace_ (c), + type_forward_ (c) + { + schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + traverse_ (i); + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + traverse_ (i); + } + + private: + Void + traverse_ (SemanticGraph::Uses&); + + private: + Context& ctx_; + Type type_; + Boolean forward_; + + Traversal::Schema schema_; + Traversal::Names schema_names_; + Namespace namespace_; + Traversal::Names names_; + TypeForward type_forward_; + }; + + // Test whether there are any aggregates to be generated. + // + struct AggregateTest: Traversal::Type, Traversal::Element + { + AggregateTest (Boolean& generate, Char const* key) + : gen_ (generate), key_ (key) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (!gen_ && t.context ().count (key_)) + gen_ = true; + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!gen_ && e.context ().count (key_)) + gen_ = true; + } + + private: + Boolean& gen_; + Char const* key_; + }; + } +} + +#endif // CXX_HYBRID_ELEMENTS_HXX diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx new file mode 100644 index 0000000..b6215f9 --- /dev/null +++ b/xsde/cxx/hybrid/generator.cxx @@ -0,0 +1,2476 @@ +// file : xsde/cxx/hybrid/generator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include + +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include "../../../libxsde/xsde/cxx/version.hxx" + +using std::endl; +using std::wcerr; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef +boost::filesystem::wifstream +WideInputFileStream; + +typedef +boost::filesystem::wofstream +WideOutputFileStream; + +typedef +boost::filesystem::ifstream +NarrowInputFileStream; + +namespace CXX +{ + namespace + { + Char const copyright_gpl[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n" + "// to C++ data binding compiler for embedded systems.\n" + "//\n" + "// This program is free software; you can redistribute it and/or modify\n" + "// it under the terms of the GNU General Public License version 2 as\n" + "// published by the Free Software Foundation.\n" + "//\n" + "// This program is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU General Public License\n" + "// along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" + "//\n" + "//\n\n"; + + Char const copyright_proprietary[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n" + "// C++ data binding compiler for embedded systems, in the Proprietary\n" + "// License mode. You should have received a proprietary license from\n" + "// Code Synthesis Tools CC prior to generating this code. See the\n" + "// license text for conditions.\n" + "//\n\n"; + } + + namespace Hybrid + { + namespace CLI + { + extern Key no_stl = "no-stl"; + extern Key no_iostream = "no-iostream"; + extern Key no_exceptions = "no-exceptions"; + extern Key no_long_long = "no-long-long"; + extern Key generate_parser = "generate-parser"; + extern Key generate_serializer = "generate-serializer"; + extern Key generate_aggregate = "generate-aggregate"; + extern Key suppress_validation = "suppress-validation"; + extern Key suppress_parser_val = "suppress-parser-val"; + extern Key suppress_serializer_val = "suppress-serializer-val"; + extern Key generate_inline = "generate-inline"; + extern Key generate_forward = "generate-forward"; + extern Key generate_xml_schema = "generate-xml-schema"; + extern Key extern_xml_schema = "extern-xml-schema"; + extern Key suppress_reset = "suppress-reset"; + extern Key reuse_style_mixin = "reuse-style-mixin"; + extern Key custom_data = "custom-data"; + extern Key custom_parser = "custom-parser"; + extern Key custom_serializer = "custom-serializer"; + extern Key root_element_first = "root-element-first"; + extern Key root_element_last = "root-element-last"; + extern Key root_element_all = "root-element-all"; + extern Key root_element_none = "root-element-none"; + extern Key root_element = "root-element"; + extern Key root_type = "root-type"; + extern Key output_dir = "output-dir"; + extern Key pskel_type_suffix = "pskel-type-suffix"; + extern Key sskel_type_suffix = "sskel-type-suffix"; + extern Key pskel_file_suffix = "pskel-file-suffix"; + extern Key sskel_file_suffix = "sskel-file-suffix"; + extern Key pimpl_type_suffix = "pimpl-type-suffix"; + extern Key simpl_type_suffix = "simpl-type-suffix"; + extern Key pimpl_file_suffix = "pimpl-file-suffix"; + extern Key simpl_file_suffix = "simpl-file-suffix"; + extern Key paggr_type_suffix = "paggr-type-suffix"; + extern Key saggr_type_suffix = "saggr-type-suffix"; + extern Key namespace_map = "namespace-map"; + extern Key namespace_regex = "namespace-regex"; + extern Key namespace_regex_trace = "namespace-regex-trace"; + extern Key reserved_name = "reserved-name"; + extern Key include_with_brackets = "include-with-brackets"; + extern Key include_prefix = "include-prefix"; + extern Key include_regex = "include-regex"; + extern Key include_regex_trace = "include-regex-trace"; + extern Key guard_prefix = "guard-prefix"; + extern Key hxx_suffix = "hxx-suffix"; + extern Key ixx_suffix = "ixx-suffix"; + extern Key cxx_suffix = "cxx-suffix"; + extern Key fwd_suffix = "fwd-suffix"; + extern Key hxx_regex = "hxx-regex"; + extern Key ixx_regex = "ixx-regex"; + extern Key cxx_regex = "cxx-regex"; + extern Key fwd_regex = "fwd-regex"; + extern Key hxx_prologue = "hxx-prologue"; + extern Key ixx_prologue = "ixx-prologue"; + extern Key cxx_prologue = "cxx-prologue"; + extern Key fwd_prologue = "fwd-prologue"; + extern Key prologue = "prologue"; + extern Key hxx_epilogue = "hxx-epilogue"; + extern Key ixx_epilogue = "ixx-epilogue"; + extern Key cxx_epilogue = "cxx-epilogue"; + extern Key fwd_epilogue = "fwd-epilogue"; + extern Key epilogue = "epilogue"; + extern Key hxx_prologue_file = "hxx-prologue-file"; + extern Key ixx_prologue_file = "ixx-prologue-file"; + extern Key cxx_prologue_file = "cxx-prologue-file"; + extern Key fwd_prologue_file = "fwd-prologue-file"; + extern Key prologue_file = "prologue-file"; + extern Key hxx_epilogue_file = "hxx-epilogue-file"; + extern Key ixx_epilogue_file = "ixx-epilogue-file"; + extern Key cxx_epilogue_file = "cxx-epilogue-file"; + extern Key fwd_epilogue_file = "fwd-epilogue-file"; + extern Key epilogue_file = "epilogue-file"; + extern Key show_anonymous = "show-anonymous"; + extern Key show_sloc = "show-sloc"; + extern Key proprietary_license = "proprietary-license"; + } + } + + Void Hybrid::Generator:: + usage () + { + std::wostream& e (wcerr); + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + e << "--no-stl" << endl + << " Generate code that does not use STL." + << endl; + + e << "--no-iostream" << endl + << " Generate code that does not use the iostream\n" + << " library." + << endl; + + e << "--no-exceptions" << endl + << " Generate code that does not use C++ exceptions." + << endl; + + e << "--no-long-long" << endl + << " Generate code that does not use the long long\n" + << " and unsigned long long types." + << endl; + + e << "--generate-parser" << endl + << " Generate XML parsing code." + << endl; + + e << "--generate-serializer" << endl + << " Generate XML serialization code." + << endl; + + e << "--generate-aggregate" << endl + << " Generate parser/serializer aggregates for root\n" + << " elements and/or types." + << endl; + + e << "--suppress-validation" << endl + << " Suppress the generation of validation code in\n" + << " parser and serializer." + << endl; + + e << "--suppress-parser-val" << endl + << " Suppress the generation of validation code in\n" + << " parser." + << endl; + + e << "--suppress-serializer-val" << endl + << " Suppress the generation of validation code in\n" + << " serializer." + << endl; + + e << "--generate-inline" << endl + << " Generate certain functions inline." + << endl; + + e << "--generate-forward" << endl + << " Generate forward declaration file." + << endl; + + e << "--generate-xml-schema" << endl + << " Generate C++ header files as if the schema being\n" + << " compiled defines the XML Schema namespace." + << endl; + + e << "--extern-xml-schema " << endl + << " Generate code as if the XML Schema namespace was\n" + << " defined in and xsd:included in the schema\n" + << " being compiled." + << endl; + + e << "--suppress-reset" << endl + << " Suppress the generation of parser and serializer\n" + << " reset code." + << endl; + + e << "--reuse-style-mixin" << endl + << " Generate code that supports the mixin base\n" + << " parser/serializer implementation reuse style." + << endl; + + e << "--custom-data " << endl + << " Add custom data to the C++ class generated for\n" + << " XML Schema type ." + << endl; + + e << "--custom-parser " << endl + << " Use a custom parser implementation instead of the\n" + << " generated version. The argument is in the\n" + << " form type[=base[/include]], where is an XML\n" + << " Schema type name, optional is a C++ name\n" + << " that should be given to the generated version,\n" + << " and optional is the header file that\n" + << " defines the custom implementation." + << endl; + + e << "--custom-serializer " << endl + << " Use a custom serializer implementation instead of\n" + << " the generated version. The argument is in\n" + << " the form type[=base[/include]], where is\n" + << " an XML Schema type name, optional is a C++\n" + << " name that should be given to the generated\n" + << " version, and optional is the header\n" + << " file that defines the custom implementation." + << endl; + + e << "--root-element-first" << endl + << " Treat only the first global element as a document\n" + << " root." + << endl; + + e << "--root-element-last" << endl + << " Treat only the last global element as a document\n" + << " root." + << endl; + + e << "--root-element-all" << endl + << " Treat all global elements as document roots." + << endl; + + e << "--root-element-none" << endl + << " Don't treat any global elements as document roots." + << endl; + + e << "--root-element " << endl + << " Treat only as a document root. Repeat\n" + << " this option to specify more than one root element." + << endl; + + e << "--root-type " << endl + << " Generate parser/serializer aggregate for .\n" + << " Repeat this option to specify more than one type." + << endl; + + e << "--output-dir " << endl + << " Write generated files to instead of the\n" + << " current directory." + << endl; + + e << "--pskel-type-suffix " << endl + << " Use instead of the default '_pskel' suffix\n" + << " to construct the names of generated parser\n" + << " skeletons." + << endl; + + e << "--sskel-type-suffix " << endl + << " Use instead of the default '_sskel' suffix\n" + << " to construct the names of generated serializer\n" + << " skeletons." + << endl; + + e << "--pskel-file-suffix " << endl + << " Use instead of the default '-pskel' suffix\n" + << " to construct the names of generated parser\n" + << " skeleton files." + << endl; + + e << "--sskel-file-suffix " << endl + << " Use instead of the default '-sskel' suffix\n" + << " to construct the names of generated serializer\n" + << " skeleton files." + << endl; + + e << "--pimpl-type-suffix " << endl + << " Use instead of the default '_pimpl' suffix\n" + << " to construct the names of generated parser\n" + << " implementations." + << endl; + + e << "--simpl-type-suffix " << endl + << " Use instead of the default '_simpl' suffix\n" + << " to construct the names of generated serializer\n" + << " implementations." + << endl; + + e << "--pimpl-file-suffix " << endl + << " Use instead of the default '-pimpl' suffix\n" + << " to construct the names of generated parser\n" + << " implementation files." + << endl; + + e << "--simpl-file-suffix " << endl + << " Use instead of the default '-simpl' suffix\n" + << " to construct the names of generated serializer\n" + << " implementation files." + << endl; + + e << "--paggr-type-suffix " << endl + << " Use instead of the default '_paggs' suffix\n" + << " to construct the names of generated parser\n" + << " aggregates." + << endl; + + e << "--saggr-type-suffix " << endl + << " Use instead of the default '_saggr' suffix\n" + << " to construct the names of generated serializer\n" + << " aggregates." + << endl; + + e << "--namespace-map =" << endl + << " Map XML Schema namespace to C++ namespace\n" + << " . Repeat this option to specify mapping for\n" + << " more than one XML Schema namespace." + << endl; + + e << "--namespace-regex " << endl + << " Add to the list of regular expressions\n" + << " used to translate XML Schema namespace names to\n" + << " C++ namespace names." + << endl; + + e << "--namespace-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --namespace-regex option." + << endl; + + e << "--reserved-name " << endl + << " Add to the list of names that should not\n" + << " be used as identifiers. The name can optionally\n" + << " be followed by '=' and the replacement name that\n" + << " should be used instead." + << endl; + + e << "--include-with-brackets" << endl + << " Use angle brackets (<>) instead of quotes (\"\") in\n" + << " generated #include directives." + << endl; + + e << "--include-prefix " << endl + << " Add to generated #include directive\n" + << " paths." + << endl; + + e << "--include-regex " << endl + << " Add to the list of regular expressions\n" + << " used to transform #include directive paths." + << endl; + + e << "--include-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --include-regex option." + << endl; + + e << "--guard-prefix " << endl + << " Add to generated header inclusion guards." + << endl; + + // File suffix. + // + e << "--hxx-suffix " << endl + << " Use instead of the default '.hxx' to\n" + << " construct the name of the header files." + << endl; + + e << "--ixx-suffix " << endl + << " Use instead of the default '.ixx' to\n" + << " construct the name of the inline files." + << endl; + + e << "--cxx-suffix " << endl + << " Use instead of the default '.cxx' to\n" + << " construct the name of the source files." + << endl; + + e << "--fwd-suffix " << endl + << " Use instead of the default '-fwd.hxx'\n" + << " to construct the name of the forward declaration\n" + << " file." + << endl; + + // File regex. + // + e << "--hxx-regex " << endl + << " Use to construct the names of the header\n" + << " files." + << endl; + + e << "--ixx-regex " << endl + << " Use to construct the names of the inline\n" + << " files." + << endl; + + e << "--cxx-regex " << endl + << " Use to construct the names of the source\n" + << " files." + << endl; + + e << "--fwd-regex " << endl + << " Use to construct the name of the forward\n" + << " declaration file." + << endl; + + + // Prologues. + // + e << "--hxx-prologue " << endl + << " Insert at the beginning of the header\n" + << " files." + << endl; + + e << "--ixx-prologue " << endl + << " Insert at the beginning of the inline\n" + << " files." + << endl; + + e << "--cxx-prologue " << endl + << " Insert at the beginning of the source\n" + << " files." + << endl; + + e << "--fwd-prologue " << endl + << " Insert at the beginning of the forward\n" + << " declaration file." + << endl; + + e << "--prologue " << endl + << " Insert at the beginning of each generated\n" + << " file for which there is no file-specific prologue." + << endl; + + + // Epilogues. + // + e << "--hxx-epilogue " << endl + << " Insert at the end of the header files." + << endl; + + e << "--ixx-epilogue " << endl + << " Insert at the end of the inline files." + << endl; + + e << "--cxx-epilogue " << endl + << " Insert at the end of the source files." + << endl; + + e << "--fwd-epilogue " << endl + << " Insert at the end of the forward\n" + << " declaration file." + << endl; + + e << "--epilogue " << endl + << " Insert at the end of each generated file\n" + << " for which there is no file-specific epilogue." + << endl; + + + // Prologue files. + // + e << "--hxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the header files." + << endl; + + e << "--ixx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the inline files." + << endl; + + e << "--cxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the source files." + << endl; + + e << "--fwd-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the forward declaration file." + << endl; + + e << "--prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of each generated file for which there is no file-\n" + << " specific prologue file." + << endl; + + + // Epilogue files. + // + e << "--hxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the header files." + << endl; + + e << "--ixx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the inline files." + << endl; + + e << "--cxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the source files." + << endl; + + e << "--fwd-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the forward declaration file." + << endl; + + e << "--epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " each generated file for which there is no file-\n" + << " specific epilogue file." + << endl; + + + // Misc. + // + e << "--show-anonymous" << endl + << " Show elements and attributes that are of anonymous\n" + << " types." + << endl; + + e << "--show-sloc" << endl + << " Show the number of generated physical source lines\n" + << " of code (SLOC)." + << endl; + + e << "--sloc-limit " << endl + << " Check that the number of generated physical source\n" + << " lines of code (SLOC) does not exceed ." + << endl; + + e << "--options-file " << endl + << " Read additional options from . Each option\n" + << " should appear on a separate line optionally\n" + << " followed by space and an argument." + << endl; + + e << "--proprietary-license" << endl + << " Indicate that the generated code is licensed under\n" + << " a proprietary license instead of the GPL." + << endl; + } + + Hybrid::CLI::OptionsSpec Hybrid::Generator:: + options_spec () + { + CLI::OptionsSpec spec; + + spec.option ().default_value ("-pskel"); + spec.option ().default_value ("-sskel"); + spec.option ().default_value ("_pskel"); + spec.option ().default_value ("_sskel"); + + spec.option ().default_value ("-pimpl"); + spec.option ().default_value ("-simpl"); + spec.option ().default_value ("_pimpl"); + spec.option ().default_value ("_simpl"); + + spec.option ().default_value ("_paggr"); + spec.option ().default_value ("_saggr"); + + spec.option ().default_value (".hxx"); + spec.option ().default_value (".ixx"); + spec.option ().default_value (".cxx"); + spec.option ().default_value ("-fwd.hxx"); + + return spec; + } + + namespace + { + NarrowString + find_value (Cult::Containers::Vector const& v, + Char const* key) + { + typedef Cult::Containers::Vector Values; + + for (Values::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i) + { + Size p (i->find ('=')); + + if (p == NarrowString::npos) + { + if (key[0] != '\0') + continue; + } + else + { + NarrowString k (*i, 0, p); + + // Unless it is one of the valid keys, assume there is no key. + // + if (!(k.empty () || k == "*" || k == "pskel" || + k == "pimpl" || k == "sskel" || k == "simpl")) + { + k.clear (); + p = NarrowString::npos; + } + + if (k != key && k != "*") + continue; + } + + return NarrowString ( + *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos); + } + + return NarrowString (); + } + + Void + copy_values (Cult::Containers::Vector& dst, + Cult::Containers::Vector const& src, + Char const* key) + { + typedef Cult::Containers::Vector Values; + + for (Values::ConstIterator i (src.begin ()), e (src.end ()); i != e; ++i) + { + Size p (i->find ('=')); + + if (p == NarrowString::npos) + { + if (key[0] != '\0') + continue; + } + else + { + NarrowString k (*i, 0, p); + + // Unless it is one of the valid keys, assume there is no key. + // + if (!(k.empty () || k == "*" || k == "pskel" || + k == "pimpl" || k == "sskel" || k == "simpl")) + { + k.clear (); + p = NarrowString::npos; + } + + if (k != key && k != "*") + continue; + } + + dst.push_back ( + NarrowString ( + *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos)); + } + } + } + + Parser::CLI::Options* Hybrid::Generator:: + parser_options (CLI::Options const& h) + { + namespace H = CLI; + namespace P = Parser::CLI; + + Evptr r (new P::Options); + + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = false; + r->value () = h.value (); + r->value () = h.value () + || h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + + Char const* k = "pskel"; + + r->value () = + find_value (h.value (), k); + r->value () = + find_value (h.value (), k); + r->value () = + find_value (h.value (), k); + + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + + r->value () = h.value (); + r->value () = h.value (); + + return r.release (); + } + + Serializer::CLI::Options* Hybrid::Generator:: + serializer_options (CLI::Options const& h) + { + namespace H = CLI; + namespace S = Serializer::CLI; + + Evptr r (new S::Options); + + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = false; + r->value () = h.value (); + r->value () = h.value () + || h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + + r->value () = h.value (); + r->value () = h.value (); + r->value () = h.value (); + + Char const* k = "sskel"; + + r->value () = + find_value (h.value (), k); + r->value () = + find_value (h.value (), k); + r->value () = + find_value (h.value (), k); + + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + r->value () = find_value ( + h.value (), k); + + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + copy_values (r->value (), h.value (), k); + + r->value () = h.value (); + r->value () = h.value (); + + return r.release (); + } + + Void Hybrid::Generator:: + calculate_size (CLI::Options const& ops, + XSDFrontend::SemanticGraph::Schema& schema, + XSDFrontend::SemanticGraph::Path const& file) + { + // Determine which types are fixed/variable-sized. + // + TreeSizeProcessor proc; + proc.process (ops, schema, file); + } + + namespace + { + template + Void + open (S& ifs, NarrowString const& path) + { + try + { + Path fs_path (path, boost::filesystem::native); + ifs.open (fs_path, std::ios_base::in | std::ios_base::binary); + + if (!ifs.is_open ()) + { + wcerr << path.c_str () << ": error: unable to open in read mode" + << endl; + + throw Hybrid::Generator::Failed (); + } + } + catch (InvalidPath const&) + { + wcerr << "error: '" << path.c_str () << "' is not a valid " + << "filesystem path" << endl; + + throw Hybrid::Generator::Failed (); + } + } + + Void + append (WideOutputFileStream& os, + NarrowString const& path, + WideInputFileStream& default_is) + { + using std::ios_base; + + if (path) + { + WideInputFileStream is; + open (is, path); + os << is.rdbuf (); + } + else if (default_is.is_open ()) + { + os << default_is.rdbuf (); + default_is.seekg (0, ios_base::beg); + } + } + + Void + append (WideOutputFileStream& os, + Cult::Containers::Vector const& primary, + Cult::Containers::Vector const& def, + Char const* primary_key, + Char const* def_key) + { + typedef Cult::Containers::Vector Values; + + for (Values const* v = &primary; v != 0; v = (v == &def ? 0 : &def)) + { + Boolean found (false); + Char const* key (v == &primary ? primary_key : def_key); + + for (Values::ConstIterator i (v->begin ()), e (v->end ()); i != e; ++i) + { + if (key == 0) + os << i->c_str () << endl; + else + { + Size p (i->find ('=')); + + if (p == NarrowString::npos) + { + if (key[0] != '\0') + continue; + } + else + { + NarrowString k (*i, 0, p); + + // Unless it is one of the valid keys, assume there is no key. + // + if (!(k.empty () || k == "*" || k == "pskel" || + k == "pimpl" || k == "sskel" || k == "simpl")) + { + k.clear (); + p = NarrowString::npos; + } + + if (k != key && k != "*") + continue; + } + + NarrowString s ( + *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos); + os << s.c_str () << endl; + } + + found = true; + } + + if (found) + break; + } + } + + Void + append (WideOutputFileStream& os, + Cult::Containers::Vector const& primary, + Cult::Containers::Vector const& def, + Char const* key) + { + append (os, primary, def, key, key); + } + } + + + UnsignedLong Hybrid::Generator:: + generate_tree (Hybrid::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + const WarningSet& disabled_warnings, + TypeMap::Namespaces& parser_type_map, + TypeMap::Namespaces& serializer_type_map, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef Context::Regex Regex; + + try + { + Boolean generate_xml_schema (ops.value ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (generate_xml_schema) + { + if (NarrowString name = ops.value ()) + { + if (file_path.native_file_string () != name) + generate_xml_schema = false; + } + } + + // Evaluate the graph for possibility of generating something useful. + // + { + Validator validator; + if (!validator.validate (ops, schema, file_path, disabled_warnings)) + throw Failed (); + } + + // Process names. + // + { + TreeNameProcessor proc; + proc.process (ops, schema, file_path); + } + + // Generate code. + // + Boolean inline_ (ops.value () && + !generate_xml_schema); + + Boolean forward (ops.value () && + !generate_xml_schema); + + Boolean source (!generate_xml_schema); + + NarrowString name (file_path.leaf ()); + + NarrowString hxx_suffix (ops.value ()); + NarrowString ixx_suffix (ops.value ()); + NarrowString cxx_suffix (ops.value ()); + NarrowString fwd_suffix (ops.value ()); + + NarrowString hxx_regex (find_value (ops.value (), "")); + NarrowString ixx_regex (find_value (ops.value (), "")); + NarrowString cxx_regex (find_value (ops.value (), "")); + + Regex hxx_expr ( + hxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" + : hxx_regex); + + Regex ixx_expr ( + ixx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#" + : ixx_regex); + + Regex cxx_expr ( + cxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#" + : cxx_regex); + + Regex fwd_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#" + : ops.value ()); + + if (!hxx_expr.match (name)) + { + wcerr << "error: header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (inline_ && !ixx_expr.match (name)) + { + wcerr << "error: inline expression '" << + ixx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (source && !cxx_expr.match (name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (forward && !fwd_expr.match (name)) + { + wcerr << "error: forward expression '" << + fwd_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ()); + NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ()); + NarrowString fwd_name (forward ? fwd_expr.merge (name) : NarrowString ()); + + Path hxx_path (hxx_name, boost::filesystem::native); + Path ixx_path (ixx_name, boost::filesystem::native); + Path cxx_path (cxx_name, boost::filesystem::native); + Path fwd_path (fwd_name, boost::filesystem::native); + + if (NarrowString dir = ops.value ()) + { + try + { + Path path (dir, boost::filesystem::native); + + hxx_path = path / hxx_path; + ixx_path = path / ixx_path; + cxx_path = path / cxx_path; + fwd_path = path / fwd_path; + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + // Open the tree files. + // + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream ixx; + WideOutputFileStream cxx; + WideOutputFileStream fwd; + + // FWD + // + if (forward) + { + fwd.open (fwd_path, ios_base::out); + + if (!fwd.is_open ()) + { + wcerr << fwd_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (fwd_path); + file_list.push_back (fwd_path.native_file_string ()); + } + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + file_list.push_back (hxx_path.native_file_string ()); + + if (inline_) + { + ixx.open (ixx_path, ios_base::out); + + if (!ixx.is_open ()) + { + wcerr << ixx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (ixx_path); + file_list.push_back (ixx_path.native_file_string ()); + } + + if (source) + { + cxx.open (cxx_path, ios_base::out); + + if (!cxx.is_open ()) + { + wcerr << cxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_path); + file_list.push_back (cxx_path.native_file_string ()); + } + + // Print copyright and license. + // + Char const* copyright ( + ops.value () + ? copyright_proprietary + : copyright_gpl); + + if (forward) + fwd << copyright; + + hxx << copyright; + + if (inline_) + ixx << copyright; + + if (source) + cxx << copyright; + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name ( + find_value (ops.value (), "")); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name ( + find_value (ops.value (), "")); + + if (name) + open (epilogue, name); + } + + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value ()); + + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + + NarrowString guard_prefix (ops.value ()); + + if (!guard_prefix) + guard_prefix = file_path.branch_path ().native_directory_string (); + + if (guard_prefix) + guard_prefix += '_'; + + + // FWD + // + if (forward) + { + Context ctx (fwd, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr); + + Indentation::Clip fwd_sloc (fwd); + + String guard (guard_expr.merge (guard_prefix + fwd_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + fwd << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + fwd << "// Begin prologue." << endl + << "//" << endl; + + append (fwd, + ops.value (), + ops.value (), + 0, + ""); + append (fwd, ops.value (), prologue); + + fwd << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Version check. + // + fwd << "#include " << endl + << endl + << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl + << "#error XSD/e runtime version mismatch" << endl + << "#endif" << endl + << endl; + + fwd << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip fwd_clip (fwd); + + // Generate. + // + generate_tree_forward (ctx, false); + + fwd << "#include " << endl + << endl; + } + + // Copy epilogue. + // + fwd << "// Begin epilogue." << endl + << "//" << endl; + + append (fwd, ops.value (), epilogue); + append (fwd, + ops.value (), + ops.value (), + 0, + ""); + + fwd << "//" << endl + << "// End epilogue." << endl + << endl; + + fwd << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << fwd_path << ": " + << fwd_sloc.buffer ().count () << endl; + + sloc += fwd_sloc.buffer ().count (); + } + } + + + // HXX + // + { + Context ctx (hxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr); + + Indentation::Clip hxx_sloc (hxx); + + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append (hxx, + ops.value (), + ops.value (), + ""); + append (hxx, + find_value (ops.value (), ""), + prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Version check. + // + hxx << "#include " << endl + << endl + << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl + << "#error XSD/e runtime version mismatch" << endl + << "#endif" << endl + << endl; + + // Runtime/generated code compatibility checks. + // + + hxx << "#include " << endl + << endl; + + if (ops.value ()) + { + hxx << "#ifdef XSDE_STL" << endl + << "#error the XSD/e runtime uses STL while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-stl)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_STL" << endl + << "#error the generated code uses STL while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-stl)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_EXCEPTIONS" << endl + << "#error the XSD/e runtime uses exceptions while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_EXCEPTIONS" << endl + << "#error the generated code uses exceptions while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_LONGLONG" << endl + << "#error the XSD/e runtime uses long long while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-long-long)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_LONGLONG" << endl + << "#error the generated code uses long long while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-long-long)" << endl + << "#endif" << endl + << endl; + } + + // + // + + hxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip hxx_clip (hxx); + + // Generate. + // + if (!generate_xml_schema) + { + if (forward) + hxx << "#include " << ctx.process_include_path (fwd_name) + << endl << endl; + else + generate_tree_forward (ctx, false); + + generate_tree_header (ctx); + } + else + generate_tree_forward (ctx, true); + + if (inline_) + { + hxx << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl + << "#include " << ctx.process_include_path (ixx_name) << endl + << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl + << endl; + } + + hxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, + find_value (ops.value (), ""), + epilogue); + append (hxx, + ops.value (), + ops.value (), + ""); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + + // IXX + // + if (inline_) + { + Context ctx (ixx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr); + + Indentation::Clip ixx_sloc (ixx); + // Guard + // + String guard (guard_expr.merge (guard_prefix + ixx_name)); + guard = ctx.escape (guard); // make a c++ id + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + ixx << "#ifndef " << guard.c_str () << endl + << "#define " << guard.c_str () << endl + << endl; + + // Copy prologue. + // + ixx << "// Begin prologue." << endl + << "//" << endl; + + append (ixx, + ops.value (), + ops.value (), + ""); + append (ixx, + find_value (ops.value (), ""), + prologue); + + ixx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip ixx_clip (ixx); + + // Generate. + // + generate_tree_inline (ctx); + } + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, + find_value (ops.value (), ""), + epilogue); + append (ixx, + ops.value (), + ops.value (), + ""); + + ixx << "//" << endl + << "// End epilogue." << endl + << endl; + + ixx << "#endif // " << guard.c_str () << endl; + + if (show_sloc) + { + wcerr << ixx_path << ": " + << ixx_sloc.buffer ().count () << endl; + + sloc += ixx_sloc.buffer ().count (); + } + } + + + // CXX + // + if (source) + { + Context ctx (cxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr); + + Indentation::Clip cxx_sloc (cxx); + + // Copy prologue. + // + cxx << "// Begin prologue." << endl + << "//" << endl; + + append (cxx, + ops.value (), + ops.value (), + ""); + append (cxx, + find_value (ops.value (), ""), + prologue); + + cxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + cxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip cxx_clip (cxx); + + cxx << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + if (!inline_) + generate_tree_inline (ctx); + + generate_tree_source (ctx); + + cxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + cxx << "// Begin epilogue." << endl + << "//" << endl; + + append (cxx, + find_value (ops.value (), ""), + epilogue); + append (cxx, + ops.value (), + ops.value (), + ""); + + cxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_path << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + + // Populate the type maps if we are generating parsing or + // serialization code. + // + if (ops.value () || + ops.value ()) + { + generate_tree_type_map ( + ops, schema, hxx_name, parser_type_map, serializer_type_map); + } + + return sloc; + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } + + UnsignedLong Hybrid::Generator:: + generate_parser (Hybrid::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + const WarningSet&, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression Regex; + + try + { + { + Boolean gen_xml_schema (ops.value ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (gen_xml_schema) + { + if (NarrowString name = ops.value ()) + { + if (file_path.native_file_string () != name) + gen_xml_schema = false; + } + } + + if (gen_xml_schema) + return 0; + } + + // Process names. + // + { + ParserNameProcessor proc; + proc.process (ops, schema, file_path); + } + + NarrowString name (file_path.leaf ()); + NarrowString skel_suffix (ops.value ()); + NarrowString impl_suffix (ops.value ()); + + NarrowString hxx_suffix (ops.value ()); + NarrowString cxx_suffix (ops.value ()); + + NarrowString hxx_obj_regex ( + find_value (ops.value (), "")); + + NarrowString hxx_skel_regex ( + find_value (ops.value (), "pskel")); + + NarrowString hxx_regex ( + find_value (ops.value (), "pimpl")); + NarrowString cxx_regex ( + find_value (ops.value (), "pimpl")); + + // Here we need to make sure that hxx_obj_expr is the same + // as in generate(). + // + Regex hxx_obj_expr ( + hxx_obj_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" + : hxx_obj_regex); + + // Here we need to make sure that hxx_skel_expr is the same + // as in the C++/Parser generator. + // + Regex hxx_skel_expr ( + hxx_skel_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#" + : hxx_skel_regex); + + Regex hxx_expr ( + hxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#" + : hxx_regex); + + Regex cxx_expr ( + cxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#" + : cxx_regex); + + if (!hxx_expr.match (name)) + { + wcerr << "error: parser implementation header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_expr.match (name)) + { + wcerr << "error: parser implementation source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + NarrowString hxx_skel_name (hxx_skel_expr.merge (name)); + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString cxx_name (cxx_expr.merge (name)); + + Path hxx_path (hxx_name, boost::filesystem::native); + Path cxx_path (cxx_name, boost::filesystem::native); + + if (NarrowString dir = ops.value ()) + { + try + { + Path path (dir, boost::filesystem::native); + + hxx_path = path / hxx_path; + cxx_path = path / cxx_path; + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream cxx (cxx_path, ios_base::out); + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + file_list.push_back (hxx_path.native_file_string ()); + + if (!cxx.is_open ()) + { + wcerr << cxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_path); + file_list.push_back (cxx_path.native_file_string ()); + + // Print copyright and license. + // + Char const* copyright ( + ops.value () + ? copyright_proprietary + : copyright_gpl); + + hxx << copyright; + cxx << copyright; + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name ( + find_value (ops.value (), "pimpl")); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name ( + find_value (ops.value (), "pimpl")); + + if (name) + open (epilogue, name); + } + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value ()); + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + + NarrowString guard_prefix (ops.value ()); + + if (!guard_prefix) + guard_prefix = file_path.branch_path ().native_directory_string (); + + if (guard_prefix) + guard_prefix += '_'; + + + // HXX + // + { + Context ctx (hxx, schema, ops, 0, &hxx_expr, 0); + + Indentation::Clip hxx_sloc (hxx); + + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append (hxx, + ops.value (), + ops.value (), + "pimpl"); + append (hxx, + find_value (ops.value (), "pimpl"), + prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + hxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip hxx_clip (hxx); + + hxx << "#include " << ctx.process_include_path (hxx_skel_name) + << endl << endl; + + generate_parser_header (ctx); + + if (ops.value ()) + generate_parser_aggregate_header (ctx); + + hxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, + find_value (ops.value (), "pimpl"), + epilogue); + append (hxx, + ops.value (), + ops.value (), + "pimpl"); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + // CXX + // + { + Context ctx (cxx, schema, ops, 0, &hxx_obj_expr, 0); + + Indentation::Clip cxx_sloc (cxx); + + // Copy prologue. + // + cxx << "// Begin prologue." << endl + << "//" << endl; + + append (cxx, + ops.value (), + ops.value (), + "pimpl"); + append (cxx, + find_value (ops.value (), "pimpl"), + prologue); + + cxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip cxx_clip (cxx); + + cxx << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + generate_parser_source (ctx); + + if (ops.value ()) + generate_parser_aggregate_source (ctx); + } + + // Copy epilogue. + // + cxx << "// Begin epilogue." << endl + << "//" << endl; + + append (cxx, + find_value (ops.value (), "pimpl"), + epilogue); + append (cxx, + ops.value (), + ops.value (), + "pimpl"); + + cxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_path << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + + return sloc; + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } + + UnsignedLong Hybrid::Generator:: + generate_serializer (Hybrid::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + const WarningSet&, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression Regex; + + try + { + { + Boolean gen_xml_schema (ops.value ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (gen_xml_schema) + { + if (NarrowString name = ops.value ()) + { + if (file_path.native_file_string () != name) + gen_xml_schema = false; + } + } + + if (gen_xml_schema) + return 0; + } + + // Process names. + // + { + SerializerNameProcessor proc; + proc.process (ops, schema, file_path); + } + + NarrowString name (file_path.leaf ()); + NarrowString skel_suffix (ops.value ()); + NarrowString impl_suffix (ops.value ()); + + NarrowString hxx_suffix (ops.value ()); + NarrowString cxx_suffix (ops.value ()); + + NarrowString hxx_skel_regex ( + find_value (ops.value (), "sskel")); + NarrowString hxx_regex ( + find_value (ops.value (), "simpl")); + NarrowString cxx_regex ( + find_value (ops.value (), "simpl")); + + // Here we need to make sure that hxx_skel_expr is the same + // as in the C++/Serializer generator. + // + Regex hxx_skel_expr ( + hxx_skel_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#" + : hxx_skel_regex); + + Regex hxx_expr ( + hxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#" + : hxx_regex); + + Regex cxx_expr ( + cxx_regex.empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#" + : cxx_regex); + + if (!hxx_expr.match (name)) + { + wcerr << "error: serializer implementation header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_expr.match (name)) + { + wcerr << "error: serializer implementation source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + NarrowString hxx_skel_name (hxx_skel_expr.merge (name)); + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString cxx_name (cxx_expr.merge (name)); + + Path hxx_path (hxx_name, boost::filesystem::native); + Path cxx_path (cxx_name, boost::filesystem::native); + + if (NarrowString dir = ops.value ()) + { + try + { + Path path (dir, boost::filesystem::native); + + hxx_path = path / hxx_path; + cxx_path = path / cxx_path; + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream cxx (cxx_path, ios_base::out); + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + file_list.push_back (hxx_path.native_file_string ()); + + if (!cxx.is_open ()) + { + wcerr << cxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_path); + file_list.push_back (cxx_path.native_file_string ()); + + // Print copyright and license. + // + Char const* copyright ( + ops.value () + ? copyright_proprietary + : copyright_gpl); + + hxx << copyright; + cxx << copyright; + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name ( + find_value (ops.value (), "simpl")); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name ( + find_value (ops.value (), "simpl")); + + if (name) + open (epilogue, name); + } + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value ()); + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + + NarrowString guard_prefix (ops.value ()); + + if (!guard_prefix) + guard_prefix = file_path.branch_path ().native_directory_string (); + + if (guard_prefix) + guard_prefix += '_'; + + + // HXX + // + { + Context ctx (hxx, schema, ops, 0, &hxx_expr, 0); + + Indentation::Clip hxx_sloc (hxx); + + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append (hxx, + ops.value (), + ops.value (), + "simpl"); + append (hxx, + find_value (ops.value (), "simpl"), + prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + hxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip hxx_clip (hxx); + + hxx << "#include " << ctx.process_include_path (hxx_skel_name) + << endl << endl; + + generate_serializer_header (ctx); + + if (ops.value ()) + generate_serializer_aggregate_header (ctx); + + hxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, + find_value (ops.value (), "simpl"), + epilogue); + append (hxx, + ops.value (), + ops.value (), + "simpl"); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + // CXX + // + { + Context ctx (cxx, schema, ops, 0, &hxx_expr, 0); + + Indentation::Clip cxx_sloc (cxx); + + // Copy prologue. + // + cxx << "// Begin prologue." << endl + << "//" << endl; + + append (cxx, + ops.value (), + ops.value (), + "simpl"); + append (cxx, + find_value (ops.value (), "simpl"), + prologue); + + cxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip cxx_clip (cxx); + + cxx << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + generate_serializer_source (ctx); + + if (ops.value ()) + generate_serializer_aggregate_source (ctx); + } + + // Copy epilogue. + // + cxx << "// Begin epilogue." << endl + << "//" << endl; + + append (cxx, + find_value (ops.value (), "simpl"), + epilogue); + append (cxx, + ops.value (), + ops.value (), + "simpl"); + + cxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_path << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + + return sloc; + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } +} diff --git a/xsde/cxx/hybrid/generator.hxx b/xsde/cxx/hybrid/generator.hxx new file mode 100644 index 0000000..ff29750 --- /dev/null +++ b/xsde/cxx/hybrid/generator.hxx @@ -0,0 +1,90 @@ +// file : xsde/cxx/hybrid/generator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_GENERATOR_HXX +#define CXX_HYBRID_GENERATOR_HXX + +#include + +#include + +#include +#include + +#include // Path +#include + +#include +#include +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class Generator + { + public: + static Void + usage (); + + static CLI::OptionsSpec + options_spec (); + + static Parser::CLI::Options* + parser_options (CLI::Options const&); + + static Serializer::CLI::Options* + serializer_options (CLI::Options const&); + + struct Failed {}; + + static Void + calculate_size ( + CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + + static UnsignedLong + generate_tree ( + CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings, + TypeMap::Namespaces& parser_type_map, + TypeMap::Namespaces& serializer_type_map, + FileList& file_list, + AutoUnlinks& unlinks); + + static UnsignedLong + generate_parser ( + CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + static UnsignedLong + generate_serializer ( + CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + private: + Generator (); + }; + } +} + +#endif // CXX_HYBRID_GENERATOR_HXX diff --git a/xsde/cxx/hybrid/parser-aggregate-header.cxx b/xsde/cxx/hybrid/parser-aggregate-header.cxx new file mode 100644 index 0000000..a717c68 --- /dev/null +++ b/xsde/cxx/hybrid/parser-aggregate-header.cxx @@ -0,0 +1,837 @@ +// file : xsde/cxx/hybrid/parser-aggregate-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + typedef Cult::Containers::Set InstanceSet; + + // For base types we only want member's types, but not the + // base itself. + // + struct BaseType: Traversal::Complex, Context + { + BaseType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + }; + + struct ParserDef: Traversal::Type, + Traversal::List, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set) + : Context (c), map_ (map), set_ (set), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (t)); + map_[&t] = inst; + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (map_.find (&l) == map_.end ()) + { + String inst (find_instance_name (l)); + map_[&l] = inst; + + dispatch (l.argumented ().type ()); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (map_.find (&c) == map_.end ()) + { + String inst (find_instance_name (c)); + map_[&c] = inst; + + // Use base type's parsers in case of a restriction + // since we are not capable of using a derived type + // in place of a base (no virtual d-tor, for one). + // + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + fund_type (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + fund_type (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fund_type (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fund_type (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fund_type (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + fund_type (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fund_type (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + fund_type (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fund_type (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + fund_type (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fund_type (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fund_type (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fund_type (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fund_type (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fund_type (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fund_type (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + fund_type (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + fund_type (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + fund_type (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + fund_type (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + fund_type (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + fund_type (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + fund_type (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + fund_type (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + fund_type (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + fund_type (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + fund_type (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + fund_type (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + fund_type (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + fund_type (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + fund_type (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + fund_type (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + fund_type (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + fund_type (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + fund_type (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + fund_type (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + fund_type (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + fund_type (t, "day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + fund_type (t, "month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + fund_type (t, "month_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + fund_type (t, "year"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + fund_type (t, "year_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + fund_type (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + fund_type (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + fund_type (t, "entities"); + } + + private: + virtual Void + fund_type (SemanticGraph::Type& t, String const& name) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (name)); + map_[&t] = inst; + } + } + + String + find_instance_name (String const& raw_name) + { + String name (escape (raw_name + L"_p_")); + + for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (raw_name + L"_p" + os.str () + L"_"); + } + + set_.insert (name); + return name; + } + + String + find_instance_name (SemanticGraph::Type& t) + { + return find_instance_name (t.name ()); + } + + TypeInstanceMap& map_; + InstanceSet& set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + + if (!tc.count ("paggr")) + return; + + String const& name (tc.get ("paggr")); + + String pre (unclash (name, "pre")); + String post (unclash (name, "post")); + String root_parser (unclash (name, "root_parser")); + String error, reset; + + InstanceSet set; + set.insert (pre); + set.insert (post); + set.insert (name); + set.insert (root_parser); + + if (!exceptions) + { + error = unclash (name, "_error"); + set.insert (error); + } + + if (Context::reset) + { + reset = unclash (name, "reset"); + set.insert (reset); + } + + tc.set ("paggr-map", TypeInstanceMap ()); + TypeInstanceMap& map (tc.get ("paggr-map")); + + ParserDef def (*this, map, set); + def.dispatch (t); + + String const& root_member (map.find (&t)->second); + + os << "// Parser aggregate for the " << comment (t.name ()) << + " type." << endl + << "//" << endl; + + os << "class " << name + << "{" + << "public:" << endl; + + // c-tor () + // + os << name << " ();" + << endl; + + // pre () + // + os << "void" << endl + << pre << " ()" + << "{" + << "this->" << root_member << ".pre ();" + << "}"; + + // post () + // + String const& ret (pret_type (t)); + + os << ret << endl + << post << " ()" + << "{" + << (ret == L"void" ? "" : "return ") << "this->" << + root_member << "." << post_name (t) << " ();" + << "}"; + + // root_parser () + // + os << fq_name (t, "p:impl") << "&" << endl + << root_parser << " ()" + << "{" + << "return this->" << root_member << ";" + << "}"; + + // _error () + // + if (error) + { + os << xs_ns_name () << "::parser_error" << endl + << error << " ()" + << "{" + << "return this->" << root_member << "._error ();" + << "}"; + } + + // reset () + // + if (reset) + { + os << "void" << endl + << reset << " ()" + << "{" + << "this->" << root_member << "._reset ();" + << "}"; + } + + os << "public:" << endl; + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + os << fq_name (*i->first, "p:impl") << " " << i->second << ";"; + + os << "};"; + } + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("paggr")) + return; + + SemanticGraph::Type& t (e.type ()); + String const& name (ec.get ("paggr")); + + String pre (unclash (name, "pre")); + String post (unclash (name, "post")); + String root_parser (unclash (name, "root_parser")); + String root_name (unclash (name, "root_name")); + String root_namespace (unclash (name, "root_namespace")); + String error, reset; + + InstanceSet set; + set.insert (pre); + set.insert (post); + set.insert (name); + set.insert (root_parser); + set.insert (root_name); + set.insert (root_namespace); + + if (!exceptions) + { + error = unclash (name, "_error"); + set.insert (error); + } + + if (Context::reset) + { + reset = unclash (name, "reset"); + set.insert (reset); + } + + ec.set ("paggr-map", TypeInstanceMap ()); + TypeInstanceMap& map (ec.get ("paggr-map")); + + ParserDef def (*this, map, set); + def.dispatch (t); + + String const& root_member (map.find (&t)->second); + + os << "// Parser aggregate for the " << comment (e.name ()) << + " element." << endl + << "//" << endl; + + os << "class " << name + << "{" + << "public:" << endl; + + // c-tor () + // + os << name << " ();" + << endl; + + // pre () + // + os << "void" << endl + << pre << " ()" + << "{" + << "this->" << root_member << ".pre ();" + << "}"; + + // post () + // + String const& ret (pret_type (t)); + + os << ret << endl + << post << " ()" + << "{" + << (ret == L"void" ? "" : "return ") << "this->" << + root_member << "." << post_name (t) << " ();" + << "}"; + + // root_parser () + // + os << fq_name (t, "p:impl") << "&" << endl + << root_parser << " ()" + << "{" + << "return this->" << root_member << ";" + << "}"; + + // root_name () + // + os << "static const char*" << endl + << root_name << " ();" + << endl; + + // root_namespace () + // + os << "static const char*" << endl + << root_namespace << " ();" + << endl; + + // _error () + // + if (error) + { + os << xs_ns_name () << "::parser_error" << endl + << error << " ()" + << "{" + << "return this->" << root_member << "._error ();" + << "}"; + } + + // reset () + // + if (reset) + { + os << "void" << endl + << reset << " ()" + << "{" + << "this->" << root_member << "._reset ();" + << "}"; + } + + os << "public:" << endl; + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + os << fq_name (*i->first, "p:impl") << " " << i->second << ";"; + + os << "};"; + } + }; + } + + Void + generate_parser_aggregate_header (Context& ctx) + { + Boolean gen (false); + + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + AggregateTest test (gen, "paggr"); + + schema >> schema_names >> ns >> names >> test; + + schema.dispatch (ctx.schema_root); + } + + if (gen) + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + GlobalType type (ctx); + GlobalElement element (ctx); + + names >> type; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/hybrid/parser-aggregate-header.hxx b/xsde/cxx/hybrid/parser-aggregate-header.hxx new file mode 100644 index 0000000..ea10495 --- /dev/null +++ b/xsde/cxx/hybrid/parser-aggregate-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/parser-aggregate-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_PARSER_AGGREGATE_HEADER_HXX +#define CXX_HYBRID_PARSER_AGGREGATE_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_parser_aggregate_header (Context&); + } +} + +#endif // CXX_HYBRID_PARSER_AGGREGATE_HEADER_HXX diff --git a/xsde/cxx/hybrid/parser-aggregate-source.cxx b/xsde/cxx/hybrid/parser-aggregate-source.cxx new file mode 100644 index 0000000..6e80318 --- /dev/null +++ b/xsde/cxx/hybrid/parser-aggregate-source.cxx @@ -0,0 +1,330 @@ +// file : xsde/cxx/hybrid/parser-aggregate-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + // + // + struct ParticleArg: Traversal::Element, Context + { + ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&e.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct AttributeArg: Traversal::Attribute, Context + { + AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&a.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct ArgList : Traversal::Complex, + Traversal::List, + Context + { + ArgList (Context& c, TypeInstanceMap& map) + : Context (c), + map_ (map), + particle_ (c, map, first_), + attribute_ (c, map, first_), + first_ (true) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&l.argumented ().type ()]; + } + + private: + TypeInstanceMap& map_; + + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleArg particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + AttributeArg attribute_; + + Boolean first_; + }; + + struct ParserConnect: Traversal::List, + Traversal::Complex, + Context + { + ParserConnect (Context& c, TypeInstanceMap& map) + : Context (c), map_ (map) + { + } + + virtual Void + traverse (SemanticGraph::List& l) + { + os << "this->" << map_[&l] << ".parsers (this->" << + map_[&l.argumented ().type ()] << ");" + << endl; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (has_members (c)) + { + os << "this->" << map_[&c] << ".parsers ("; + + ArgList args (*this, map_); + args.dispatch (c); + + os << ");" + << endl; + } + } + + private: + Boolean + has_members (SemanticGraph::Complex& c) + { + using SemanticGraph::Complex; + + if (has (c)) + return true; + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&b)) + return has_members (*cb); + + return b.is_a (); + } + + return false; + } + + private: + TypeInstanceMap& map_; + }; + + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + + if (!tc.count ("paggr")) + return; + + String const& name (tc.get ("paggr")); + TypeInstanceMap& map (tc.get ("paggr-map")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << name << "::" << endl + << name << " ()" + << "{"; + + ParserConnect connect (*this, map); + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + connect.dispatch (*i->first); + + os << "}"; + } + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("paggr")) + return; + + String const& name (ec.get ("paggr")); + TypeInstanceMap& map (ec.get ("paggr-map")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << name << "::" << endl + << name << " ()" + << "{"; + + ParserConnect connect (*this, map); + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + connect.dispatch (*i->first); + + os << "}"; + + // root_name () + // + String root_name (unclash (name, "root_name")); + + os << "const char* " << name << "::" << endl + << root_name << " ()" + << "{" + << "return " << strlit (e.name ()) << ";" + << "}"; + + // root_namespace () + // + String root_namespace (unclash (name, "root_namespace")); + + os << "const char* " << name << "::" << endl + << root_namespace << " ()" + << "{" + << "return " << strlit (e.namespace_ ().name ()) << ";" + << "}"; + } + }; + } + + Void + generate_parser_aggregate_source (Context& ctx) + { + Boolean gen (false); + + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + AggregateTest test (gen, "paggr"); + + schema >> schema_names >> ns >> names >> test; + + schema.dispatch (ctx.schema_root); + } + + if (gen) + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + GlobalType type (ctx); + GlobalElement element (ctx); + + names >> type; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/hybrid/parser-aggregate-source.hxx b/xsde/cxx/hybrid/parser-aggregate-source.hxx new file mode 100644 index 0000000..bb5b947 --- /dev/null +++ b/xsde/cxx/hybrid/parser-aggregate-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/parser-aggregate-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_PARSER_AGGREGATE_SOURCE_HXX +#define CXX_HYBRID_PARSER_AGGREGATE_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_parser_aggregate_source (Context&); + } +} + +#endif // CXX_HYBRID_PARSER_AGGREGATE_SOURCE_HXX diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx new file mode 100644 index 0000000..450a27e --- /dev/null +++ b/xsde/cxx/hybrid/parser-header.cxx @@ -0,0 +1,574 @@ +// file : xsde/cxx/hybrid/parser-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (epimpl_custom (l)); + + // We may not need to generate the class if this parser is + // being customized. + // + if (name) + { + String item (unclash (epskel (l), "item")); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << epskel (l) + << "{" + << "public:" << endl; + + // d-tor & c-tor + // + os << "~" << name << " ();" + << name << " (bool = false);" + << endl; + + // reset + // + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + + // pre + // + os << "virtual void" << endl + << "pre ();" + << endl; + + // item + // + String const& arg (parg_type (l.argumented ().type ())); + + os << "virtual void" << endl + << item << " (" << arg << ");" + << endl; + + // post + // + String const& ret (pret_type (l)); + + os << "virtual " << ret << endl + << post_name (l) << " ();" + << endl; + + // pre_impl + // + String const& type (fq_name (l)); + + os << "void" << endl + << pre_impl_name (l) << " (" << type << "*);" + << endl; + + os << (tiein ? "public:" : "protected:") << endl; + + // State. + // + os << type << "* " << epstate_member (l) << ";" + << "bool " << epstate_base (l) << ";" + << "};"; + } + + // Generate include for custom parser. + // + if (l.context ().count ("p:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + l.context ().get ("p:impl-include")) << endl + << endl; + + open_ns (); + } + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (epimpl_custom (u)); + + // We may not need to generate the class if this parser is + // being customized. + // + if (name) + { + Boolean fl (fixed_length (u)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << epskel (u) + << "{" + << "public:" << endl; + + if (!fl) + { + // d-tor & c-tor + // + os << "~" << name << " ();" + << name << " (bool = false);" + << endl; + + // reset + // + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + } + + // pre + // + os << "virtual void" << endl + << "pre ();" + << endl; + + // _characters + // + os << "virtual void" << endl + << "_characters (const " << string_type << "&);" + << endl; + + // post + // + String const& ret (pret_type (u)); + + os << "virtual " << ret << endl + << post_name (u) << " ();" + << endl; + + String const& type (fq_name (u)); + + // pre_impl + // + if (!fl) + os << "void" << endl + << pre_impl_name (u) << " (" << type << "*);" + << endl; + + os << (tiein ? "public:" : "protected:") << endl; + + // State. + // + String const& state_type (epstate_type (u)); + + os << "struct " << state_type + << "{"; + + if (!fl) + os << type << "* " << "x_;"; + + if (stl) + os << "::std::string str_;"; + else + os << "::xsde::cxx::string str_;"; + + os << "};" + << state_type << " " << epstate (u) << ";"; + + if (!fl) + os << "bool " << epstate_base (u) << ";"; + + os << "};"; + } + + // Generate include for custom parser. + // + if (u.context ().count ("p:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + u.context ().get ("p:impl-include")) << endl + << endl; + + open_ns (); + } + } + }; + + // + // State. + // + + struct CompositorState: Traversal::Compositor, Context + { + CompositorState (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + if (c.max () != 1) + { + String scope (fq_scope (c)); + + os << scope << "::" << etype (c) << "* " << + epstate_member (c) << ";"; + } + + Compositor::traverse (c); + } + }; + + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + os << "virtual void" << endl + << eppresent (a) << " ();" + << endl; + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + os << "virtual void" << endl + << eparm (c) << " (" << eparm_tag (c) << ");" + << endl; + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + os << "virtual void" << endl + << epnext (s) << " ();" + << endl; + } + else if (s.min () == 0) + { + os << "virtual void" << endl + << eppresent (s) << " ();" + << endl; + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& arg (parg_type (e.type ())); + + os << "virtual void" << endl + << epname (e) << " ("; + + if (arg != L"void") + os << arg; + + os << ");" + << endl; + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& arg (parg_type (a.type ())); + + os << "virtual void" << endl + << epname (a) << " ("; + + if (arg != L"void") + os << arg; + + os << ");" + << endl; + } + }; + + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + // State. + // + compositor_state_ (c), + + // Callbacks. + // + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + // State. + // + contains_compositor_state_ >> compositor_state_; + compositor_state_ >> contains_particle_state_; + contains_particle_state_ >> compositor_state_; + + // Callbacks. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + String const& name (epimpl_custom (c)); + + // We may not need to generate the class if this parser is + // being customized. + // + if (name) + { + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + Boolean hae (has_particle (c)); + + Boolean restriction (restriction_p (c)); + Boolean fixed (fixed_length (c)); + + String const& ret (pret_type (c)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << epskel (c); + + if (mixin && hb) + os << "," << endl + << " public " << fq_name (c.inherits ().base (), "p:impl"); + + os << "{" + << "public:" << endl; + + // c-tor + // + if (!fixed || (hb && tiein)) + os << name << " (" << (fixed ? "" : "bool = false") << ");" + << endl; + + if (!fixed) + { + // d-tor + // + os << "~" << name << " ();" + << endl; + + // reset + // + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + } + + // pre + // + os << "virtual void" << endl + << "pre ();" + << endl; + + // In case of an inheritance-by-restriction, we don't need to + // generate parser callbacks, etc. since they are the same as + // in the base. + // + if (!restriction) + { + if (ha) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + + if (he || hae) + { + os << "// Elements." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_callback_); + } + } + + // post + // + os << "virtual " << ret << endl + << post_name (c) << " ();" + << endl; + + // pre_impl + // + String const& type (fq_name (c)); + + if (!fixed) + os << (tiein ? "public:" : "protected:") << endl + << "void" << endl + << pre_impl_name (c) << " (" << type << "*);" + << endl; + + // State. + // + String const& state_type (epstate_type (c)); + String const& member (epstate_member (c)); + + os << (tiein ? "public:" : "protected:") << endl + << "struct " << state_type + << "{"; + + if (fixed) + os << type << " " << member << ";"; + else + os << type << "* " << member << ";"; + + if (!restriction && c.contains_compositor_p ()) + contains_compositor (c, contains_compositor_state_); + + os << "};" + << state_type << " " << epstate (c) << ";"; + + if (!fixed) + os << "bool " << epstate_base (c) << ";"; + + os << endl; + + // Base implementation. + // + if (tiein && hb) + os << (tiein ? "public:" : "protected:") << endl + << fq_name (c.inherits ().base (), "p:impl") << " base_impl_;" + << endl; + + os << "};"; + } + + // Generate include for custom parser. + // + if (c.context ().count ("p:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + c.context ().get ("p:impl-include")) << endl + << endl; + + open_ns (); + } + } + + private: + // State. + // + CompositorState compositor_state_; + Traversal::ContainsCompositor contains_compositor_state_; + Traversal::ContainsParticle contains_particle_state_; + + // Callbacks. + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_parser_header (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::impl_header); + Traversal::Names schema_names; + + Namespace ns (ctx, true); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/parser-header.hxx b/xsde/cxx/hybrid/parser-header.hxx new file mode 100644 index 0000000..1663b3b --- /dev/null +++ b/xsde/cxx/hybrid/parser-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/parser-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_PARSER_HEADER_HXX +#define CXX_HYBRID_PARSER_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_parser_header (Context&); + } +} + +#endif // CXX_HYBRID_PARSER_HEADER_HXX diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx new file mode 100644 index 0000000..482c195 --- /dev/null +++ b/xsde/cxx/hybrid/parser-name-processor.cxx @@ -0,0 +1,709 @@ +// file : xsde/cxx/hybrid/parser-name-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + schema_path_ (file), + impl_suffix_ (ops.value ()), + aggr_suffix_ (ops.value ()), + options (ops), + schema (root), + schema_path (schema_path_), + aggregate (ops.value ()), + impl_suffix (impl_suffix_), + aggr_suffix (aggr_suffix_), + custom_parser_map (custom_parser_map_), + global_type_names (global_type_names_) + { + // Custom parser mapping. + // + typedef Containers::Vector Vector; + Vector const& v (ops.value ()); + + for (Vector::ConstIterator i (v.begin ()), e (v.end ()); + i != e; ++i) + { + String s (*i); + + if (s.empty ()) + continue; + + // Split the string in two parts at the last '='. + // + Size pos (s.rfind ('=')); + + // If no delimiter found then both base and include are empty. + // + if (pos == String::npos) + { + custom_parser_map_[s].base.clear (); + custom_parser_map_[s].include.clear (); + continue; + } + + String name (s, 0, pos); + String rest (s, pos + 1); + + // See if we've got the include part after '/'. + // + pos = rest.find ('/'); + + String base, include; + + if (pos != String::npos) + { + base.assign (rest, 0, pos); + include.assign (rest, pos + 1, String::npos); + } + else + base = rest; + + custom_parser_map_[name].base = base; + custom_parser_map_[name].include = include; + } + } + + protected: + Context (Context& c) + : CXX::Context (c), + options (c.options), + schema (c.schema), + schema_path (c.schema_path), + aggregate (c.aggregate), + impl_suffix (c.impl_suffix), + aggr_suffix (c.aggr_suffix), + custom_parser_map (c.custom_parser_map), + global_type_names (c.global_type_names) + { + } + + public: + Boolean + fixed_length (SemanticGraph::Type& t) + { + return t.context ().get ("fixed"); + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + public: + using CXX::Context::ename; + + static String const& + ename (SemanticGraph::Compositor& c) + { + return c.context ().get ("name"); + } + + String + state_name (SemanticGraph::Compositor& c) + { + using namespace SemanticGraph; + + String r; + + for (Compositor* p (&c);; + p = &p->contained_particle ().compositor ()) + { + if (p->context ().count ("type")) + { + // Not a see-through compositor. + // + if (!r) + r = ename (*p); + else + { + String tmp; + tmp.swap (r); + r = ename (*p); + r += L"_"; + r += tmp; + } + } + + if (p->contained_compositor_p ()) + break; + } + + return r; + } + + String + state_name (SemanticGraph::Element& e) + { + String r (state_name (e.contained_particle ().compositor ())); + + if (!r) + r = ename (e); + else + { + r += L"_"; + r += ename (e); + } + + return r; + } + + public: + struct CustomParser + { + CustomParser (String const& b = L"", String const& i = L"") + : base (b), include (i) + { + } + + String base; + String include; + }; + + typedef + Cult::Containers::Map + CustomParserMap; + + private: + SemanticGraph::Path const schema_path_; + String const impl_suffix_; + String const aggr_suffix_; + CustomParserMap custom_parser_map_; + + Cult::Containers::Map global_type_names_; + + public: + CLI::Options const& options; + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + Boolean aggregate; + String const& impl_suffix; + String const& aggr_suffix; + CustomParserMap const& custom_parser_map; + + Cult::Containers::Map& global_type_names; + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + SemanticGraph::Context& lc (l.context ()); + + // In case of customization use p:impl-base instead of p:impl. + // If the name is empty then we are not generating anything. + // + String const& name (lc.count ("p:impl-base") + ? lc.get ("p:impl-base") + : lc.get ("p:impl")); + if (!name) + return; + + NameSet set; + set.insert (name); + set.insert (unclash (lc.get ("p:name"), "item")); + + lc.set ("pstate-member", + find_name (lc.get ("name"), "_", set)); + + lc.set ("pstate-base", find_name (name + L"_base", "_", set)); + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + SemanticGraph::Context& uc (u.context ()); + + // In case of customization use p:impl-base instead of p:impl. + // If the name is empty then we are not generating anything. + // + String const& name (uc.count ("p:impl-base") + ? uc.get ("p:impl-base") + : uc.get ("p:impl")); + if (!name) + return; + + NameSet set; + set.insert (name); + + String state_type (find_name (name + L"_state", set)); + + uc.set ("pstate-type", state_type); + uc.set ("pstate", find_name (state_type, "_", set)); + + if (!fixed_length (u)) + uc.set ("pstate-base", find_name (name + L"_base", "_", set)); + } + }; + + // State names. + // + + struct CompositorState: Traversal::Compositor, Context + { + CompositorState (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + if (c.max () != 1) + { + SemanticGraph::Context& cc (c.context ()); + cc.set ("pstate-member", find_name (state_name (c), L"_", set_)); + } + + Compositor::traverse (c); + } + + private: + NameSet& set_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + + SemanticGraph::Context& cc (c.context ()); + + // In case of customization use p:impl-base instead of p:impl. + // If the name is empty then we are not generating anything. + // + String const& base (cc.count ("p:impl-base") + ? cc.get ("p:impl-base") + : cc.get ("p:impl")); + + if (!base) + return; + + // Use skeleton's name set to make sure we don't clash + // with callbacks which we are overriding. + // + NameSet& set ( + cc.get ("cxx-parser-name-processor-member-set")); + + String state_type (find_name (base + L"_state", set)); + + cc.set ("pstate-type", state_type); + cc.set ("pstate", find_name (state_type, "_", set)); + cc.set ("pstate-base", find_name (base + L"_base", "_", set)); + + // State members are in a nested struct so use a new and + // empty name set. + // + NameSet state_set; + + String member ( + find_name (cc.get ("name"), "_", state_set)); + + cc.set ("pstate-member", member); + state_set.insert (member); + + // Assign state names. + // + if (!restriction && c.contains_compositor_p ()) + { + CompositorState compositor (*this, state_set); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor; + contains_particle >> compositor >> contains_particle; + + Complex::contains_compositor (c, contains_compositor); + } + } + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + String const& name (t.name ()); + + tc.set ("p:impl", find_name (name + impl_suffix, set_)); + + // See if this parser is being customized. + // + CustomParserMap::ConstIterator i (custom_parser_map.find (name)); + + if (i != custom_parser_map.end ()) + { + tc.set ("p:impl-base", i->second.base + ? find_name (i->second.base, set_) + : i->second.base); + + if (i->second.include) + tc.set ("p:impl-include", i->second.include); + } + + if (aggregate) + { + typedef Cult::Containers::Vector Names; + Names const& names (options.value ()); + + // Hopefully nobody will specify more than a handful of names. + // + for (Names::ConstIterator i (names.begin ()); + i != names.end (); ++i) + { + if (name == String (*i)) + { + tc.set ("paggr", find_name (name + aggr_suffix, set_)); + break; + } + } + } + } + + private: + NameSet& set_; + }; + + // + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c, NameSet& set) + : Context (c), set_ (set), last_ (0) + { + } + + ~GlobalElement () + { + if (last_ != 0 && options.value ()) + process (*last_); + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + Boolean p (false); + + if (last_ == 0 && options.value ()) + p = true; + + last_ = &e; + + if (!p && + !options.value () && + !options.value () && + !options.value () && + !options.value () && + options.value ().empty ()) + { + // By default process them all. + // + p = true; + } + + if (!p && options.value ()) + p = true; + + if (!p) + { + typedef Cult::Containers::Vector Names; + Names const& names (options.value ()); + + // Hopefully nobody will specify more than a handful of names. + // + for (Names::ConstIterator i (names.begin ()); + !p && i != names.end (); + ++i) + { + if (e.name () == String (*i)) + p = true; + } + } + + if (p) + process (e); + } + + private: + Void + process (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("paggr")) + { + ec.set ("paggr", find_name (e.name () + aggr_suffix, set_)); + } + } + + private: + NameSet& set_; + SemanticGraph::Element* last_; + }; + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + // Parser implementations. + // + { + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + + // Parser aggregates. + // + if (aggregate) + { + GlobalElement element (*this, type_set); + Traversal::Names names (element); + + Traversal::Namespace::names (ns, names); + } + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Imports::traverse (i); + } + } + + static Char const* seen_key; + }; + + Char const* Uses::seen_key = "cxx-hybrid-parser-name-processor-seen"; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + // Pass one - assign names to global types. This pass cannot + // be combined with pass two because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count (Uses::seen_key)) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (Uses::seen_key, true); + + schema.dispatch (tu); + } + + // Pass two - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + + Void ParserNameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/hybrid/parser-name-processor.hxx b/xsde/cxx/hybrid/parser-name-processor.hxx new file mode 100644 index 0000000..ea3e985 --- /dev/null +++ b/xsde/cxx/hybrid/parser-name-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/hybrid/parser-name-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX +#define CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class ParserNameProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx new file mode 100644 index 0000000..4f5fc38 --- /dev/null +++ b/xsde/cxx/hybrid/parser-source.cxx @@ -0,0 +1,1185 @@ +// file : xsde/cxx/hybrid/parser-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (epimpl_custom (l)); + + if (!name) + return; + + String const& type (fq_name (l)); + String const& base (epstate_base (l)); + String const& member (epstate_member (l)); + String item (unclash (epskel (l), "item")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + os << name << "::" << endl + << name << " (bool b)" + << "{" + << "this->" << base << " = b;" + << "this->" << member << " = 0;" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "if (!this->" << base << ")" << endl + << "delete this->" << member << ";" + << "}"; + + // reset + // + if (reset) + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << epskel (l) << "::_reset ();" + << endl + << "if (!this->" << base << ")" + << "{" + << "delete this->" << member << ";" + << "this->" << member << " = 0;" + << "}" + << "}"; + + // pre_impl + // + os << "void " << name << "::" << endl + << pre_impl_name (l) << " (" << type << "* x)" + << "{" + << "this->" << member << " = x;" + << "}"; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (exceptions) + os << "this->" << pre_impl_name (l) << " (new " << type << ");"; + else + os << type << "* x = new " << type << ";" + << "if (x)" << endl + << "this->" << pre_impl_name (l) << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + + os << "}"; + + // item + // + String const& arg (parg_type (l.argumented ().type ())); + + os << "void " << name << "::" << endl + << item << " (" << arg << " i)" + << "{"; + + if (exceptions) + os << "this->" << member << "->push_back (i);"; + else + os << "if (this->" << member << "->push_back (i))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + + os << "}"; + + // post + // + String const& ret (pret_type (l)); + + os << ret << " " << name << "::" << endl + << post_name (l) << " ()" + << "{" + << type << "* r = this->" << member << ";" + << "this->" << member << " = 0;" + << "return r;" + << "}"; + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (epimpl_custom (u)); + + if (!name) + return; + + String const& type (fq_name (u)); + String const& state (epstate (u)); + String const& ret (pret_type (u)); + String const& value (u.context ().get ("value")); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (stl) + { + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{" + << "this->" << state << ".str_.clear ();" + << "}"; + + // _characters + // + os << "void " << name << "::" << endl + << "_characters (const " << string_type << "& s)" + << "{" + << "this->" << state << ".str_.append (s.data (), s.size ());" + << "}"; + + // post + // + os << ret << " " << name << "::" << endl + << post_name (u) << " ()" + << "{" + << "::std::string s;" + << "s.swap (this->" << state << ".str_);" + << type << " r;" + << "r." << value << " (s);" + << "return r;" + << "}"; + } + else + { + String const& base (epstate_base (u)); + + // c-tor + // + os << name << "::" << endl + << name << " (bool b)" + << "{" + << "this->" << base << " = b;" + << "this->" << state << ".x_ = 0;" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "if (!this->" << base << ")" << endl + << "delete this->" << state << ".x_;" + << "}"; + + // reset + // + if (reset) + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << epskel (u) << "::_reset ();" + << endl + << "if (!this->" << base << ")" + << "{" + << "delete this->" << state << ".x_;" + << "this->" << state << ".x_ = 0;" + << "}" + << "}"; + + // pre_impl + // + os << "void " << name << "::" << endl + << pre_impl_name (u) << " (" << type << "* x)" + << "{" + << "this->" << state << ".x_ = x;"; + + if (exceptions) + os << "this->" << state << ".str_.assign (\"\", 0);"; + else + { + os << endl + << "if (this->" << state << ".str_.assign (\"\", 0))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (exceptions) + os << "this->" << pre_impl_name (u) << " (new " << type << ");"; + else + os << type << "* x = new " << type << ";" + << "if (x)" << endl + << "this->" << pre_impl_name (u) << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + + os << "}"; + + // _characters + // + os << "void " << name << "::" << endl + << "_characters (const " << string_type << "& s)" + << "{"; + + if (exceptions) + os << "this->" << state << ".str_.append (s.data (), s.size ());"; + else + { + os << "if (this->" << state << ".str_.append (" << + "s.data (), s.size ()))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + + // post + // + os << ret << " " << name << "::" << endl + << post_name (u) << " ()" + << "{" + << type << "* r = this->" << state << ".x_;" + << "this->" << state << ".x_ = 0;" + << "r->" << value << " (this->" << state << ".str_.detach ());" + << "return r;" + << "}"; + } + } + }; + + struct ParserContext: Context + { + ParserContext (Context& c) + : Context (c) + { + } + + // Return the access sequence up until this particle. If + // element is false then the access sequence for the + // container is returned. Otherwise the access sequence + // for the current element in the container is returned. + // + String + access_seq (SemanticGraph::Particle& p, Boolean element = true) + { + using namespace SemanticGraph; + + String r; + + Boolean seq (false); + + Compositor* c; + + if (p.contained_particle_p ()) + { + c = &p.contained_particle ().compositor (); + + // Check if this particle is a sequence. In this case + // we just need the top-level struct member. + // + if (element && p.max () != 1 && p.is_a ()) + { + seq = true; + } + else + { + for (;; c = &c->contained_particle ().compositor ()) + { + if (c->context ().count ("type")) + { + // Not a see-through compositor. + // + if (c->max () != 1) + { + String const& ptr (epstate_member (*c)); + + if (!r) + { + r = ptr; + r += L"->"; + } + else + { + String tmp; + tmp.swap (r); + r = ptr; + r += L"->"; + r += tmp; + } + + seq = true; + break; + } + else + { + String const& func (ename (*c)); + + if (!r) + { + r = func; + r += L" ()."; + } + else + { + String tmp; + tmp.swap (r); + r = func; + r += L" ()."; + r += tmp; + } + } + } + + if (c->contained_compositor_p ()) + break; + } + } + + // Get to the top in case we bailed out on a sequence. + // + while (!c->contained_compositor_p ()) + c = &c->contained_particle ().compositor (); + } + else + { + // This particle is a top-level compositor. + // + c = &dynamic_cast (p); + seq = element && c->max () != 1; + } + + Complex& t ( + dynamic_cast ( + c->contained_compositor ().container ())); + + if (!seq) + { + Boolean fixed (fixed_length (t)); + String const& s (epstate_member (t)); + + if (!r) + { + r = s; + r += fixed ? L"." : L"->"; + } + else + { + String tmp; + tmp.swap (r); + r = s; + r += fixed ? L"." : L"->"; + r += tmp; + } + } + + String tmp; + tmp.swap (r); + r = epstate (t); + r += L"."; + r += tmp; + + return r; + } + + String + access_seq (SemanticGraph::Attribute& a) + { + using namespace SemanticGraph; + + Complex& t (dynamic_cast (a.scope ())); + + String r (epstate (t)); + r += L"."; + r += epstate_member (t); + r += fixed_length (t) ? L"." : L"->"; + + return r; + } + }; + + // + // Test for presence of var-length compositor in choice + // that need initialization. + // + + struct CompositorTest: Traversal::Compositor + { + CompositorTest (Boolean& p) + : p_ (p) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + // We are only interested in var-length required compositors. + // + if (c.max () == 1 && + c.min () == 1 && + !c.context ().get ("fixed")) + p_ = true; + } + + private: + Boolean& p_; + }; + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + ParserContext + { + CompositorCallback (Context& c) + : ParserContext (c), compositor_test_ (init_) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + String const& s (epimpl_custom (scope (a))); + + os << "void " << s << "::" << endl + << eppresent (a) << " ()" + << "{"; + + String access (access_seq (a)); + + if (fixed_length (a)) + os << "this->" << access << epresent (a) << " (true);"; + else + { + String const& name (ename (a)); + String const& type (etype (a)); + String const& scope (fq_scope (a)); + + if (exceptions) + os << "this->" << access << name << " (new " << + scope << "::" << type << ");"; + else + os << scope << "::" << type << "* x = new " << + scope << "::" << type << ";" + << "if (x)" << endl + << "this->" << access << name << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + String const& s (epimpl_custom (scope (c))); + String const& access (access_seq (c)); + String const& type_scope (fq_scope (c)); + + os << "void " << s << "::" << endl + << eparm (c) << " (" << eparm_tag (c) << " t)" + << "{"; + + if (c.max () != 1) + { + String const& name (ename (c)); + String const& type (etype (c)); + String const& access_s (access_seq (c, false)); + String const& ptr (epstate_member (c)); + + if (fixed_length (c)) + { + if (exceptions) + os << "this->" << access_s << name << " ().push_back (" << + type_scope << "::" << type << " ());"; + else + os << "if (this->" << access_s << name << " ().push_back (" << + type_scope << "::" << type << " ()))" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + + os << "this->" << access << ptr << " = &this->" << + access_s << name << " ().back ();"; + } + else + { + os << "this->" << access << ptr << " = new " << + type_scope << "::" << type << ";"; + + if (exceptions) + os << "this->" << access_s << name << " ().push_back (" << + "this->" << access << ptr << ");"; + else + os << "if (!this->" << access << ptr << " ||" << endl + << "this->" << access_s << name << " ().push_back (" << + "this->" << access << ptr << "))" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + } + + os << "this->" << access << ptr << "->"; + } + else if (c.min () == 0) + { + String const& name (ename (c)); + + if (fixed_length (c)) + os << "this->" << access << epresent (c) << " (true);"; + else + { + String const& type (etype (c)); + + if (exceptions) + os << "this->" << access << name << " (new " << + type_scope << "::" << type << ");"; + else + os << type_scope << "::" << type << "* x = new " << + type_scope << "::" << type << ";" + << "if (x)" << endl + << "this->" << access << name << " (x);" + << "else" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + } + + os << "this->" << access << name << " ()."; + } + else + { + // We may be in a choice in which case we get a nested + // type (and accessor function) even for min == max == 1. + // + if (c.context ().count ("type")) + os << "this->" << access << ename (c) << " ()."; + else + os << "this->" << access; + } + + os << earm (c) << " (static_cast< " << type_scope; + + if (c.context ().count ("type")) + os << "::" << etype (c); + + os << "::" << earm_tag (c) << " > (t));" + << endl; + + // Test whether we have any arms that need initialization. + // Those are var-length required compositors. + // + init_ = false; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()), e (c.contains_end ()); + !init_ && i != e; ++i) + { + compositor_test_.dispatch (i->particle ()); + } + + if (init_) + { + os << "switch (t)" + << "{"; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()), e (c.contains_end ()); + i != e; ++i) + { + // Test if this arm needs initialization. + // + init_ = false; + compositor_test_.dispatch (i->particle ()); + + if (init_) + { + SemanticGraph::Compositor& p ( + dynamic_cast ( + i->particle ())); + + os << "case " << eptag (p) << ":" + << "{"; + + String const& type (etype (p)); + String const& scope (fq_scope (p)); + + if (exceptions) + os << "this->" << access_seq (p) << ename (p) << + " (new " << scope << "::" << type << ");"; + else + os << scope << "::" << type << "* x = new " << + scope << "::" << type << ";" + << "if (x)" << endl + << "this->" << access_seq (p) << ename (p) << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + + os << "break;" + << "}"; + } + } + + os << "default:" + << "{" + << "break;" + << "}" + << "}"; + } + + os << "}"; + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + String const& sc (epimpl_custom (scope (s))); + + String const& access (access_seq (s)); + String const& access_s (access_seq (s, false)); + String const& name (ename (s)); + String const& type (etype (s)); + String const& scope (fq_scope (s)); + String const& ptr (epstate_member (s)); + + os << "void " << sc << "::" << endl + << epnext (s) << " ()" + << "{"; + + if (fixed_length (s)) + { + if (exceptions) + os << "this->" << access_s << name << " ().push_back (" << + scope << "::" << type << " ());"; + else + os << "if (this->" << access_s << name << " ().push_back (" << + scope << "::" << type << " ()))" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + + os << "this->" << access << ptr << " = &this->" << + access_s << name << " ().back ();"; + } + else + { + os << "this->" << access << ptr << " = new " << + scope << "::" << type << ";"; + + if (exceptions) + os << "this->" << access_s << name << " ().push_back (" << + "this->" << access << ptr << ");"; + else + os << "if (!this->" << access << ptr << " ||" << endl + << "this->" << access_s << name << " ().push_back (" << + "this->" << access << ptr << "))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + } + else if (s.min () == 0) + { + String const& sc (epimpl_custom (scope (s))); + + os << "void " << sc << "::" << endl + << eppresent (s) << " ()" + << "{"; + + String access (access_seq (s)); + + if (fixed_length (s)) + os << "this->" << access << epresent (s) << " (true);"; + else + { + String const& name (ename (s)); + String const& type (etype (s)); + String const& scope (fq_scope (s)); + + if (exceptions) + os << "this->" << access << name << " (new " << + scope << "::" << type << ");"; + else + os << scope << "::" << type << "* x = new " << + scope << "::" << type << ";" + << "if (x)" << endl + << "this->" << access << name << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Complex& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + + private: + Boolean init_; + CompositorTest compositor_test_; + }; + + struct ParticleCallback: Traversal::Element, ParserContext + { + ParticleCallback (Context& c) + : ParserContext (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Complex; + + String const& name (epname (e)); + String const& arg (parg_type (e.type ())); + Complex& c (dynamic_cast (e.scope ())); + + os << "void " << epimpl_custom (c) << "::" << endl + << name << " ("; + + if (arg != L"void") + { + os << arg << " x)" + << "{"; + + if (e.max () != 1) + { + if (exceptions) + os << "this->" << access_seq (e) << ename (e) << + " ().push_back (x);"; + else + os << "if (this->" << access_seq (e) << ename (e) << + " ().push_back (x))" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + else + { + os << "this->" << access_seq (e) << ename (e) << " (x);"; + } + + os << "}"; + } + else + { + os << ")" + << "{" + << "}"; + } + } + }; + + struct AttributeCallback: Traversal::Attribute, ParserContext + { + AttributeCallback (Context& c) + : ParserContext (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Complex; + + String const& name (epname (a)); + String const& arg (parg_type (a.type ())); + Complex& c (dynamic_cast (a.scope ())); + + os << "void " << epimpl_custom (c) << "::" << endl + << name << " ("; + + if (arg != L"void") + { + os << arg << " x)" + << "{" + << "this->" << access_seq (a) << ename (a) << " (x);" + << "}"; + } + else + { + os << ")" + << "{" + << "}"; + } + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + base_name_ (c, TypeName::base), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + String const& name (epimpl_custom (c)); + + if (!name) + return; + + Boolean hb (c.inherits_p ()); + Boolean restriction (restriction_p (c)); + Boolean fixed (fixed_length (c)); + Boolean c_string_base (false); + + if (!stl && hb) + { + StringType test (c_string_base); + test.dispatch (c.inherits ().base ()); + } + + String const& ret (pret_type (c)); + + String const& state (epstate (c)); + String const& member (epstate_member (c)); + String const& type (fq_name (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (!fixed || (hb && tiein)) + { + os << name << "::" << endl + << name << " (" << (fixed ? "" : "bool b") << ")"; + + if (hb) + { + if (tiein) + os << endl + << ": " << epskel (c) << " (&base_impl_)"; + + SemanticGraph::Type& b (c.inherits ().base ()); + + // C-string-based built-in parser implementations don't + // have c-tor (bool base). + // + if (!c_string_base && !fixed_length (b)) + { + if (tiein) + os << "," << endl + << " " << "base_impl_" << " (true)"; + else + os << endl + << ": " << fq_name (b, "p:impl") << " (true)"; + } + } + + os << "{"; + + if (!fixed) + os << "this->" << epstate_base (c) << " = b;" + << "this->" << state << "." << member << " = 0;"; + + os << "}"; + } + + if (!fixed) + { + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "if (!this->" << epstate_base (c) << ")" << endl + << "delete this->" << state << "." << member << ";" + << "}"; + + // reset + // + if (reset) + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + if (mixin && hb) + os << epimpl (c); //@@ fq-name + else + os << epskel (c); //@@ fq-name + + os << "::_reset ();" + << endl; + + os << "if (!this->" << epstate_base (c) << ")" + << "{" + << "delete this->" << state << "." << member << ";" + << "this->" << state << "." << member << " = 0;" + << "}" + << "}"; + } + + // pre_impl + // + if (!fixed) + { + os << "void " << name << "::" << endl + << pre_impl_name (c) << " (" << type << "* x)" + << "{" + << "this->" << state << "." << member << " = x;"; + + // Call base pre_impl (var-length) or pre (fix-length). C-string- + // based built-in parser implementations don't have pre_impl(). + // + if (hb && !c_string_base) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + if (fixed_length (b)) + os << "pre ();"; + else + os << pre_impl_name (b) << " (x);"; + } + + os << "}"; + } + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (fixed) + { + if (hb) + { + // Our base is also fixed-length so call its pre() + // + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (c.inherits ().base ()) << "::"; //@@ fq-name. + + os << "pre ();"; + } + + os << "this->" << state << "." << member << " = " << + type << " ();"; + } + else + { + if (exceptions) + os << "this->" << pre_impl_name (c) << " (new " << type << ");"; + else + os << type << "* x = new " << type << ";" + << "if (x)" << endl + << "this->" << pre_impl_name (c) << " (x);" + << "else" << endl + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"; + } + + os << "}"; + + // Parser callbacks. + // + if (!restriction) + { + names (c, names_attribute_callback_); + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + os << ret << " " << name << "::" << endl + << post_name (c) << " ()" + << "{"; + + if (hb) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + // Default parser implementations for anyType and + // anySimpleType return void. + // + if (!b.is_a () && + !b.is_a ()) + { + // If our base is a fixed-length type or C-string-base, then + // copy the data over. + // + if (fixed_length (b)) + { + os << "static_cast< "; + + base_name_.dispatch (b); + + os << "& > (" << (fixed ? "" : "*") << "this->" << + state << "." << member << ") = "; + } + + if (c_string_base) + { + os << "static_cast< "; + + base_name_.dispatch (b); + + os << "* > (this->" << + state << "." << member << ")->base_value ("; + } + + if (tiein) + os << "this->base_impl_."; + else + os << epimpl (b) << "::"; //@@ fq-name. + + os << post_name (b) << " ()"; + + if (c_string_base) + os << ")"; + + os << ";"; + } + } + + if (fixed) + os << "return this->" << state << "." << member << ";"; + else + os << type << "* r = this->" << state << "." << member << ";" + << "this->" << state << "." << member << " = 0;" + << "return r;"; + + os << "}"; + } + + private: + TypeName base_name_; + + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_parser_source (Context& ctx) + { + { + // Emit "weak" header includes for the object model types. + // Otherwise we cannot delete the objects of forward-declared + // classes in the parser implementations. + // + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/parser-source.hxx b/xsde/cxx/hybrid/parser-source.hxx new file mode 100644 index 0000000..23f1399 --- /dev/null +++ b/xsde/cxx/hybrid/parser-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/parser-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_PARSER_SOURCE_HXX +#define CXX_HYBRID_PARSER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_parser_source (Context&); + } +} + +#endif // CXX_HYBRID_PARSER_SOURCE_HXX diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.cxx b/xsde/cxx/hybrid/serializer-aggregate-header.cxx new file mode 100644 index 0000000..b697715 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-aggregate-header.cxx @@ -0,0 +1,847 @@ +// file : xsde/cxx/hybrid/serializer-aggregate-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + typedef Cult::Containers::Set InstanceSet; + + // For base types we only want member's types, but not the + // base itself. + // + struct BaseType: Traversal::Complex, Context + { + BaseType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + }; + + struct SerializerDef: Traversal::Type, + Traversal::List, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set) + : Context (c), map_ (map), set_ (set), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (t)); + map_[&t] = inst; + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (map_.find (&l) == map_.end ()) + { + String inst (find_instance_name (l)); + map_[&l] = inst; + + dispatch (l.argumented ().type ()); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (map_.find (&c) == map_.end ()) + { + String inst (find_instance_name (c)); + map_[&c] = inst; + + // Use base type's serializers in case of a restriction + // since we are not capable of using a derived type + // in place of a base (need upcasting, ect). + // + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + fund_type (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + fund_type (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fund_type (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fund_type (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fund_type (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + fund_type (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fund_type (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + fund_type (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fund_type (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + fund_type (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fund_type (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fund_type (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fund_type (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fund_type (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fund_type (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fund_type (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + fund_type (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + fund_type (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + fund_type (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + fund_type (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + fund_type (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + fund_type (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + fund_type (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + fund_type (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + fund_type (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + fund_type (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + fund_type (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + fund_type (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + fund_type (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + fund_type (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + fund_type (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + fund_type (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + fund_type (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + fund_type (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + fund_type (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + fund_type (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + fund_type (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + fund_type (t, "day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + fund_type (t, "month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + fund_type (t, "month_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + fund_type (t, "year"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + fund_type (t, "year_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + fund_type (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + fund_type (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + fund_type (t, "entities"); + } + + private: + virtual Void + fund_type (SemanticGraph::Type& t, String const& name) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (name)); + map_[&t] = inst; + } + } + + String + find_instance_name (String const& raw_name) + { + String name (escape (raw_name + L"_s_")); + + for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (raw_name + L"_s" + os.str () + L"_"); + } + + set_.insert (name); + return name; + } + + String + find_instance_name (SemanticGraph::Type& t) + { + return find_instance_name (t.name ()); + } + + TypeInstanceMap& map_; + InstanceSet& set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + + if (!tc.count ("saggr")) + return; + + String const& name (tc.get ("saggr")); + + String pre (unclash (name, "pre")); + String post (unclash (name, "post")); + String root_serializer (unclash (name, "root_serializer")); + String error, reset; + + InstanceSet set; + set.insert (pre); + set.insert (post); + set.insert (name); + set.insert (root_serializer); + + if (!exceptions) + { + error = unclash (name, "_error"); + set.insert (error); + } + + if (Context::reset) + { + reset = unclash (name, "reset"); + set.insert (reset); + } + + tc.set ("saggr-map", TypeInstanceMap ()); + TypeInstanceMap& map (tc.get ("saggr-map")); + + SerializerDef def (*this, map, set); + def.dispatch (t); + + String const& root_member (map.find (&t)->second); + + os << "// Serializer aggregate for the " << comment (t.name ()) << + " type." << endl + << "//" << endl; + + os << "class " << name + << "{" + << "public:" << endl; + + // c-tor () + // + os << name << " ();" + << endl; + + // pre () + // + String const& arg (sarg_type (t)); + + os << "void" << endl + << pre << " ("; + + if (arg != L"void") + os << arg << " x"; + + os <<")" + << "{" + << "this->" << root_member << ".pre (" << + (arg != L"void" ? "x" : "") << ");" + << "}"; + + // post () + // + os << "void" << endl + << post << " ()" + << "{" + << "this->" << root_member << ".post ();" + << "}"; + + // root_serializer () + // + os << fq_name (t, "s:impl") << "&" << endl + << root_serializer << " ()" + << "{" + << "return this->" << root_member << ";" + << "}"; + + // _error () + // + if (error) + { + os << xs_ns_name () << "::serializer_error" << endl + << error << " ()" + << "{" + << "return this->" << root_member << "._error ();" + << "}"; + } + + // reset () + // + if (reset) + { + os << "void" << endl + << reset << " ()" + << "{" + << "this->" << root_member << "._reset ();" + << "}"; + } + + os << "public:" << endl; + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + os << fq_name (*i->first, "s:impl") << " " << i->second << ";"; + + os << "};"; + } + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("saggr")) + return; + + SemanticGraph::Type& t (e.type ()); + String const& name (ec.get ("saggr")); + + String pre (unclash (name, "pre")); + String post (unclash (name, "post")); + String root_serializer (unclash (name, "root_serializer")); + String root_name (unclash (name, "root_name")); + String root_namespace (unclash (name, "root_namespace")); + String error, reset; + + InstanceSet set; + set.insert (pre); + set.insert (post); + set.insert (name); + set.insert (root_serializer); + set.insert (root_name); + set.insert (root_namespace); + + if (!exceptions) + { + error = unclash (name, "_error"); + set.insert (error); + } + + if (Context::reset) + { + reset = unclash (name, "reset"); + set.insert (reset); + } + + ec.set ("saggr-map", TypeInstanceMap ()); + TypeInstanceMap& map (ec.get ("saggr-map")); + + SerializerDef def (*this, map, set); + def.dispatch (t); + + String const& root_member (map.find (&t)->second); + + os << "// Serializer aggregate for the " << comment (e.name ()) << + " element." << endl + << "//" << endl; + + os << "class " << name + << "{" + << "public:" << endl; + + // c-tor () + // + os << name << " ();" + << endl; + + // pre () + // + String const& arg (sarg_type (t)); + + os << "void" << endl + << pre << " ("; + + if (arg != L"void") + os << arg << " x"; + + os <<")" + << "{" + << "this->" << root_member << ".pre (" << + (arg != L"void" ? "x" : "") << ");" + << "}"; + + // post () + // + os << "void" << endl + << post << " ()" + << "{" + << "this->" << root_member << ".post ();" + << "}"; + + // root_serializer () + // + os << fq_name (t, "s:impl") << "&" << endl + << root_serializer << " ()" + << "{" + << "return this->" << root_member << ";" + << "}"; + + // root_name () + // + os << "static const char*" << endl + << root_name << " ();" + << endl; + + // root_namespace () + // + os << "static const char*" << endl + << root_namespace << " ();" + << endl; + + // _error () + // + if (error) + { + os << xs_ns_name () << "::serializer_error" << endl + << error << " ()" + << "{" + << "return this->" << root_member << "._error ();" + << "}"; + } + + // reset () + // + if (reset) + { + os << "void" << endl + << reset << " ()" + << "{" + << "this->" << root_member << "._reset ();" + << "}"; + } + + os << "public:" << endl; + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + os << fq_name (*i->first, "s:impl") << " " << i->second << ";"; + + os << "};"; + } + }; + } + + Void + generate_serializer_aggregate_header (Context& ctx) + { + Boolean gen (false); + + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + AggregateTest test (gen, "saggr"); + + schema >> schema_names >> ns >> names >> test; + + schema.dispatch (ctx.schema_root); + } + + if (gen) + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + GlobalType type (ctx); + GlobalElement element (ctx); + + names >> type; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.hxx b/xsde/cxx/hybrid/serializer-aggregate-header.hxx new file mode 100644 index 0000000..3fde7b4 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-aggregate-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/serializer-aggregate-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_SERIALIZER_AGGREGATE_HEADER_HXX +#define CXX_HYBRID_SERIALIZER_AGGREGATE_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_serializer_aggregate_header (Context&); + } +} + +#endif // CXX_HYBRID_SERIALIZER_AGGREGATE_HEADER_HXX diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.cxx b/xsde/cxx/hybrid/serializer-aggregate-source.cxx new file mode 100644 index 0000000..7e305b6 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-aggregate-source.cxx @@ -0,0 +1,330 @@ +// file : xsde/cxx/hybrid/serializer-aggregate-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + // + // + struct ParticleArg: Traversal::Element, Context + { + ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&e.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct AttributeArg: Traversal::Attribute, Context + { + AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&a.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct ArgList : Traversal::Complex, + Traversal::List, + Context + { + ArgList (Context& c, TypeInstanceMap& map) + : Context (c), + map_ (map), + particle_ (c, map, first_), + attribute_ (c, map, first_), + first_ (true) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << "this->" << map_[&l.argumented ().type ()]; + } + + private: + TypeInstanceMap& map_; + + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleArg particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + AttributeArg attribute_; + + Boolean first_; + }; + + struct SerializerConnect: Traversal::List, + Traversal::Complex, + Context + { + SerializerConnect (Context& c, TypeInstanceMap& map) + : Context (c), map_ (map) + { + } + + virtual Void + traverse (SemanticGraph::List& l) + { + os << "this->" << map_[&l] << ".serializers (this->" << + map_[&l.argumented ().type ()] << ");" + << endl; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (has_members (c)) + { + os << "this->" << map_[&c] << ".serializers ("; + + ArgList args (*this, map_); + args.dispatch (c); + + os << ");" + << endl; + } + } + + private: + Boolean + has_members (SemanticGraph::Complex& c) + { + using SemanticGraph::Complex; + + if (has (c)) + return true; + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&b)) + return has_members (*cb); + + return b.is_a (); + } + + return false; + } + + private: + TypeInstanceMap& map_; + }; + + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + + if (!tc.count ("saggr")) + return; + + String const& name (tc.get ("saggr")); + TypeInstanceMap& map (tc.get ("saggr-map")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << name << "::" << endl + << name << " ()" + << "{"; + + SerializerConnect connect (*this, map); + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + connect.dispatch (*i->first); + + os << "}"; + } + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("saggr")) + return; + + String const& name (ec.get ("saggr")); + TypeInstanceMap& map (ec.get ("saggr-map")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << name << "::" << endl + << name << " ()" + << "{"; + + SerializerConnect connect (*this, map); + + for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ()); + i != end; ++i) + connect.dispatch (*i->first); + + os << "}"; + + // root_name () + // + String root_name (unclash (name, "root_name")); + + os << "const char* " << name << "::" << endl + << root_name << " ()" + << "{" + << "return " << strlit (e.name ()) << ";" + << "}"; + + // root_namespace () + // + String root_namespace (unclash (name, "root_namespace")); + + os << "const char* " << name << "::" << endl + << root_namespace << " ()" + << "{" + << "return " << strlit (e.namespace_ ().name ()) << ";" + << "}"; + } + }; + } + + Void + generate_serializer_aggregate_source (Context& ctx) + { + Boolean gen (false); + + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + AggregateTest test (gen, "saggr"); + + schema >> schema_names >> ns >> names >> test; + + schema.dispatch (ctx.schema_root); + } + + if (gen) + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + GlobalType type (ctx); + GlobalElement element (ctx); + + names >> type; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.hxx b/xsde/cxx/hybrid/serializer-aggregate-source.hxx new file mode 100644 index 0000000..c011366 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-aggregate-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/serializer-aggregate-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_SERIALIZER_AGGREGATE_SOURCE_HXX +#define CXX_HYBRID_SERIALIZER_AGGREGATE_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_serializer_aggregate_source (Context&); + } +} + +#endif // CXX_HYBRID_SERIALIZER_AGGREGATE_SOURCE_HXX diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx new file mode 100644 index 0000000..c6fbc6c --- /dev/null +++ b/xsde/cxx/hybrid/serializer-header.cxx @@ -0,0 +1,534 @@ +// file : xsde/cxx/hybrid/serializer-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (esimpl_custom (l)); + + // We may not need to generate the class if this serializer is + // being customized. + // + if (name) + { + String const& skel (esskel (l)); + String const& arg (sarg_type (l)); + String const& ret (sret_type (l.argumented ().type ())); + + String item (unclash (skel, "item")); + String item_next (unclash (skel, "item_next")); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << skel + << "{" + << "public:" << endl; + + // pre + // + os << "virtual void" << endl + << "pre (" << arg << ");" + << endl; + + // item_next + // + os << "virtual bool" << endl + << item_next << " ();" + << endl; + + // item + // + os << "virtual " << ret << endl + << item << " ();" + << endl; + + // State. + // + os << (tiein ? "public:" : "protected:") << endl; + + String const& type (fq_name (l)); + String const& state_type (esstate_type (l)); + + os << "struct " << state_type + << "{" + << type << "::const_iterator i_;" + << type << "::const_iterator end_;" + << "};" + << state_type << " " << esstate (l) << ";" + << "};"; + } + + // Generate include for custom serializer. + // + if (l.context ().count ("s:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + l.context ().get ("s:impl-include")) << endl + << endl; + + open_ns (); + } + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (esimpl_custom (u)); + + // We may not need to generate the class if this serializer is + // being customized. + // + if (name) + { + String const& arg (sarg_type (u)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << esskel (u) + << "{" + << "public:" << endl; + + // pre + // + os << "virtual void" << endl + << "pre (" << arg << ");" + << endl; + + // _serialize_content + // + os << "virtual void" << endl + << "_serialize_content ();" + << endl; + + // State. + // + os << (tiein ? "public:" : "protected:") << endl + << "const " << fq_name (u) << "* " << esstate (u) << ";" + << "};"; + } + + // Generate include for custom serializer. + // + if (u.context ().count ("s:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + u.context ().get ("s:impl-include")) << endl + << endl; + + open_ns (); + } + } + }; + + // + // State. + // + + struct CompositorState: Traversal::Compositor, Context + { + CompositorState (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + if (c.max () != 1) + { + String scope (fq_scope (c)); + String const& const_iterator (econst_iterator (c)); + + os << scope << "::" << const_iterator << " " << + esstate_member (c) << ";" + << scope << "::" << const_iterator << " " << + esstate_member_end (c) << ";"; + } + + Compositor::traverse (c); + } + }; + + struct ParticleState: Traversal::Element, Context + { + ParticleState (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + { + String scope (fq_scope (e)); + String const& const_iterator (econst_iterator (e)); + + os << scope << "::" << const_iterator << " " << + esstate_member (e) << ";" + << scope << "::" << const_iterator << " " << + esstate_member_end (e) << ";"; + } + } + }; + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + os << "virtual bool" << endl + << espresent (a) << " ();" + << endl; + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << espresent (c) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << esnext (c) << " ();" + << endl; + } + + os << "virtual " << esarm_tag (c) << endl + << esarm (c) << " ();" + << endl; + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << espresent (s) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << esnext (s) << " ();" + << endl; + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << espresent (e) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << esnext (e) << " ();" + << endl; + } + + String const& ret (sret_type (e.type ())); + + os << "virtual " << ret << endl + << esname (e) << " ();" + << endl; + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (a.optional ()) + { + os << "virtual bool" << endl + << espresent (a) << " ();" + << endl; + } + + String const& ret (sret_type (a.type ())); + + os << "virtual " << ret << endl + << esname (a) << " ();" + << endl; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + + // State. + // + compositor_state_ (c), + particle_state_ (c), + + // Callbacks. + // + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + // State. + // + contains_compositor_state_ >> compositor_state_; + compositor_state_ >> contains_particle_state_; + contains_particle_state_ >> compositor_state_; + contains_particle_state_ >> particle_state_; + + + // Callbacks. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + String const& name (esimpl_custom (c)); + + // We may not need to generate the class if this serializer is + // being customized. + // + if (name) + { + // In case of an inheritance-by-restriction, we don't need to + // generate serializer callbacks, etc. since they are the same + // as in the base. We only need the serialization/validation code. + // + Boolean restriction (restriction_p (c)); + + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + Boolean haa (has (c)); + + String const& arg (sarg_type (c)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << esskel (c); + + if (mixin && hb) + os << "," << endl + << " public " << fq_name (c.inherits ().base (), "s:impl"); + + os << "{" + << "public:" << endl; + + // c-tor + // + if (tiein && hb) + os << name << " ();" + << endl; + + // pre + // + os << "virtual void" << endl + << "pre (" << arg << ");" + << endl; + + // Member callbacks. + // + if (!restriction && (ha || he || hae || haa)) + { + if (ha || haa) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + + if (he || hae) + { + os << "// Elements." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_callback_); + } + } + + if (!restriction) + { + String const& state_type (esstate_type (c)); + String const& member (esstate_member (c)); + + os << "protected:" << endl + << "struct " << state_type + << "{" + << "const " << fq_name (c) << "* " << member << ";"; + + if (c.contains_compositor_p ()) + contains_compositor (c, contains_compositor_state_); + + os << "};" + << state_type << " " << esstate (c) << ";"; + } + + if (tiein && hb) + os << endl + << "protected:" << endl + << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;"; + + os << "};"; + } + + // Generate include for custom serializer. + // + if (c.context ().count ("s:impl-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + c.context ().get ("s:impl-include")) << endl + << endl; + + open_ns (); + } + } + + private: + // State. + // + CompositorState compositor_state_; + ParticleState particle_state_; + Traversal::ContainsCompositor contains_compositor_state_; + Traversal::ContainsParticle contains_particle_state_; + + // Callbacks. + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_serializer_header (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::impl_header); + Traversal::Names schema_names; + + Namespace ns (ctx, true); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/serializer-header.hxx b/xsde/cxx/hybrid/serializer-header.hxx new file mode 100644 index 0000000..d24bc6a --- /dev/null +++ b/xsde/cxx/hybrid/serializer-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/serializer-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_SERIALIZER_HEADER_HXX +#define CXX_HYBRID_SERIALIZER_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_serializer_header (Context&); + } +} + +#endif // CXX_HYBRID_SERIALIZER_HEADER_HXX diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx new file mode 100644 index 0000000..8d3c15d --- /dev/null +++ b/xsde/cxx/hybrid/serializer-name-processor.cxx @@ -0,0 +1,723 @@ +// file : xsde/cxx/hybrid/serializer-name-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + schema_path_ (file), + impl_suffix_ (ops.value ()), + aggr_suffix_ (ops.value ()), + options (ops), + schema (root), + schema_path (schema_path_), + aggregate (ops.value ()), + impl_suffix (impl_suffix_), + aggr_suffix (aggr_suffix_), + custom_serializer_map (custom_serializer_map_), + global_type_names (global_type_names_) + { + // Custom serializer mapping. + // + typedef Containers::Vector Vector; + Vector const& v (ops.value ()); + + for (Vector::ConstIterator i (v.begin ()), e (v.end ()); + i != e; ++i) + { + String s (*i); + + if (s.empty ()) + continue; + + // Split the string in two parts at the last '='. + // + Size pos (s.rfind ('=')); + + // If no delimiter found then both base and include are empty. + // + if (pos == String::npos) + { + custom_serializer_map_[s].base.clear (); + custom_serializer_map_[s].include.clear (); + continue; + } + + String name (s, 0, pos); + String rest (s, pos + 1); + + // See if we've got the include part after '/'. + // + pos = rest.find ('/'); + + String base, include; + + if (pos != String::npos) + { + base.assign (rest, 0, pos); + include.assign (rest, pos + 1, String::npos); + } + else + base = rest; + + custom_serializer_map_[name].base = base; + custom_serializer_map_[name].include = include; + } + } + + protected: + Context (Context& c) + : CXX::Context (c), + options (c.options), + schema (c.schema), + schema_path (c.schema_path), + aggregate (c.aggregate), + impl_suffix (c.impl_suffix), + aggr_suffix (c.aggr_suffix), + custom_serializer_map (c.custom_serializer_map), + global_type_names (c.global_type_names) + { + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + public: + using CXX::Context::ename; + + static String const& + ename (SemanticGraph::Compositor& c) + { + return c.context ().get ("name"); + } + + String + state_name (SemanticGraph::Compositor& c) + { + using namespace SemanticGraph; + + String r; + + for (Compositor* p (&c);; + p = &p->contained_particle ().compositor ()) + { + if (p->context ().count ("type")) + { + // Not a see-through compositor. + // + if (!r) + r = ename (*p); + else + { + String tmp; + tmp.swap (r); + r = ename (*p); + r += L"_"; + r += tmp; + } + } + + if (p->contained_compositor_p ()) + break; + } + + return r; + } + + String + state_name (SemanticGraph::Element& e) + { + String r (state_name (e.contained_particle ().compositor ())); + + if (!r) + r = ename (e); + else + { + r += L"_"; + r += ename (e); + } + + return r; + } + + public: + struct CustomSerializer + { + CustomSerializer (String const& b = L"", String const& i = L"") + : base (b), include (i) + { + } + + String base; + String include; + }; + + typedef + Cult::Containers::Map + CustomSerializerMap; + + private: + SemanticGraph::Path const schema_path_; + String const impl_suffix_; + String const aggr_suffix_; + CustomSerializerMap custom_serializer_map_; + + Cult::Containers::Map global_type_names_; + + public: + CLI::Options const& options; + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + Boolean aggregate; + String const& impl_suffix; + String const& aggr_suffix; + CustomSerializerMap const& custom_serializer_map; + + Cult::Containers::Map& global_type_names; + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + SemanticGraph::Context& lc (l.context ()); + + // In case of customization use s:impl-base instead of s:impl. + // If the name is empty then we are not generating anything. + // + String const& name (lc.count ("s:impl-base") + ? lc.get ("s:impl-base") + : lc.get ("s:impl")); + if (!name) + return; + + String const& skel (lc.get ("p:name")); + + NameSet set; + set.insert (name); + set.insert (unclash (skel, "item")); + set.insert (unclash (skel, "item_next")); + + String state_type (find_name (name + L"_state", set)); + lc.set ("sstate-type", state_type); + lc.set ("sstate", find_name (state_type, "_", set)); + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + SemanticGraph::Context& uc (l.context ()); + + // In case of customization use s:impl-base instead of s:impl. + // If the name is empty then we are not generating anything. + // + String const& name (uc.count ("s:impl-base") + ? uc.get ("s:impl-base") + : uc.get ("s:impl")); + if (!name) + return; + + NameSet set; + set.insert (name); + + uc.set ("sstate", find_name (name + L"_state", "_", set)); + } + }; + + // State names. + // + + struct CompositorState: Traversal::Compositor, Context + { + CompositorState (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + if (c.max () != 1) + { + SemanticGraph::Context& cc (c.context ()); + String b (state_name (c)); + cc.set ("sstate-member", find_name (b, L"_", set_)); + cc.set ("sstate-member-end", find_name (b + L"_end", L"_", set_)); + } + + Compositor::traverse (c); + } + + private: + NameSet& set_; + }; + + struct ParticleState: Traversal::Element, Context + { + ParticleState (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + { + SemanticGraph::Context& ec (e.context ()); + String b (state_name (e)); + ec.set ("sstate-member", find_name (b, L"_", set_)); + ec.set ("sstate-member-end", find_name (b + L"_end", L"_", set_)); + } + } + + private: + NameSet& set_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + + SemanticGraph::Context& cc (c.context ()); + + // In case of customization use s:impl-base instead of s:impl. + // If the name is empty then we are not generating anything. + // + String const& base (cc.count ("s:impl-base") + ? cc.get ("s:impl-base") + : cc.get ("s:impl")); + if (!base) + return; + + // Use skeleton's name set to make sure we don't clash + // with callbacks which we are overriding. + // + NameSet& set ( + cc.get ("cxx-serializer-name-processor-member-set")); + + String state_type (find_name (base + L"_state", set)); + cc.set ("sstate-type", state_type); + cc.set ("sstate", find_name (state_type, "_", set)); + + // State members are in a nested struct so use a new and + // empty name set. + // + NameSet state_set; + + String member ( + find_name (cc.get ("name"), "_", state_set)); + + cc.set ("sstate-member", member); + state_set.insert (member); + + // Assign state names. + // + if (!restriction && c.contains_compositor_p ()) + { + ParticleState particle (*this, state_set); + CompositorState compositor (*this, state_set); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + } + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& tc (t.context ()); + String const& name (t.name ()); + + tc.set ("s:impl", find_name (name + impl_suffix, set_)); + + // See if this serializer is being customized. + // + CustomSerializerMap::ConstIterator i ( + custom_serializer_map.find (name)); + + if (i != custom_serializer_map.end ()) + { + tc.set ("s:impl-base", i->second.base + ? find_name (i->second.base, set_) + : i->second.base); + + if (i->second.include) + tc.set ("s:impl-include", i->second.include); + } + + if (aggregate) + { + typedef Cult::Containers::Vector Names; + Names const& names (options.value ()); + + // Hopefully nobody will specify more than a handful of names. + // + for (Names::ConstIterator i (names.begin ()); + i != names.end (); ++i) + { + if (name == String (*i)) + { + tc.set ("saggr", find_name (name + aggr_suffix, set_)); + break; + } + } + } + } + + private: + NameSet& set_; + }; + + // + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c, NameSet& set) + : Context (c), set_ (set), last_ (0) + { + } + + ~GlobalElement () + { + if (last_ != 0 && options.value ()) + process (*last_); + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + Boolean p (false); + + if (last_ == 0 && options.value ()) + p = true; + + last_ = &e; + + if (!p && + !options.value () && + !options.value () && + !options.value () && + !options.value () && + options.value ().empty ()) + { + // By default process them all. + // + p = true; + } + + if (!p && options.value ()) + p = true; + + if (!p) + { + typedef Cult::Containers::Vector Names; + Names const& names (options.value ()); + + // Hopefully nobody will specify more than a handful of names. + // + for (Names::ConstIterator i (names.begin ()); + !p && i != names.end (); + ++i) + { + if (e.name () == String (*i)) + p = true; + } + } + + if (p) + process (e); + } + + private: + Void + process (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!ec.count ("saggr")) + { + ec.set ("saggr", find_name (e.name () + aggr_suffix, set_)); + } + } + + private: + NameSet& set_; + SemanticGraph::Element* last_; + }; + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + // Serializer implementations. + // + { + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + + // Serializer aggregates. + // + if (aggregate) + { + GlobalElement element (*this, type_set); + Traversal::Names names (element); + + Traversal::Namespace::names (ns, names); + } + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key)) + { + s.context ().set (seen_key, true); + Traversal::Imports::traverse (i); + } + } + + static Char const* seen_key; + }; + + Char const* Uses::seen_key = "cxx-hybrid-serializer-name-processor-seen"; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + // Pass one - assign names to global types. This pass cannot + // be combined with pass two because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count (Uses::seen_key)) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (Uses::seen_key, true); + + schema.dispatch (tu); + } + + // Pass two - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + + Void SerializerNameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/hybrid/serializer-name-processor.hxx b/xsde/cxx/hybrid/serializer-name-processor.hxx new file mode 100644 index 0000000..f69dfe4 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-name-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/hybrid/serializer-name-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX +#define CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class SerializerNameProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx new file mode 100644 index 0000000..37fff42 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-source.cxx @@ -0,0 +1,1001 @@ +// file : xsde/cxx/hybrid/serializer-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + // Some built-in types are passed by pointer to built-in serializer + // implementations. + // + struct TypePass: Traversal::Fundamental::NameTokens, + Traversal::Fundamental::QName, + Traversal::Fundamental::IdRefs, + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + Traversal::Fundamental::Entities, + Context + { + TypePass (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens&) + { + os << "&"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::QName&) + { + if (!stl) + os << "&"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs&) + { + os << "&"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary&) + { + os << "&"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary&) + { + os << "&"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&) + { + os << "&"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c), type_pass_ (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (esimpl_custom (l)); + + if (!name) + return; + + SemanticGraph::Type& t (l.argumented ().type ()); + + String const& skel (esskel (l)); + String const& arg (sarg_type (l)); + String const& ret (sret_type (t)); + + String item (unclash (skel, "item")); + String item_next (unclash (skel, "item_next")); + + os << "// " << name << endl + << "//" << endl + << endl; + + String const& state (esstate (l)); + + // pre + // + os << "void " << name << "::" << endl + << "pre (" << arg << " x)" + << "{" + << "this->" << state << ".i_ = x.begin ();" + << "this->" << state << ".end_ = x.end ();" + << "}"; + + // item_next + // + os << "bool " << name << "::" << endl + << item_next << " ()" + << "{" + << "return this->" << state << ".i_ != this->" << + state << ".end_;" + << "}"; + + // item + // + os << ret << " " << name << "::" << endl + << item << " ()" + << "{" + << "return "; + + type_pass_.dispatch (t); + + os << "*this->" << state << ".i_++;" + << "}"; + } + + private: + TypePass type_pass_; + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (esimpl_custom (u)); + + if (!name) + return; + + String const& state (esstate (u)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + String const& arg (sarg_type (u)); + + os << "void " << name << "::" << endl + << "pre (" << arg << " x)" + << "{" + << "this->" << state << " = &x;" + << "}"; + + // _serialize_content + // + String const& value (u.context ().get ("value")); + + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{"; + + if (stl) + { + os << "const ::std::string& s = this->" << state << "->" << + value << " ();" + << "this->_characters (s.c_str (), s.size ());"; + } + else + os << "this->_characters (" << + "this->" << state << "->" << value << " ());"; + + os << "}"; + } + }; + + // + // + struct SerializerContext: Context + { + SerializerContext (Context& c) + : Context (c) + { + } + + // Return the access sequence up until this particle. If + // element is false then the access sequence for the + // container is returned. Otherwise the access sequence + // for the current element in the container is returned. + // + String + access_seq (SemanticGraph::Particle& p, Boolean element = true) + { + using namespace SemanticGraph; + + String r; + + Boolean seq (false); + + Compositor* c; + + if (p.contained_particle_p ()) + { + c = &p.contained_particle ().compositor (); + + // Check if this particle is a sequence. In this case + // we just need the top-level struct member. + // + if (element && p.max () != 1) + { + seq = true; + } + else + { + for (;; c = &c->contained_particle ().compositor ()) + { + if (c->context ().count ("type")) + { + // Not a see-through compositor. + // + if (c->max () != 1) + { + String const& iter (esstate_member (*c)); + + if (!r) + { + r = iter; + r += L"->"; + } + else + { + String tmp; + tmp.swap (r); + r = iter; + r += L"->"; + r += tmp; + } + + seq = true; + break; + } + else + { + String const& func (ename (*c)); + + if (!r) + { + r = func; + r += L" ()."; + } + else + { + String tmp; + tmp.swap (r); + r = func; + r += L" ()."; + r += tmp; + } + } + } + + if (c->contained_compositor_p ()) + break; + } + } + + // Get to the top in case we bailed out on a sequence. + // + while (!c->contained_compositor_p ()) + c = &c->contained_particle ().compositor (); + } + else + { + // This particle is a top-level compositor. + // + c = &dynamic_cast (p); + seq = element && c->max () != 1; + } + + Complex& t ( + dynamic_cast ( + c->contained_compositor ().container ())); + + if (!seq) + { + String const& s (esstate_member (t)); + + if (!r) + { + r = s; + r += L"->"; + } + else + { + String tmp; + tmp.swap (r); + r = s; + r += L"->"; + r += tmp; + } + } + + String tmp; + tmp.swap (r); + r = esstate (t); + r += L"."; + r += tmp; + + return r; + } + + String + access_seq (SemanticGraph::Attribute& a) + { + using namespace SemanticGraph; + + Complex& t (dynamic_cast (a.scope ())); + + String r (esstate (t)); + r += L"."; + r += esstate_member (t); + r += L"->"; + + return r; + } + }; + + // + // Test for presence of sequences. + // + + struct CompositorTest: Traversal::Choice, + Traversal::Sequence + { + CompositorTest (Boolean& seq) + : seq_ (seq) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + seq_ = true; + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + seq_ = true; + else if (s.min () == 1) + { + // Test nested particles of the see-through sequence. + // + Sequence::traverse (s); + } + } + + private: + Boolean& seq_; + }; + + struct ParticleTest: Traversal::Element + { + ParticleTest (Boolean& seq) + : seq_ (seq) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + seq_ = true; + } + + private: + Boolean& seq_; + }; + + // + // State initializers. + // + + struct CompositorInit: Traversal::Choice, + Traversal::Sequence, + SerializerContext + { + CompositorInit (Context& c) + : SerializerContext (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + { + String access (access_seq (c)); + String access_s (access_seq (c, false)); + String const& iter (esstate_member (c)); + String const& end (esstate_member_end (c)); + + // Initialize the iterator. + // + os << "this->" << access << end << " = this->" << + access_s << ename (c) << " ().end ();" + << "this->" << access << iter << " = this->" << + access << end << ";"; + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + String access (access_seq (s)); + String access_s (access_seq (s, false)); + String const& iter (esstate_member (s)); + String const& end (esstate_member_end (s)); + + // Initialize the iterator. + // + os << "this->" << access << end << " = this->" << + access_s << ename (s) << " ().end ();" + << "this->" << access << iter << " = this->" << + access << end << ";"; + } + else if (s.min () == 1) + { + // Initialize nested particles of the see-through sequence. + // + Sequence::traverse (s); + } + } + }; + + struct ParticleInit: Traversal::Element, SerializerContext + { + ParticleInit (Context& c) + : SerializerContext (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + { + String access (access_seq (e)); + String access_s (access_seq (e, false)); + String const& iter (esstate_member (e)); + String const& end (esstate_member_end (e)); + String const& name (ename (e)); + + // Initialize the iterator. + // + os << "this->" << access << iter << " = this->" << + access_s << name << " ().begin ();" + << "this->" << access << end << " = this->" << + access_s << name << " ().end ();"; + } + } + }; + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + SerializerContext + { + CompositorCallback (Context& c, Traversal::ContainsParticle& init) + : SerializerContext (c), + init_ (init), + compositor_test_ (seq_), + particle_test_ (seq_) + { + compositor_test_ >> contains_particle_test_; + contains_particle_test_ >> compositor_test_; + contains_particle_test_ >> particle_test_; + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + String const& s (esimpl_custom (scope (a))); + + os << "bool " << s << "::" << endl + << espresent (a) << " ()" + << "{" + << "return this->" << access_seq (a) << epresent (a) << " ();" + << "}"; + } + + All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + SemanticGraph::Complex& t (scope (c)); + + String access (access_seq (c)); + String const& s (esimpl_custom (t)); + String const& arm_tag (esarm_tag (c)); + + if (c.max () != 1) + { + String access_s (access_seq (c, false)); + String const& iter (esstate_member (c)); + String const& end (esstate_member_end (c)); + + // When iterating over a compositor sequence, there is no + // simple place to increment the iterator. So we will need + // to increment it in *_next() and make sure we handle the + // first call in a special way. + // + os << "bool " << s << "::" << endl + << esnext (c) << " ()" + << "{" + << "if (this->" << access << iter << " != this->" << + access << end << ")" << endl + << "this->" << access << iter << "++;" + << "else" << endl + << "this->" << access << iter << " = this->" << + access_s << ename (c) << " ().begin ();" + << endl + << "return this->" << access << iter << " != this->" << + access << end << ";" + << "}"; + + os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl + << esarm (c) << " ()" + << "{" + << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl + << "this->" << access << iter << "->" << earm (c) << " ()));"; + } + else if (c.min () == 0) + { + os << "bool " << s << "::" << endl + << espresent (c) << " ()" + << "{" + << "return this->" << access << epresent (c) << " ();" + << "}"; + + os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl + << esarm (c) << " ()" + << "{" + << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl + << "this->" << access << ename (c) << " ()." << + earm (c) << " ()));"; + } + else + { + os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl + << esarm (c) << " ()" + << "{" + << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl; + + + // We may be in a choice in which case we get a nested + // type (and accessor function) even for min == max == 1. + // + if (c.context ().count ("type")) + os << "this->" << access << ename (c) << " ()." << + earm (c) << " ()));"; + else + os << "this->" << access << earm (c) << " ()));"; + } + + // Test whether we have any arms that need initialization. + // + seq_ = false; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()), e (c.contains_end ()); + !seq_ && i != e; ++i) + { + contains_particle_test_.dispatch (*i); + } + + if (seq_) + { + os << "switch (t)" + << "{"; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()), e (c.contains_end ()); + i != e; ++i) + { + // Test if this arm needs initialization. + // + seq_ = false; + contains_particle_test_.dispatch (*i); + + if (seq_) + { + SemanticGraph::Particle& p (i->particle ()); + + os << "case " << estag (p) << ":" + << "{"; + init_.dispatch (*i); + os << "break;" + << "}"; + } + } + + os << "default:" + << "{" + << "break;" + << "}" + << "}"; + } + + os << "return t;" + << "}"; + + Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + String const& sc (esimpl_custom (scope (s))); + + if (s.max () != 1) + { + String access (access_seq (s)); + String access_s (access_seq (s, false)); + String const& iter (esstate_member (s)); + String const& end (esstate_member_end (s)); + + // When iterating over a compositor sequence, there is no + // simple place to increment the iterator. So we will need + // to increment it in *_next() and make sure we handle the + // first call in a special way. + // + os << "bool " << sc << "::" << endl + << esnext (s) << " ()" + << "{" + << "if (this->" << access << iter << " != this->" << + access << end << ")" << endl + << "this->" << access << iter << "++;" + << "else" << endl + << "this->" << access << iter << " = this->" << + access_s << ename (s) << " ().begin ();" + << endl + << "if (this->" << access << iter << " != this->" << + access << end << ")" + << "{"; + + Sequence::contains (s, init_); + + os << "return true;" + << "}" + << "else" << endl + << "return false;" + << "}"; + } + else if (s.min () == 0) + { + os << "bool " << sc << "::" << endl + << espresent (s) << " ()" + << "{" + << "if (this->" << access_seq (s) << epresent (s) << " ())" + << "{"; + + Sequence::contains (s, init_); + + os << "return true;" + << "}" + << "else" << endl + << "return false;" + << "}"; + } + + Sequence::traverse (s); + } + + private: + SemanticGraph::Complex& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + + private: + Traversal::ContainsParticle& init_; + + Boolean seq_; + CompositorTest compositor_test_; + ParticleTest particle_test_; + Traversal::ContainsParticle contains_particle_test_; + }; + + struct ParticleCallback: Traversal::Element, SerializerContext + { + ParticleCallback (Context& c) + : SerializerContext (c), type_pass_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& s ( + esimpl_custom ( + dynamic_cast (e.scope ()))); + + SemanticGraph::Type& t (e.type ()); + String const& ret (sret_type (t)); + String access (access_seq (e)); + + if (e.max () != 1) + { + String const& iter (esstate_member (e)); + + os << "bool " << s << "::" << endl + << esnext (e) << " ()" + << "{" + << "return this->" << access << iter << " != this->" << + access << esstate_member_end (e) << ";" + << "}"; + + os << ret << " " << s << "::" << endl + << esname (e) << " ()" + << "{"; + + if (ret != L"void") + { + os << "return "; + type_pass_.dispatch (t); + os << "*this->" << access << iter << "++;"; + } + + os << "}"; + } + else + { + if (e.min () == 0) + { + os << "bool " << s << "::" << endl + << espresent (e) << " ()" + << "{" + << "return this->" << access << epresent (e) << " ();" + << "}"; + } + + os << ret << " " << s << "::" << endl + << esname (e) << " ()" + << "{"; + + if (ret != L"void") + { + os << "return "; + type_pass_.dispatch (t); + os << "this->" << access << ename (e) << " ();"; + } + + os << "}"; + } + } + + private: + TypePass type_pass_; + }; + + struct AttributeCallback: Traversal::Attribute, SerializerContext + { + AttributeCallback (Context& c) + : SerializerContext (c), type_pass_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& s ( + esimpl_custom ( + dynamic_cast (a.scope ()))); + + String access (access_seq (a)); + + if (a.optional ()) + { + os << "bool " << s << "::" << endl + << espresent (a) << " ()" + << "{" + << "return this->" << access << epresent (a) << " ();" + << "}"; + } + + SemanticGraph::Type& t (a.type ()); + String const& ret (sret_type (t)); + + os << ret << " " << s << "::" << endl + << esname (a) << " ()" + << "{"; + + if (ret != L"void") + { + os << "return "; + type_pass_.dispatch (t); + os << "this->" << access << ename (a) << " ();"; + } + + os << "}"; + } + + private: + TypePass type_pass_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + type_pass_ (c), + + // Initializers. + // + compositor_init_ (c), + particle_init_ (c), + + // Callbacks. + // + compositor_callback_ (c, contains_particle_init_), + particle_callback_ (c), + attribute_callback_ (c) + { + // Initializers. + // + contains_compositor_init_ >> compositor_init_; + compositor_init_ >> contains_particle_init_; + contains_particle_init_ >> compositor_init_; + contains_particle_init_ >> particle_init_; + + // Callbacks. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + String const& name (esimpl_custom (c)); + + if (!name) + return; + + Boolean hb (c.inherits_p ()); + Boolean restriction (restriction_p (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein && hb) + os << name << "::" << endl + << name << " ()" << endl + << ": " << esskel (c) << " (&base_impl_)" + << "{" + << "}"; + + // pre + // + String const& arg (sarg_type (c)); + + os << "void " << name << "::" << endl + << "pre (" << arg << " x)" + << "{"; + + if (hb) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + // Default serializer implementations for anyType and + // anySimpleType return void. + // + if (!b.is_a () && + !b.is_a ()) + { + + if (tiein) + os << "this->base_impl_.pre ("; + else + os << esimpl (b) << "::pre ("; + + type_pass_.dispatch (b); + + os << "x);"; + } + } + + if (!restriction) + { + os << "this->" << esstate (c) << "." << esstate_member (c) << + " = &x;"; + + contains_compositor (c, contains_compositor_init_); + } + + os << "}"; + + // Member callbacks. + // + if (!restriction) + { + names (c, names_attribute_callback_); + contains_compositor (c, contains_compositor_callback_); + } + } + + private: + TypePass type_pass_; + + // Initializers. + // + CompositorInit compositor_init_; + ParticleInit particle_init_; + Traversal::ContainsCompositor contains_compositor_init_; + Traversal::ContainsParticle contains_particle_init_; + + // Callbacks. + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_serializer_source (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/serializer-source.hxx b/xsde/cxx/hybrid/serializer-source.hxx new file mode 100644 index 0000000..dee3629 --- /dev/null +++ b/xsde/cxx/hybrid/serializer-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/serializer-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_SERIALIZER_SOURCE_HXX +#define CXX_HYBRID_SERIALIZER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_serializer_source (Context&); + } +} + +#endif // CXX_HYBRID_SERIALIZER_SOURCE_HXX diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx new file mode 100644 index 0000000..f1c0dfa --- /dev/null +++ b/xsde/cxx/hybrid/tree-forward.cxx @@ -0,0 +1,626 @@ +// file : xsd/cxx/hybrid/tree-forward.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + os << "class " << ename (l) << ";"; + } + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + os << "class " << ename (u) << ";"; + } + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + os << "class " << ename (c) << ";"; + } + }; + + struct FundType : Context, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + { + FundType (Context& c) + : Context (c) + { + if (stl) + string_type_ = L"::std::string"; + else + string_type_ = L"char*"; + + if (options.value ()) + { + long_type_ = L"long"; + unsigned_long_type_ = L"unsigned long"; + } + else + { + long_type_ = L"long long"; + unsigned_long_type_ = L"unsigned long long"; + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType&) + { + gen_using ("::xsde::cxx::hybrid::any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType&) + { + gen_using ("::xsde::cxx::hybrid::any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&) + { + gen_typedef ("boolean", "bool"); + gen_using ("::xsde::cxx::hybrid::boolean_base"); + os << endl; + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&) + { + gen_typedef ("byte", "signed char"); + gen_using ("::xsde::cxx::hybrid::byte_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + gen_typedef ("unsigned_byte", "unsigned char"); + gen_using ("::xsde::cxx::hybrid::unsigned_byte_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short&) + { + gen_typedef ("short", "short"); + gen_using ("::xsde::cxx::hybrid::short_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + gen_typedef ("unsigned_short", "unsigned short"); + gen_using ("::xsde::cxx::hybrid::unsigned_short_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int&) + { + gen_typedef ("int", "int"); + gen_using ("::xsde::cxx::hybrid::int_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + gen_typedef ("unsigned_int", "unsigned int"); + gen_using ("::xsde::cxx::hybrid::unsigned_int_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long&) + { + gen_typedef ("long", long_type_); + gen_using ("::xsde::cxx::hybrid::long_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + gen_typedef ("unsigned_long", unsigned_long_type_); + gen_using ("::xsde::cxx::hybrid::unsigned_long_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&) + { + gen_typedef ("integer", "long"); + gen_using ("::xsde::cxx::hybrid::integer_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + gen_typedef ("negative_integer", "long"); + gen_using ("::xsde::cxx::hybrid::negative_integer_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + gen_typedef ("non_positive_integer", "long"); + gen_using ("::xsde::cxx::hybrid::non_positive_integer_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + gen_typedef ("positive_integer", "unsigned long"); + gen_using ("::xsde::cxx::hybrid::positive_integer_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + gen_typedef ("non_negative_integer", "unsigned long"); + gen_using ("::xsde::cxx::hybrid::non_negative_integer_base"); + os << endl; + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&) + { + gen_typedef ("float", "float"); + gen_using ("::xsde::cxx::hybrid::float_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double&) + { + gen_typedef ("double", "double"); + gen_using ("::xsde::cxx::hybrid::double_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&) + { + gen_typedef ("decimal", "double"); + gen_using ("::xsde::cxx::hybrid::decimal_base"); + os << endl; + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + gen_typedef ("string", string_type_); + gen_using ("::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + gen_typedef ("normalized_string", string_type_); + + if (!stl) + gen_typedef ("normalized_string_base", + "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + gen_typedef ("token", string_type_); + if (!stl) + gen_typedef ("token_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + gen_typedef ("nmtoken", string_type_); + if (!stl) + gen_typedef ("nmtoken_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens&) + { + gen_typedef ("nmtokens", "::xsde::cxx::string_sequence"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + gen_typedef ("name", string_type_); + if (!stl) + gen_typedef ("name_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + gen_typedef ("ncname", string_type_); + if (!stl) + gen_typedef ("ncname_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + gen_typedef ("language", string_type_); + if (!stl) + gen_typedef ("language_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName&) + { + gen_using ("::xsde::cxx::qname"); + os << endl; + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&) + { + gen_typedef ("id", string_type_); + if (!stl) + gen_typedef ("id_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&) + { + gen_typedef ("idref", string_type_); + if (!stl) + gen_typedef ("idref_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs&) + { + gen_typedef ("idrefs", "::xsde::cxx::string_sequence"); + os << endl; + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&) + { + gen_typedef ("uri", string_type_); + if (!stl) + gen_typedef ("uri_base", "::xsde::cxx::hybrid::string_base"); + os << endl; + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary&) + { + gen_typedef ("base64_binary", "::xsde::cxx::buffer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary&) + { + gen_typedef ("hex_binary", "::xsde::cxx::buffer"); + os << endl; + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date&) + { + gen_using ("::xsde::cxx::date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime&) + { + gen_using ("::xsde::cxx::date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration&) + { + gen_using ("::xsde::cxx::duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day&) + { + gen_using ("::xsde::cxx::gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month&) + { + gen_using ("::xsde::cxx::gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay&) + { + gen_using ("::xsde::cxx::gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year&) + { + gen_using ("::xsde::cxx::gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth&) + { + gen_using ("::xsde::cxx::gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time&) + { + gen_using ("::xsde::cxx::time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&) + { + } + + private: + Void + gen_typedef (String const& name, String const& type) + { + os << "typedef " << type << " " << escape (name) << ";"; + } + + Void + gen_using (String const& name) + { + os << "using " << name << ";"; + } + + String string_type_; + String long_type_; + String unsigned_long_type_; + }; + + struct FundNamespace : Namespace, Context + { + FundNamespace (Context& c) + : Namespace (c), Context (c) + { + } + + void + traverse (Type& ns) + { + pre (ns); + names (ns); + + // strdupx + // + if (!stl) + { + os << endl + << "using ::xsde::cxx::strdupx;" + << "using ::xsde::cxx::strndupx;"; + } + + post (ns); + } + }; + } + + Void + generate_tree_forward (Context& ctx, Boolean generate_xml_schema) + { + NarrowString xml_schema (ctx.options.value ()); + + // Inlcude or Emit fundamental types. + // + if (!generate_xml_schema && xml_schema) + { + String name (ctx.hxx_expr->merge (xml_schema)); + + ctx.os << "#include " << ctx.process_include_path (name) << endl + << endl; + } + else + { + if (ctx.stl) + ctx.os << "#include " << endl; + else + ctx.os << "#include " << endl; + + ctx.os << "#include " << endl + << endl; + + if (generate_xml_schema) + { + Traversal::Schema schema; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + return; + } + else + { + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> implies >> xsd >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + } + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + //Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + //names >> enumeration; + + schema.dispatch (ctx.schema_root); + + ctx.os << endl; + } + } +} diff --git a/xsde/cxx/hybrid/tree-forward.hxx b/xsde/cxx/hybrid/tree-forward.hxx new file mode 100644 index 0000000..19dbf5d --- /dev/null +++ b/xsde/cxx/hybrid/tree-forward.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/tree-forward.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_FORWARD_HXX +#define CXX_HYBRID_TREE_FORWARD_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_tree_forward (Context&, Boolean generate_xml_schema); + } +} + +#endif // CXX_HYBRID_TREE_FORWARD_HXX diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx new file mode 100644 index 0000000..c7231c9 --- /dev/null +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -0,0 +1,2459 @@ +// file : xsd/cxx/hybrid/tree-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c), base_name_ (c, TypeName::seq) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + os << "// " << comment (l.name ()) << " (variable-length)" << endl + << "//" << endl; + + os << "class " << name << ": public "; + + base_name_.dispatch (l.argumented ().type ()); + + os << "{" + << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; + + // c-tor + // + os << "public:" << endl + << name << " ();"; + + // Custom data. + // + if (l.context ().count ("cd-name")) + { + String const& name (ecd_name (l)); + String const& sequence (ecd_sequence (l)); + String const& iterator (ecd_iterator (l)); + String const& const_iterator (ecd_const_iterator (l)); + + os << endl + << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + + os << "private:" << endl + << sequence << " " << ecd_member (l) << ";"; + } + + os << "};"; + } + + private: + TypeName base_name_; + }; + + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + SemanticGraph::Context& uc (u.context ()); + + String name (ename (u)); + Boolean cd (uc.count ("cd-name")); + + os << "// " << comment (u.name ()) << " (variable-length)" << endl + << "//" << endl; + + os << "class " << name + << "{"; + + if (!fixed_length (u)) + os << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; + + os << "public:" << endl; + + // c-tor + // + os << name << " ();"; + + String const& value (uc.get ("value")); + String const& member (uc.get ("value-member")); + + if (stl) + { + os << endl; + + // const std::string& + // name () const + // + os << "const ::std::string&" << endl + << value << " () const;" + << endl; + + // std::string& + // name () + // + os << "::std::string&" << endl + << value << " ();" + << endl; + + // void + // name (const std::string&) + // + os << "void" << endl + << value << " (const ::std::string&);" + << endl; + } + else + { + // d-tor + // + os << "~" << name << " ();" + << endl; + + // const char* + // name () const + // + os << "const char*" << endl + << value << " () const;" + << endl; + + // char* + // name () + // + os << "char*" << endl + << value << " ();" + << endl; + + // void + // name (char*) + // + os << "void" << endl + << value << " (char*);" + << endl; + } + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (u)); + String const& sequence (ecd_sequence (u)); + String const& iterator (ecd_iterator (u)); + String const& const_iterator (ecd_const_iterator (u)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + if (stl) + { + os << "private:" << endl + << "::std::string " << member << ";"; + } + else + { + os << "private:" << endl + << "char* " << member << ";"; + } + + // Custom data. + // + if (cd) + os << ecd_sequence (u) << " " << ecd_member (u) << ";"; + + os << "};"; + } + }; + + // + // Data. + // + + struct AlignType: Traversal::Compositor, + + Traversal::List, + Traversal::Union, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + + Context + { + AlignType (Context& c) + : Context (c), nested_ (false) + { + *this >> inherits_ >> *this; + + *this >> attribute_names_ >> attribute_; + + *this >> contains_particle_; + contains_particle_ >> particle_; + contains_particle_ >> *this; + contains_compositor_ >> *this; + + attribute_ >> belongs_; + particle_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + dispatch (SemanticGraph::Node& n) + { + found_ = false; + NodeBase::dispatch (n); + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + Boolean top (false); + + if (!nested_) + { + nested_ = true; + top = true; + } + + Traversal::Compositor::traverse (c); + + if (top) + { + nested_ = false; + + if (!found_) + os << "char"; // Empty compositor. + } + } + + virtual Void + traverse (SemanticGraph::List&) + { + align_type ("size_t"); + } + + virtual Void + traverse (SemanticGraph::Union&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + // Keep track of the nested calls for base types. + // + Boolean top (false); + + if (!nested_) + { + nested_ = true; + top = true; + } + + Complex::inherits (c, inherits_); + + if (!found_) + { + Complex::names (c, attribute_names_); + + if (!found_ && c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + + if (top) + { + nested_ = false; + + if (!found_) + os << "char"; // Empty class. + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType&) + { + align_type ("char"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType&) + { + align_type ("char"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&) + { + align_type ("bool"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&) + { + align_type ("signed char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + align_type ("unsigned char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short&) + { + align_type ("short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + align_type ("unsigned short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int&) + { + align_type ("int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + align_type ("unsigned int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long&) + { + align_type (options.value () + ? "long" + : "long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + align_type (options.value () + ? "unsigned long" + : "unsigned long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&) + { + align_type ("long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + align_type ("long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + align_type ("unsigned long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + align_type ("unsigned long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + align_type ("long"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&) + { + align_type ("float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double&) + { + align_type ("double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&) + { + align_type ("double"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language&) + { + align_type ("size_t"); // std::string + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName&) + { + align_type ("size_t"); // std::string + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&) + { + align_type ("size_t"); // std::string + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&) + { + align_type ("size_t"); // std::string + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&) + { + align_type ("size_t"); // std::string + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth&) + { + align_type ("bool"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time&) + { + align_type ("bool"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + align_type ("size_t"); // std::string + } + + private: + Void + align_type (Char const* t) + { + if (!found_) + { + os << t; + found_ = true; + } + } + + private: + Boolean found_; + Boolean nested_; + + private: + Traversal::Inherits inherits_; + + Traversal::Attribute attribute_; + Traversal::Names attribute_names_; + + Traversal::Element particle_; + Traversal::ContainsParticle contains_particle_; + Traversal::ContainsCompositor contains_compositor_; + + Traversal::Belongs belongs_; + }; + + struct AttributeData: Traversal::Attribute, Context + { + AttributeData (Context& c) + : Context (c), var_ (c, TypeName::var) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Type& t (a.type ()); + + var_.dispatch (t); + os << " " << emember (a) << ";"; + + if (a.optional () && fixed_length (t)) + os << "bool " << epresent_member (a) << ";"; + } + + private: + TypeName var_; + }; + + + struct ElementData: Traversal::Element, Context + { + ElementData (Context& c) + : Context (c), var_ (c, TypeName::var) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + { + os << esequence (e) << " " << emember (e) << ";"; + } + else + { + SemanticGraph::Type& t (e.type ()); + + var_.dispatch (t); + os << " " << emember (e) << ";"; + + if (e.min () == 0 && fixed_length (t)) + os << "bool " << epresent_member (e) << ";"; + } + } + + private: + TypeName var_; + }; + + struct ElementInChoiceData: Traversal::Element, Context + { + ElementInChoiceData (Context& c) + : Context (c), var_ (c, TypeName::var), align_type_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () != 1) + { + os << "union" + << "{" + << "size_t align_;" + << "char data_[sizeof (" << esequence (e) << ")];" + << "} " << emember (e) << ";"; + } + else + { + SemanticGraph::Type& t (e.type ()); + + if (fixed_length (t)) + { + os << "union" + << "{"; + + align_type_.dispatch (t); + + os << " align_;" + << "char data_[sizeof ("; + + var_.dispatch (t); + + os << ")"; + + // Reserve an extra byte for the present flag. + // + if (e.min () == 0) + os << " + 1"; + + os << "];" + << "} " << emember (e) << ";"; + } + else + { + var_.dispatch (t); + os << " " << emember (e) << ";"; + } + } + } + + private: + TypeName var_; + AlignType align_type_; + }; + + struct AllData: Traversal::All, Context + { + AllData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& member (emember(a)); + + if (fixed_length (a)) + { + os << type << " " << member << ";" + << "bool " << epresent_member (a) << ";"; + } + else + os << type << "* " << member << ";"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceData: Traversal::Choice, Context + { + ChoiceInSequenceData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () != 1) + { + os << esequence (c) << " " << emember (c) << ";"; + } + else if (c.min () == 0) + { + String const& type (etype (c)); + String const& member (emember (c)); + + if (fixed_length (c)) + os << type << " " << member << ";" + << "bool " << epresent_member (c) << ";"; + else + os << type << "* " << member << ";"; + } + else + { + os << "union" + << "{"; + + Choice::contains (c); + + os << "} " << emember (c) << ";" + << earm_tag (c) << " " << earm_member (c) << ";"; + } + } + }; + + struct ChoiceInChoiceData: Traversal::Choice, Context + { + ChoiceInChoiceData (Context& c) + : Context (c), align_type_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // For choice in choice we always have a nested class. + // + if (c.max () != 1) + { + os << "union" + << "{" + << "size_t align_;" + << "char data_[sizeof (" << esequence (c) << ")];" + << "} " << emember (c) << ";"; + } + else + { + if (fixed_length (c)) + { + os << "union" + << "{"; + + align_type_.dispatch (c); + + os << " align_;" + << "char data_[sizeof (" << etype (c) << ")"; + + // Reserve an extra byte for the present flag. + // + if (c.min () == 0) + os << " + 1"; + + os << "];" + << "} " << emember (c) << ";"; + } + else + os << etype (c) << "* " << emember (c) << ";"; + } + } + + private: + AlignType align_type_; + }; + + struct SequenceInSequenceData: Traversal::Sequence, Context + { + SequenceInSequenceData (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1) + { + os << esequence (s) << " " << emember (s) << ";"; + } + else if (s.min () == 0) + { + String const& type (etype (s)); + String const& member (emember (s)); + + if (fixed_length (s)) + os << type << " " << member << ";" + << "bool " << epresent_member (s) << ";"; + else + os << type << "* " << member << ";"; + } + else + Sequence::contains (s); + } + }; + + struct SequenceInChoiceData: Traversal::Sequence, Context + { + SequenceInChoiceData (Context& c) + : Context (c), align_type_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // For sequence in choice we always have a nested class. + // + if (s.max () != 1) + { + os << "union" + << "{" + << "size_t align_;" + << "char data_[sizeof (" << esequence (s) << ")];" + << "} " << emember (s) << ";"; + } + else + { + if (fixed_length (s)) + { + os << "union" + << "{"; + + align_type_.dispatch (s); + + os << " align_;" + << "char data_[sizeof (" << etype (s) << ")"; + + // Reserve an extra byte for the present flag. + // + if (s.min () == 0) + os << " + 1"; + + os << "];" + << "} " << emember (s) << ";"; + } + else + os << etype (s) << "* " << emember (s) << ";"; + } + } + + private: + AlignType align_type_; + }; + + // + // Accessors/modifiers. + // + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c), + ro_ret_ (c, TypeName::ro_ret), + ret_ (c, TypeName::ret), + arg_ (c, TypeName::arg) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + os << "// " << comment (a.name ()) << endl + << "// " << endl; + + String const& name (ename (a)); + SemanticGraph::Type& t (a.type ()); + + if (a.optional ()) + { + String const& present (epresent (a)); + + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + } + + // const type& + // name () const + // + ro_ret_.dispatch (t); + os << endl + << name << " () const;" + << endl; + + // type& + // name () + // + ret_.dispatch (t); + os << endl + << name << " ();" + << endl; + + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + arg_.dispatch (t); + os << ");" + << endl; + } + + private: + TypeName ro_ret_; + TypeName ret_; + TypeName arg_; + }; + + struct Element: Traversal::Element, virtual Context + { + Element (Context& c) + : Context (c), + seq_ (c, TypeName::seq), + ro_ret_ (c, TypeName::ro_ret), + ret_ (c, TypeName::ret), + arg_ (c, TypeName::arg) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "// " << comment (e.name ()) << endl + << "// " << endl; + + String const& name (ename (e)); + SemanticGraph::Type& t (e.type ()); + + if (e.max () != 1) + { + String const& sequence (esequence (e)); + String const& iterator (eiterator (e)); + String const& const_iterator (econst_iterator (e)); + + // sequence & iterators + // + os << "typedef "; + seq_.dispatch (t); + os << " " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + else + { + if (e.min () == 0) + { + // optional + // + String const& present (epresent (e)); + + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + } + + // const type& + // name () const + // + ro_ret_.dispatch (t); + os << endl + << name << " () const;" + << endl; + + // type& + // name () + // + ret_.dispatch (t); + os << endl + << name << " ();" + << endl; + + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + arg_.dispatch (t); + os << ");" + << endl; + } + } + + private: + TypeName seq_; + TypeName ro_ret_; + TypeName ret_; + TypeName arg_; + }; + + struct All: Traversal::All, Context + { + All (Context& c, Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + Boolean fl (fixed_length (a)); + Boolean cd (a.context ().count ("cd-name")); + + String const& name (ename (a)); + String const& type (etype (a)); + String const& present (epresent (a)); + + os << "// " << comment (name) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "// " << endl; + + os << "class " << type + << "{"; + + // c-tor & d-tor + // + os << "public:" << endl + << type << " ();" + << "~" << type << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + os << type << " (const " << type << "&);" + << type << "& operator= (const " << type << "&);" + << endl; + + if (!fl) + os << "public:" << endl; + + All::contains (a); + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (a)); + String const& sequence (ecd_sequence (a)); + String const& iterator (ecd_iterator (a)); + String const& const_iterator (ecd_const_iterator (a)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + os << "private:" << endl; + + All::contains (a, contains_data_); + + // Custom data. + // + if (cd) + os << ecd_sequence (a) << " " << ecd_member (a) << ";"; + + os << "};"; + + // name_present + // + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + + // const type& + // name () const + // + os << "const " << type << "&" << endl + << name << " () const;" + << endl; + + // type& + // name () + // + os << type << "&" << endl + << name << " ();" + << endl; + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << ");" + << endl; + } + else + All::contains (a); + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct ParticleTag: Traversal::Element, + Traversal::Any, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleTag (Context& c) + : Context (c), first_ (true) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + emit_tag (etag (e)); + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + emit_tag (etag (a)); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + emit_tag (etag (c)); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + emit_tag (etag (s)); + } + + virtual Void + emit_tag (String const& tag) + { + if (first_) + first_ = false; + else + os << "," << endl; + + os << tag; + } + + private: + Boolean first_; + }; + + struct ChoiceInSequence: Traversal::Choice, Context + { + ChoiceInSequence (Context& c, + Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + UnsignedLong min (c.min ()), max (c.max ()); + + String const& name (ename (c)); + + Boolean fl; + String type; + + if (max != 1 || min == 0) + { + type = etype (c); + + fl = fixed_length (c); + + os << "// " << comment (name) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "// " << endl; + + os << "class " << type + << "{"; + + // c-tor & d-tor + // + os << "public:" << endl + << type << " ();" + << "~" << type << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + os << type << " (const " << type << "&);" + << type << "& operator= (const " << type << "&);" + << endl; + + if (!fl) + os << "public:" << endl; + } + else + { + os << "// " << comment (name) << endl + << "// " << endl; + } + + String const& arm_tag (earm_tag (c)); + String const& arm (earm (c)); + + os << "enum " << arm_tag + << "{"; + + { + ParticleTag particle (*this); + Traversal::ContainsParticle contains_particle (particle); + Traversal::Choice::contains (c, contains_particle); + } + + os << "};"; + + // arm_tag + // arm () const; + // + os << arm_tag << endl + << arm << " () const;" + << endl; + + // void + // arm (arm_tag); + // + os << "void" << endl + << arm << " (" << arm_tag << ");" + << endl; + + Choice::contains (c); + + if (max != 1 || min == 0) + { + Boolean cd (c.context ().count ("cd-name")); + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (c)); + String const& sequence (ecd_sequence (c)); + String const& iterator (ecd_iterator (c)); + String const& const_iterator (ecd_const_iterator (c)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + os << "private:" << endl + << "union" + << "{"; + + Choice::contains (c, contains_data_); + + os << "} " << emember (c) << ";" + << arm_tag << " " << earm_member (c) << ";"; + + // Custom data. + // + if (cd) + os << ecd_sequence (c) << " " << ecd_member (c) << ";"; + + os << "};"; + } + + if (max != 1) + { + String const& sequence (esequence (c)); + String const& iterator (eiterator (c)); + String const& const_iterator (econst_iterator (c)); + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::"; + + if (fl) + os << "fix_seq"; + else + os << "var_seq"; + + os << "< " << type << " > " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + + } + else if (min == 0) + { + String const& present (epresent (c)); + + // name_present + // + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + + // const type& + // name () const + // + os << "const " << type << "&" << endl + << name << " () const;" + << endl; + + // type& + // name () + // + os << type << "&" << endl + << name << " ();" + << endl; + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << ");" + << endl; + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct ChoiceInChoice: Traversal::Choice, Context + { + ChoiceInChoice (Context& c, + Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When shoice is in choice we generate nested class even + // for min == max == 1. + // + UnsignedLong min (c.min ()), max (c.max ()); + + Boolean fl (fixed_length (c)); + Boolean cd (c.context ().count ("cd-name")); + + String const& name (ename (c)); + String const& type (etype (c)); + + os << "// " << comment (name) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "// " << endl; + + os << "class " << type + << "{"; + + // c-tor & d-tor + // + os << "public:" << endl + << type << " ();" + << "~" << type << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + os << type << " (const " << type << "&);" + << type << "& operator= (const " << type << "&);" + << endl; + + if (!fl) + os << "public:" << endl; + + String const& arm_tag (earm_tag (c)); + String const& arm (earm (c)); + + os << "enum " << arm_tag + << "{"; + + { + ParticleTag particle (*this); + Traversal::ContainsParticle contains_particle (particle); + Traversal::Choice::contains (c, contains_particle); + } + + os << "};"; + + // arm_tag + // arm () const; + // + os << arm_tag << endl + << arm << " () const;" + << endl; + + // void + // arm (arm_tag); + // + os << "void" << endl + << arm << " (" << arm_tag << ");" + << endl; + + Choice::contains (c); + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (c)); + String const& sequence (ecd_sequence (c)); + String const& iterator (ecd_iterator (c)); + String const& const_iterator (ecd_const_iterator (c)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + os << "private:" << endl + << "union" + << "{"; + + Choice::contains (c, contains_data_); + + os << "} " << emember (c) << ";" + << arm_tag << " " << earm_member (c) << ";"; + + // Custom data. + // + if (cd) + os << ecd_sequence (c) << " " << ecd_member (c) << ";"; + + os << "};"; + + if (max != 1) + { + String const& sequence (esequence (c)); + String const& iterator (eiterator (c)); + String const& const_iterator (econst_iterator (c)); + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::"; + + if (fl) + os << "fix_seq"; + else + os << "var_seq"; + + os << "< " << type << " > " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + else + { + if (min == 0) + { + String const& present (epresent (c)); + + // name_present + // + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + } + + // const type& + // name () const + // + os << "const " << type << "&" << endl + << name << " () const;" + << endl; + + // type& + // name () + // + os << type << "&" << endl + << name << " ();" + << endl; + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << ");" + << endl; + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + + struct SequenceInSequence: Traversal::Sequence, Context + { + SequenceInSequence (Context& c, + Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (max == 1 && min == 1) + { + Sequence::contains (s); + return; + } + + Boolean fl (fixed_length (s)); + Boolean cd (s.context ().count ("cd-name")); + + String const& name (ename (s)); + String const& type (etype (s)); + + os << "// " << comment (name) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "// " << endl; + + os << "class " << type + << "{"; + + // c-tor & d-tor + // + os << "public:" << endl + << type << " ();" + << "~" << type << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + os << type << " (const " << type << "&);" + << type << "& operator= (const " << type << "&);" + << endl; + + if (!fl) + os << "public:" << endl; + + Sequence::contains (s); + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (s)); + String const& sequence (ecd_sequence (s)); + String const& iterator (ecd_iterator (s)); + String const& const_iterator (ecd_const_iterator (s)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + os << "private:" << endl; + + Sequence::contains (s, contains_data_); + + // Custom data. + // + if (cd) + os << ecd_sequence (s) << " " << ecd_member (s) << ";"; + + os << "};"; + + if (max != 1) + { + String const& sequence (esequence (s)); + String const& iterator (eiterator (s)); + String const& const_iterator (econst_iterator (s)); + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::"; + + if (fl) + os << "fix_seq"; + else + os << "var_seq"; + + os << "< " << type << " > " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + + } + else if (min == 0) + { + String const& present (epresent (s)); + + // name_present + // + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + + // const type& + // name () const + // + os << "const " << type << "&" << endl + << name << " () const;" + << endl; + + // type& + // name () + // + os << type << "&" << endl + << name << " ();" + << endl; + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << ");" + << endl; + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct SequenceInChoice: Traversal::Sequence, Context + { + SequenceInChoice (Context& c, + Traversal::ContainsParticle& contains_data) + : Context (c), contains_data_ (contains_data) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + Boolean fl (fixed_length (s)); + Boolean cd (s.context ().count ("cd-name")); + + String const& name (ename (s)); + String const& type (etype (s)); + + os << "// " << comment (name) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "// " << endl; + + os << "class " << type + << "{"; + + // c-tor & d-tor + // + os << "public:" << endl + << type << " ();" + << "~" << type << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + os << type << " (const " << type << "&);" + << type << "& operator= (const " << type << "&);" + << endl; + + if (!fl) + os << "public:" << endl; + + Sequence::contains (s); + + if (cd) + { + String const& name (ecd_name (s)); + String const& sequence (ecd_sequence (s)); + String const& iterator (ecd_iterator (s)); + String const& const_iterator (ecd_const_iterator (s)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + os << "private:" << endl; + + Sequence::contains (s, contains_data_); + + // Custom data. + // + if (cd) + os << ecd_sequence (s) << " " << ecd_member (s) << ";"; + + os << "};"; + + if (s.max () != 1) + { + String const& sequence (esequence (s)); + String const& iterator (eiterator (s)); + String const& const_iterator (econst_iterator (s)); + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::"; + + if (fl) + os << "fix_seq"; + else + os << "var_seq"; + + os << "< " << type << " > " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + + } + else + { + if (s.min () == 0) + { + String const& present (epresent (s)); + + // name_present + // + os << "bool" << endl + << present << " () const;" + << endl; + + os << "void" << endl + << present << " (bool);" + << endl; + } + + // const type& + // name () const + // + os << "const " << type << "&" << endl + << name << " () const;" + << endl; + + // type& + // name () + // + os << type << "&" << endl + << name << " ();" + << endl; + + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << ");" + << endl; + } + } + + private: + Traversal::ContainsParticle& contains_data_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + base_name_ (c, TypeName::base), + + // Data. + // + attribute_data_ (c), + element_data_ (c), + element_in_choice_data_ (c), + all_data_ (c), + choice_in_choice_data_ (c), + choice_in_sequence_data_ (c), + sequence_in_choice_data_ (c), + sequence_in_sequence_data_ (c), + + // Functions and nested classes. + // + attribute_ (c), + element_ (c), + all_ (c, all_contains_data_), + choice_in_choice_ (c, choice_contains_data_), + choice_in_sequence_ (c, choice_contains_data_), + sequence_in_choice_ (c, sequence_contains_data_), + sequence_in_sequence_ (c, sequence_contains_data_) + { + // Data + // + attribute_names_data_ >> attribute_data_; + + all_data_ >> all_contains_data_ >> element_data_; + + sequence_in_choice_data_ >> sequence_contains_data_; + sequence_in_sequence_data_ >> sequence_contains_data_; + sequence_contains_data_ >> element_data_; + sequence_contains_data_ >> choice_in_sequence_data_; + sequence_contains_data_ >> sequence_in_sequence_data_; + + choice_in_choice_data_ >> choice_contains_data_; + choice_in_sequence_data_ >> choice_contains_data_; + choice_contains_data_ >> element_in_choice_data_; + choice_contains_data_ >> choice_in_choice_data_; + choice_contains_data_ >> sequence_in_choice_data_; + + contains_compositor_data_ >> all_data_; + contains_compositor_data_ >> choice_in_sequence_data_; + contains_compositor_data_ >> sequence_in_sequence_data_; + + // Functions and nested classes. + // + attribute_names_ >> attribute_; + + all_ >> all_contains_ >> element_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> element_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> element_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + Boolean fl (fixed_length (c)); + Boolean restriction (restriction_p (c)); + Boolean cd (c.context ().count ("cd-name")); + + os << "// " << comment (c.name ()) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "//" << endl; + + os << "class " << name; + + if (c.inherits_p ()) + { + os << ": public "; + base_name_.dispatch (c.inherits ().base ()); + } + + os << "{"; + + // c-tor + // + os << "public:" << endl + << name << " ();"; + + // d-tor + // + if (!restriction) + os << "~" << name << " ();"; + + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; + + if (!fl || !restriction) + os << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; + + if ((!restriction && !fl) || cd) + os << "public:" << endl; + + if (!restriction) + { + Complex::names (c, attribute_names_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + + // Custom data. + // + if (cd) + { + String const& name (ecd_name (c)); + String const& sequence (ecd_sequence (c)); + String const& iterator (ecd_iterator (c)); + String const& const_iterator (ecd_const_iterator (c)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + if (!restriction || cd) + os << "private:" << endl; + + if (!restriction) + { + Complex::names (c, attribute_names_data_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_data_); + } + + // Custom data. + // + if (cd) + os << ecd_sequence (c) << " " << ecd_member (c) << ";"; + + os << "};"; + } + + private: + TypeName base_name_; + + // Data. + // + AttributeData attribute_data_; + Traversal::Names attribute_names_data_; + + ElementData element_data_; + ElementInChoiceData element_in_choice_data_; + AllData all_data_; + ChoiceInChoiceData choice_in_choice_data_; + ChoiceInSequenceData choice_in_sequence_data_; + SequenceInChoiceData sequence_in_choice_data_; + SequenceInSequenceData sequence_in_sequence_data_; + Traversal::ContainsParticle all_contains_data_; + Traversal::ContainsParticle choice_contains_data_; + Traversal::ContainsParticle sequence_contains_data_; + + Traversal::ContainsCompositor contains_compositor_data_; + + // Functions and nested classes. + // + Attribute attribute_; + Traversal::Names attribute_names_; + + Element element_; + All all_; + ChoiceInChoice choice_in_choice_; + ChoiceInSequence choice_in_sequence_; + SequenceInChoice sequence_in_choice_; + SequenceInSequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_tree_header (Context& ctx) + { + ctx.os << "#include " << endl + << endl; + + Boolean inline_ (ctx.options.value ()); + + // Emit header includes. + // + { + if (inline_) + { + ctx.os << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl + << "#define XSDE_DONT_INCLUDE_INLINE" << endl + << endl; + } + + Traversal::Schema schema; + Includes includes (ctx, Includes::header); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + + if (inline_) + { + ctx.os << "#undef XSDE_DONT_INCLUDE_INLINE" << endl + << "#else" << endl + << endl; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + //Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + //names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + + // Emit inline includes. + // + if (inline_) + { + ctx.os << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl + << endl; + + Traversal::Schema schema; + Includes ixx_includes (ctx, Includes::inline_); + schema >> ixx_includes; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + } +} diff --git a/xsde/cxx/hybrid/tree-header.hxx b/xsde/cxx/hybrid/tree-header.hxx new file mode 100644 index 0000000..2ef9573 --- /dev/null +++ b/xsde/cxx/hybrid/tree-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/tree-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_HEADER_HXX +#define CXX_HYBRID_TREE_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_tree_header (Context&); + } +} + +#endif // CXX_HYBRID_TREE_HEADER_HXX diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx new file mode 100644 index 0000000..72d2d8f --- /dev/null +++ b/xsde/cxx/hybrid/tree-inline.cxx @@ -0,0 +1,1817 @@ +// file : xsd/cxx/hybrid/tree-inline.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct List : Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + os << "// " << comment (l.name ()) << endl + << "//" << endl + << endl; + + // c-tor + // + os << inl + << name << "::" << endl + << name << " ()" + << "{" + << "}"; + + // Custom data. + // + if (l.context ().count ("cd-name")) + { + String const& cd_name (ecd_name (l)); + String const& member (ecd_member (l)); + String const& sequence (ecd_sequence (l)); + + // const seq& + // name () const + // + os << inl + << "const " << name << "::" << sequence << "& " << + name << "::" << endl + << cd_name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << name << "::" << sequence << "& " << name << "::" << endl + << cd_name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + }; + + // + // + struct Union : Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + os << "// " << comment (u.name ()) << endl + << "//" << endl + << endl; + + SemanticGraph::Context& uc (u.context ()); + String const& value (uc.get ("value")); + String const& member (uc.get ("value-member")); + + // c-tor + // + os << inl + << name << "::" << endl + << name << " ()" + << "{"; + + if (!stl) + os << "this->" << member << " = 0;"; + + os << "}"; + + if (stl) + { + // const std::string& + // name () const + // + os << inl + << "const ::std::string& " << name << "::" << endl + << value << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // std::string& + // name () + // + os << inl + << "::std::string& " << name << "::" << endl + << value << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (const std::string&) + // + os << inl + << "void " << name << "::" << endl + << value << " (const ::std::string& x)" + << "{" + << "this->" << member << " = x;" + << "}"; + } + else + { + // d-tor + // + os << inl + << name << "::" << endl + << "~" << name << " ()" + << "{" + << "delete[] this->" << member << ";" + << "}"; + + // const char* + // name () const + // + os << inl + << "const char* " << name << "::" << endl + << value << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // char* + // name () + // + os << inl + << "char* " << name << "::" << endl + << value << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (char*) + // + os << inl + << "void " << name << "::" << endl + << value << " (char* x)" + << "{" + << "delete[] this->" << member << ";" + << "this->" << member << " = x;" + << "}"; + } + + // Custom data. + // + if (uc.count ("cd-name")) + { + String const& cd_name (ecd_name (u)); + String const& member (ecd_member (u)); + String const& sequence (ecd_sequence (u)); + + // const seq& + // name () const + // + os << inl + << "const " << name << "::" << sequence << "& " << + name << "::" << endl + << cd_name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << name << "::" << sequence << "& " << name << "::" << endl + << cd_name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + }; + + // + // + struct AttributeFunc: Traversal::Attribute, Context + { + AttributeFunc (Context& c) + : Context (c), + ro_ret_ (c, TypeName::ro_ret), + ret_ (c, TypeName::ret), + arg_ (c, TypeName::arg), + deref_ (c, TypeOps::deref), + delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + String const& member (emember (a)); + + SemanticGraph::Type& t (a.type ()); + Boolean fl (fixed_length (t)); + String scope (Context::scope (a)); + + if (a.optional ()) + { + String const& present (epresent (a)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + os << "return this->" << epresent_member (a) << ";"; + else + os << "return this->" << member << " != 0;"; + + os << "}"; + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{"; + + if (fl) + os << "this->" << epresent_member (a) << " = x;"; + else + { + os << "if (!x)" + << "{"; + delete_.dispatch (t); + os << " this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + + os << "}"; + } + + // const type& + // name () const + // + os << inl; + ro_ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " () const" + << "{" + << "return "; + deref_.dispatch (t); + os << "this->" << member << ";" + << "}"; + + // type& + // name () + // + os << inl; + ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " ()" + << "{" + << "return "; + deref_.dispatch (t); + os << "this->" << member << ";" + << "}"; + + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + arg_.dispatch (t); + os << " x)" + << "{"; + + if (!fl) + { + delete_.dispatch (t); + os << " this->" << member << ";"; + } + + os << "this->" << member << " = x;"; + + if (fl && a.optional ()) + os << "this->" << epresent_member (a) << " = true;"; + + os << "}"; + } + + private: + TypeName ro_ret_; + TypeName ret_; + TypeName arg_; + TypeOps deref_; + TypeOps delete_; + }; + + struct ElementFunc: Traversal::Element, Context + { + ElementFunc (Context& c) + : Context (c), + ro_ret_ (c, TypeName::ro_ret), + ret_ (c, TypeName::ret), + arg_ (c, TypeName::arg), + deref_ (c, TypeOps::deref), + delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& name (ename (e)); + String const& member (emember (e)); + + SemanticGraph::Type& t (e.type ()); + Boolean fl (fixed_length (t)); + String scope (Context::scope (e)); + + if (e.max () != 1) + { + String const& sequence (esequence (e)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + else + { + if (e.min () == 0) + { + String const& present (epresent (e)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + os << "return this->" << epresent_member (e) << ";"; + else + os << "return this->" << member << " != 0;"; + + os << "}"; + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{"; + + if (fl) + os << "this->" << epresent_member (e) << " = x;"; + else + { + os << "if (!x)" + << "{"; + delete_.dispatch (t); + os << " this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + + os << "}"; + } + + // const type& + // name () const + // + os << inl; + ro_ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " () const" + << "{" + << "return "; + deref_.dispatch (t); + os << "this->" << member << ";" + << "}"; + + // type& + // name () + // + os << inl; + ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " ()" + << "{" + << "return "; + deref_.dispatch (t); + os << "this->" << member << ";" + << "}"; + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + arg_.dispatch (t); + os << " x)" + << "{"; + + if (!fl) + { + delete_.dispatch (t); + os << " this->" << member << ";"; + } + + os << "this->" << member << " = x;"; + + if (fl && e.min () == 0) + os << "this->" << epresent_member (e) << " = true;"; + + os << "}"; + } + } + + private: + TypeName ro_ret_; + TypeName ret_; + TypeName arg_; + TypeOps deref_; + TypeOps delete_; + }; + + struct ElementInChoiceFunc: Traversal::Element, Context + { + ElementInChoiceFunc (Context& c) + : Context (c), + ro_ret_ (c, TypeName::ro_ret), + ret_ (c, TypeName::ret), + arg_ (c, TypeName::arg), + var_ (c, TypeName::var), + deref_ (c, TypeOps::deref), + delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& name (ename (e)); + String const& member (emember (e)); + + SemanticGraph::Choice& c ( + dynamic_cast ( + e.contained_particle ().compositor ())); + + String const& arm (earm (c)); + String const& umember (emember (c)); + + String scope (Context::scope (e)); + + if (e.max () != 1) + { + String const& sequence (esequence (e)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return reinterpret_cast< const " << sequence << "& > (" << + "this->" << umember << "." << member << ");" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return reinterpret_cast< " << sequence << "& > (" << + "this->" << umember << "." << member << ");" + << "}"; + } + else + { + UnsignedLong min (e.min ()); + + SemanticGraph::Type& t (e.type ()); + Boolean fl (fixed_length (t)); + + String const& tag (etag (e)); + String const& arm_member (earm_member (c)); + + if (min == 0) + { + String const& present (epresent (e)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + { + os << "return this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")];"; + } + else + os << "return this->" << umember << "." << member << " != 0;"; + + os << "}"; + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{" + << "if (this->" << arm_member << " != " << tag << ")" << endl + << "this->" << arm << " (" << tag << ");"; + + if (fl) + { + os << endl + << "this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")] = x;"; + } + else + { + os << "else if (!x)" + << "{"; + delete_.dispatch (t); + os << " this->" << umember << "." << member << ";" + << "this->" << umember << "." << member << " = 0;" + << "}"; + } + + os << "}"; + } + + // const type& + // name () const + // + os << inl; + ro_ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " () const" + << "{" + << "return "; + + if (fl) + { + os << "reinterpret_cast< const "; + var_.dispatch (t); + os << "& > (this->" << umember << "." << member << ");"; + } + else + { + deref_.dispatch (t); + os << "this->" << umember << "." << member << ";"; + } + + os << "}"; + + // type& + // name () + // + os << inl; + ret_.dispatch (t); + os << " " << scope << "::" << endl + << name << " ()" + << "{" + << "return "; + + if (fl) + { + os << "reinterpret_cast< "; + var_.dispatch (t); + os << "& > (this->" << umember << "." << member << ");"; + } + else + { + deref_.dispatch (t); + os << "this->" << umember << "." << member << ";"; + } + + os << "}"; + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + arg_.dispatch (t); + os << " x)" + << "{" + << "if (this->" << arm_member << " != " << tag << ")" << endl + << "this->" << arm << " (" << tag << ");"; + + if (fl) + { + os << endl + << "reinterpret_cast< "; + var_.dispatch (t); + os << "& > (this->" << umember << "." << member << ") = x;"; + + if (min == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")] = true;"; + } + } + else + { + os << "else" << endl; + delete_.dispatch (t); + os << " this->" << umember << "." << member << ";" + << endl + << "this->" << umember << "." << member << " = x;"; + } + + os << "}"; + } + } + + private: + TypeName ro_ret_; + TypeName ret_; + TypeName arg_; + TypeName var_; + TypeOps deref_; + TypeOps delete_; + }; + + struct AllFunc: Traversal::All, Context + { + AllFunc (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& name (ename (a)); + String const& type (etype (a)); + String const& present (epresent (a)); + String const& member (emember (a)); + + Boolean fl (fixed_length (a)); + String scope (Context::scope (a)); + + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + os << "return this->" << epresent_member (a) << ";"; + else + os << "return this->" << member << " != 0;"; + + os << "}"; + + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{"; + + if (fl) + os << "this->" << epresent_member (a) << " = x;"; + else + { + os << "if (!x)" + << "{" + << "delete this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + + os << "}"; + + + // const type& + // name () const + // + os << inl + << "const " << scope << "::" << type << "& " << + scope << "::" << endl + << name << " () const" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // type& + // name () + // + os << inl + << scope << "::" << type << "& " << scope << "::" << endl + << name << " ()" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << " x)" + << "{"; + + if (!fl) + os << "delete this->" << member << ";"; + + os << "this->" << member << " = x;"; + + if (fl) + os << "this->" << epresent_member (a) << " = true;"; + + os << "}"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceFunc: Traversal::Choice, Context + { + ChoiceInSequenceFunc (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (max == 1 && min == 1) + { + String scope (Context::scope (c)); + + // void + // arm (arm_tag) + // + os << inl + << scope << "::" << earm_tag (c) << " " << scope << "::" << endl + << earm (c) << " () const" + << "{" + << "return this->" << earm_member (c) << ";" + << "}"; + + Choice::contains (c); + return; + } + + String const& name (ename (c)); + String const& member (emember (c)); + String scope (Context::scope (c)); + + if (max != 1) + { + String const& sequence (esequence (c)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + else if (min == 0) + { + Boolean fl (fixed_length (c)); + + String const& type (etype (c)); + String const& present (epresent (c)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + os << "return this->" << epresent_member (c) << ";"; + else + os << "return this->" << member << " != 0;"; + + os << "}"; + + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{"; + + if (fl) + os << "this->" << epresent_member (c) << " = x;"; + else + { + os << "if (!x)" + << "{" + << "delete this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + + os << "}"; + + + // const type& + // name () const + // + os << inl + << "const " << scope << "::" << type << "& " << + scope << "::" << endl + << name << " () const" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // type& + // name () + // + os << inl + << scope << "::" << type << "& " << scope << "::" << endl + << name << " ()" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << " x)" + << "{"; + + if (!fl) + os << "delete this->" << member << ";"; + + os << "this->" << member << " = x;"; + + if (fl) + os << "this->" << epresent_member (c) << " = true;"; + + os << "}"; + } + } + }; + + struct SequenceInSequenceFunc: Traversal::Sequence, Context + { + SequenceInSequenceFunc (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (max == 1 && min == 1) + { + Sequence::contains (s); + return; + } + + String const& name (ename (s)); + String const& member (emember (s)); + String scope (Context::scope (s)); + + if (max != 1) + { + String const& sequence (esequence (s)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + else if (min == 0) + { + Boolean fl (fixed_length (s)); + + String const& type (etype (s)); + String const& present (epresent (s)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + os << "return this->" << epresent_member (s) << ";"; + else + os << "return this->" << member << " != 0;"; + + os << "}"; + + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{"; + + if (fl) + os << "this->" << epresent_member (s) << " = x;"; + else + { + os << "if (!x)" + << "{" + << "delete this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + + os << "}"; + + + // const type& + // name () const + // + os << inl + << "const " << scope << "::" << type << "& " << + scope << "::" << endl + << name << " () const" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // type& + // name () + // + os << inl + << scope << "::" << type << "& " << scope << "::" << endl + << name << " ()" + << "{"; + + if (fl) + os << "return this->" << member << ";"; + else + os << "return *this->" << member << ";"; + + os << "}"; + + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << " x)" + << "{"; + + if (!fl) + os << "delete this->" << member << ";"; + + os << "this->" << member << " = x;"; + + if (fl) + os << "this->" << epresent_member (s) << " = true;"; + + os << "}"; + } + } + }; + + struct CompositorInChoiceFunc: Context + { + CompositorInChoiceFunc (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + // When compositor is in choice we generate nested class even + // for min == max == 1. + // + String const& name (ename (c)); + String const& member (emember (c)); + + SemanticGraph::Choice& cont ( + dynamic_cast ( + c.contained_particle ().compositor ())); + + String const& arm (earm (cont)); + String const& umember (emember (cont)); + + String scope (Context::scope (c)); + + if (c.max () != 1) + { + String const& sequence (esequence (c)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return reinterpret_cast< const " << sequence << "& > (" << + "this->" << umember << "." << member << ");" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return reinterpret_cast< " << sequence << "& > (" << + "this->" << umember << "." << member << ");" + << "}"; + } + else + { + UnsignedLong min (c.min ()); + + Boolean fl (fixed_length (c)); + + String const& type (etype (c)); + String const& tag (etag (c)); + String const& arm_member (earm_member (cont)); + + if (min == 0) + { + String const& present (epresent (c)); + + // bool + // preset () const; + // + os << inl + << "bool " << scope << "::" << endl + << present << " () const" + << "{"; + + if (fl) + { + os << "return this->" << umember << "." << member << + ".data_[sizeof (" << type << ")];"; + } + else + os << "return this->" << umember << "." << member << " != 0;"; + + os << "}"; + + // void + // preset (bool); + // + os << inl + << "void " << scope << "::" << endl + << present << " (bool x)" + << "{" + << "if (this->" << arm_member << " != " << tag << ")" << endl + << "this->" << arm << " (" << tag << ");"; + + if (fl) + { + os << endl + << "this->" << umember << "." << member << + ".data_[sizeof (" << type << ")] = x;"; + } + else + { + os << "else if (!x)" + << "{" + << "delete this->" << umember << "." << member << ";" + << "this->" << umember << "." << member << " = 0;" + << "}"; + } + + os << "}"; + } + + // const type& + // name () const + // + os << inl + << "const " << scope << "::" << type << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return "; + + if (fl) + os << "reinterpret_cast< const " << type << "& > (this->" << + umember << "." << member << ");"; + else + os << "*this->" << umember << "." << member << ";"; + + os << "}"; + + // type& + // name () + // + os << inl + << scope << "::" << type << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return "; + + if (fl) + os << "reinterpret_cast< " << type << "& > (this->" << + umember << "." << member << ");"; + else + os << "*this->" << umember << "." << member << ";"; + + os << "}"; + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; + + if (fl) + os << "const " << type << "&"; + else + os << type << "*"; + + os << " x)" + << "{" + << "if (this->" << arm_member << " != " << tag << ")" << endl + << "this->" << arm << " (" << tag << ");"; + + if (fl) + { + os << endl + << "reinterpret_cast< " << type << "& > (this->" << + umember << "." << member << ") = x;"; + + if (min == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof (" << type << ")] = true;"; + } + } + else + { + os << "else" << endl + << "delete this->" << umember << "." << member << ";" + << endl + << "this->" << umember << "." << member << " = x;"; + } + + os << "}"; + } + } + }; + + struct ChoiceInChoiceFunc: Traversal::Choice, CompositorInChoiceFunc + { + ChoiceInChoiceFunc (Context& c) + : CompositorInChoiceFunc (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + CompositorInChoiceFunc::traverse (c); + } + }; + + struct SequenceInChoiceFunc: Traversal::Sequence, CompositorInChoiceFunc + { + SequenceInChoiceFunc (Context& c) + : CompositorInChoiceFunc (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + CompositorInChoiceFunc::traverse (s); + } + }; + + // + // + // + + struct All: Traversal::All, Context + { + All (Context& c, Traversal::ContainsParticle& contains_func) + : Context (c), contains_func_ (contains_func) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + All::contains (a, contains_func_); + + // Custom data. + // + if (a.context ().count ("cd-name")) + { + String const& scope (Context::scope (a)); + String const& type (etype (a)); + + String const& name (ecd_name (a)); + String const& member (ecd_member (a)); + String const& sequence (ecd_sequence (a)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << type << "::" << + sequence << "& " << scope << "::" << type << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << type << "::" << sequence << "& " << + scope << "::" << type << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + } + + private: + Traversal::ContainsParticle& contains_func_; + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, + Boolean in_choice, + Traversal::ContainsParticle& contains_func) + : Context (c), + in_choice_ (in_choice), + contains_func_ (contains_func) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String scope (Context::scope (c)); + String const& type (etype (c)); + + // void + // arm (arm_tag) + // + os << inl + << scope << "::" << type << "::" << earm_tag (c) << " " << + scope << "::" << type << "::" << endl + << earm (c) << " () const" + << "{" + << "return this->" << earm_member (c) << ";" + << "}"; + + Choice::contains (c, contains_func_); + + // Custom data. + // + if (c.context ().count ("cd-name")) + { + String const& name (ecd_name (c)); + String const& member (ecd_member (c)); + String const& sequence (ecd_sequence (c)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << type << "::" << + sequence << "& " << scope << "::" << type << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << type << "::" << sequence << "& " << + scope << "::" << type << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + Traversal::ContainsParticle& contains_func_; + }; + + + struct SequenceInSequence: Traversal::Sequence, Context + { + SequenceInSequence (Context& c, + Traversal::ContainsParticle& contains_func) + : Context (c), contains_func_ (contains_func) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () != 1 || s.min () == 0) + { + Sequence::contains (s, contains_func_); + + // Custom data. + // + if (s.context ().count ("cd-name")) + { + String const& scope (Context::scope (s)); + String const& type (etype (s)); + + String const& name (ecd_name (s)); + String const& member (ecd_member (s)); + String const& sequence (ecd_sequence (s)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << type << "::" << + sequence << "& " << scope << "::" << type << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << type << "::" << sequence << "& " << + scope << "::" << type << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + + Sequence::contains (s); + } + + private: + Traversal::ContainsParticle& contains_func_; + }; + + struct SequenceInChoice: Traversal::Sequence, Context + { + SequenceInChoice (Context& c, + Traversal::ContainsParticle& contains_func) + : Context (c), contains_func_ (contains_func) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + Sequence::contains (s, contains_func_); + + // Custom data. + // + if (s.context ().count ("cd-name")) + { + String const& scope (Context::scope (s)); + String const& type (etype (s)); + + String const& name (ecd_name (s)); + String const& member (ecd_member (s)); + String const& sequence (ecd_sequence (s)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << type << "::" << + sequence << "& " << scope << "::" << type << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << type << "::" << sequence << "& " << + scope << "::" << type << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + + Sequence::contains (s); + } + + private: + Traversal::ContainsParticle& contains_func_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + + // Functions. + // + attribute_func_ (c), + element_func_ (c), + element_in_choice_func_ (c), + all_func_ (c), + choice_in_choice_func_ (c), + choice_in_sequence_func_ (c), + sequence_in_choice_func_ (c), + sequence_in_sequence_func_ (c), + + // Nested classes. + // + all_ (c, all_contains_func_), + choice_in_choice_ (c, true, choice_contains_func_), + choice_in_sequence_ (c, false, choice_contains_func_), + sequence_in_choice_ (c, sequence_contains_func_), + sequence_in_sequence_ (c, sequence_contains_func_) + { + // Functions. + // + attribute_names_func_ >> attribute_func_; + + all_func_ >> all_contains_func_ >> element_func_; + + sequence_in_choice_func_ >> sequence_contains_func_; + sequence_in_sequence_func_ >> sequence_contains_func_; + sequence_contains_func_ >> element_func_; + sequence_contains_func_ >> choice_in_sequence_func_; + sequence_contains_func_ >> sequence_in_sequence_func_; + + choice_in_choice_func_ >> choice_contains_func_; + choice_in_sequence_func_ >> choice_contains_func_; + choice_contains_func_ >> element_in_choice_func_; + choice_contains_func_ >> sequence_in_choice_func_; + choice_contains_func_ >> choice_in_choice_func_; + + contains_compositor_func_ >> all_func_; + contains_compositor_func_ >> choice_in_sequence_func_; + contains_compositor_func_ >> sequence_in_sequence_func_; + + // Nested classes. + // + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + if (!restriction_p (c)) + { + os << "// " << comment (c.name ()) << endl + << "//" << endl + << endl; + + Complex::names (c, attribute_names_func_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_func_); + + // Nested classes. + // + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + + // Custom data. + // + if (c.context ().count ("cd-name")) + { + String const& scope (ename (c)); + String const& name (ecd_name (c)); + String const& member (ecd_member (c)); + String const& sequence (ecd_sequence (c)); + + // const seq& + // name () const + // + os << inl + << "const " << scope << "::" << sequence << "& " << + scope << "::" << endl + << name << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // seq& + // name () + // + os << inl + << scope << "::" << sequence << "& " << scope << "::" << endl + << name << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + } + } + + private: + // Functions. + // + AttributeFunc attribute_func_; + Traversal::Names attribute_names_func_; + + ElementFunc element_func_; + ElementInChoiceFunc element_in_choice_func_; + AllFunc all_func_; + ChoiceInChoiceFunc choice_in_choice_func_; + ChoiceInSequenceFunc choice_in_sequence_func_; + SequenceInChoiceFunc sequence_in_choice_func_; + SequenceInSequenceFunc sequence_in_sequence_func_; + Traversal::ContainsParticle all_contains_func_; + Traversal::ContainsParticle choice_contains_func_; + Traversal::ContainsParticle sequence_contains_func_; + + Traversal::ContainsCompositor contains_compositor_func_; + + // Nested classes. + // + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + SequenceInChoice sequence_in_choice_; + SequenceInSequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_tree_inline (Context& ctx) + { + // Generate includes. + // + if (ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::inline_); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + else + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + //Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + //names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/tree-inline.hxx b/xsde/cxx/hybrid/tree-inline.hxx new file mode 100644 index 0000000..9c8866d --- /dev/null +++ b/xsde/cxx/hybrid/tree-inline.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/tree-inline.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_INLINE_HXX +#define CXX_HYBRID_TREE_INLINE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_tree_inline (Context&); + } +} + +#endif // CXX_HYBRID_TREE_INLINE_HXX diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx new file mode 100644 index 0000000..c828250 --- /dev/null +++ b/xsde/cxx/hybrid/tree-name-processor.cxx @@ -0,0 +1,1993 @@ +// file : xsde/cxx/hybrid/tree-name-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + Char const* member_set_key = "cxx-hybrid-name-processor-member-set"; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + schema_path_ (file), + schema (root), + schema_path (schema_path_), + custom_data_map (custom_data_map_), + global_type_names (global_type_names_) + { + // Translate the type names with custom data. + // + { + typedef Cult::Containers::Vector CustomData; + CustomData const& cd (ops.value ()); + + for (CustomData::ConstIterator i (cd.begin ()); + i != cd.end (); ++i) + { + String name (*i); + CustomDataMap* map (&custom_data_map); + String::size_type b (0), e; + + do + { + e = name.find (L"::", b); + String entry (name, b, e == String::npos ? e : e - b); + + Shptr& p ((*map)[entry]); + + if (p == 0) + p = Shptr (new CustomDataMap); + + b = e; + + if (b == String::npos) + { + // Last name. Add an empty string to indicate this. + // + (*p)[L""] = Shptr (0); + break; + } + + map = p.get (); + b += 2; + + } while (true); + } + } + } + + protected: + Context (Context& c) + : CXX::Context (c), + schema (c.schema), + schema_path (c.schema_path), + custom_data_map (c.custom_data_map), + global_type_names (c.global_type_names) + { + } + + public: + Boolean + fixed_length (SemanticGraph::Type& t) + { + return t.context ().get ("fixed"); + } + + Boolean + fixed_length (SemanticGraph::Compositor& c) + { + return c.context ().get ("fixed"); + } + + Void + mark_variable (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* p (&c); + + while (true) + { + p->context ().set ("fixed", false); + + if (p->contained_compositor_p ()) + break; + + p = &p->contained_particle ().compositor (); + + if (!p->context ().get ("fixed")) + break; + } + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = Hybrid::Context::escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + public: + struct CustomDataMap: + Cult::Containers::Map > + { + }; + + private: + SemanticGraph::Path const schema_path_; + + CustomDataMap custom_data_map_; + Cult::Containers::Map global_type_names_; + + public: + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + + CustomDataMap& custom_data_map; + Cult::Containers::Map& global_type_names; + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& l) + { + if (!data_members_) + { + // Check if this type has custom data. + // + CustomDataMap::Iterator i (custom_data_map.find (l.name ())); + + if (i != custom_data_map.end () && + i->second->find (L"") != i->second->end ()) + { + SemanticGraph::Context& lc (l.context ()); + + // Use processed name. + // + String const& name (lc.get ("name")); + + lc.set (member_set_key, NameSet ()); + NameSet& set (lc.get (member_set_key)); + set.insert (name); + + { + String name (find_name ("custom_data", set)); + + lc.set ("cd-name", name); + lc.set ("cd-sequence", find_name (name + L"_sequence", set)); + lc.set ("cd-iterator", find_name (name + L"_iterator", set)); + lc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", set)); + } + } + } + else + { + SemanticGraph::Context& lc (l.context ()); + + // Custom data. + // + if (lc.count ("cd-name")) + { + NameSet& set (lc.get (member_set_key)); + String const& base (lc.get ("cd-name")); + lc.set ("cd-member", find_name (base + L"_", set)); + } + } + } + + private: + Boolean data_members_; + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& u) + { + SemanticGraph::Context& uc (u.context ()); + + if (!data_members_) + { + // Use processed name. + // + String const& name (uc.get ("name")); + + uc.set (member_set_key, NameSet ()); + NameSet& set (uc.get (member_set_key)); + set.insert (name); + + uc.set ("value", find_name ("value", set)); + + // Check if this type has custom data. + // + CustomDataMap::Iterator i (custom_data_map.find (u.name ())); + + if (i != custom_data_map.end () && + i->second->find (L"") != i->second->end ()) + { + String name (find_name ("custom_data", set)); + + uc.set ("cd-name", name); + uc.set ("cd-sequence", find_name (name + L"_sequence", set)); + uc.set ("cd-iterator", find_name (name + L"_iterator", set)); + uc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", set)); + } + } + else + { + NameSet& set (uc.get (member_set_key)); + uc.set ("value-member", find_name ("value_", set)); + + // Custom data. + // + if (uc.count ("cd-name")) + { + String const& base (uc.get ("cd-name")); + uc.set ("cd-member", find_name (base + L"_", set)); + } + } + } + + private: + Boolean data_members_; + }; + + // + // Primary names. + // + + struct PrimaryAttribute: Traversal::Attribute, Context + { + PrimaryAttribute (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + a.context ().set ("name", find_name (a.name (), set_)); + } + + private: + NameSet& set_; + }; + + struct PrimaryElement: Traversal::Element, Context + { + PrimaryElement (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + e.context ().set ("name", find_name (e.name (), set_)); + } + + private: + NameSet& set_; + }; + + struct PrimaryAll: Traversal::All, Context + { + PrimaryAll (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + a.context ().set ("name", find_name ("all", set_)); + else + All::contains (a); + } + + private: + NameSet& set_; + }; + + struct PrimaryChoice: Traversal::Choice, Context + { + PrimaryChoice (Context& c, NameSet& set, Boolean in_choice) + : Context (c), set_ (set), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // In case of choice assign primary name even if there is + // no nested class. It is used to derive names for arm + // functions. + // + c.context ().set ("name", find_name ("choice", set_)); + + if (!in_choice_ && c.max () == 1 && c.min () == 1) + Choice::contains (c); + } + + private: + NameSet& set_; + Boolean in_choice_; + }; + + struct PrimarySequence: Traversal::Sequence, Context + { + PrimarySequence (Context& c, NameSet& set, Boolean in_choice) + : Context (c), set_ (set), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + s.context ().set ("name", find_name ("sequence", set_)); + else + Sequence::contains (s); + } + + private: + NameSet& set_; + Boolean in_choice_; + }; + + // + // Secondary names. + // + + struct SecondaryAttribute: Traversal::Attribute, Context + { + SecondaryAttribute (Context& c, NameSet& set, Boolean data_members) + : Context (c), set_ (set), data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Context& ac (a.context ()); + + if (!data_members_) + { + if (a.optional ()) + ac.set ( + "present", + find_name (ac.get ("name") + L"_present", set_)); + } + else + { + String const& base (ac.get ("name")); + + if (a.optional ()) + { + if (fixed_length (a.type ())) + ac.set ("present-member", + find_name (ac.get ("present") + L"_", set_)); + } + + ac.set ("member", find_name (base + L"_", set_)); + } + } + + private: + NameSet& set_; + Boolean data_members_; + }; + + struct SecondaryElement: Traversal::Element, Context + { + SecondaryElement (Context& c, NameSet& set, Boolean data_members) + : Context (c), set_ (set), data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Context& ec (e.context ()); + + if (!data_members_) + { + if (e.max () != 1) + { + String const& base (ec.get ("name")); + + ec.set ("sequence", find_name (base + L"_sequence", set_)); + ec.set ("iterator", find_name (base + L"_iterator", set_)); + ec.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (e.min () == 0) + { + ec.set ( + "present", + find_name (ec.get ("name") + L"_present", set_)); + } + } + else + { + String const& base (ec.get ("name")); + + if (e.max () == 1 && e.min () == 0) + { + if (fixed_length (e.type ())) + ec.set ("present-member", + find_name (ec.get ("present") + L"_", set_)); + } + + ec.set ("member", find_name (base + L"_", set_)); + } + } + + + private: + NameSet& set_; + Boolean data_members_; + }; + + struct SecondaryAll: Traversal::All, Context + { + SecondaryAll (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + SemanticGraph::Context& ac (a.context ()); + String const& base (ac.get ("name")); + + if (!data_members_) + { + // Check if this type has custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + String type (find_name (base + L"_type", set_)); + ac.set ("type", type); + + // Handle the nested class. + // + { + ac.set (member_set_key, NameSet ()); + NameSet& name_set (ac.get (member_set_key)); + + name_set.insert (type); + + { + PrimaryElement element (*this, name_set); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + } + + { + SecondaryElement element (*this, name_set, false); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (a)) + mark_variable (a); + + String name (find_name ("custom_data", name_set)); + + ac.set ("cd-name", name); + + ac.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + ac.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + ac.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + ac.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (ac.get (member_set_key)); + + SecondaryElement element (*this, name_set, true); + Traversal::ContainsParticle contains_particle (element); + All::contains (a, contains_particle); + + // Custom data. + // + if (ac.count ("cd-name")) + { + String const& base (ac.get ("cd-name")); + ac.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (fixed_length (a)) + ac.set ("present-member", + find_name (ac.get ("present") + L"_", set_)); + + ac.set ("member", find_name (base + L"_", set_)); + } + } + else + All::contains (a); + } + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean data_members_; + }; + + struct ParticleTag: Traversal::Element, + Traversal::Any, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleTag (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& base (e.context ().get ("name")); + e.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + a.context ().set ("tag", find_name (L"any", L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + String const& base (c.context ().get ("name")); + c.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + String const& base (s.context ().get ("name")); + s.context ().set ("tag", find_name (base, L"_tag", set_)); + } + + private: + NameSet& set_; + }; + + struct SecondaryChoice: Traversal::Choice, Context + { + SecondaryChoice (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean in_choice, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + in_choice_ (in_choice), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Choice&); + + Void + traverse_nested (SemanticGraph::Choice&, NameSet&, CustomDataMap*); + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean in_choice_; + Boolean data_members_; + }; + + struct SecondarySequence: Traversal::Sequence, Context + { + SecondarySequence (Context& c, + NameSet& set, + CustomDataMap* map, + Boolean in_choice, + Boolean data_members) + : Context (c), + set_ (set), + map_ (map), + in_choice_ (in_choice), + data_members_ (data_members) + { + } + + virtual Void + traverse (SemanticGraph::Sequence&); + + Void + traverse_nested (SemanticGraph::Sequence&, NameSet&, CustomDataMap*); + + private: + NameSet& set_; + CustomDataMap* map_; + Boolean in_choice_; + Boolean data_members_; + }; + + + Void SecondaryChoice:: + traverse (SemanticGraph::Choice& c) + { + SemanticGraph::Context& cc (c.context ()); + String const& base (cc.get ("name")); + + // When choice is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + if (!data_members_) + { + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + // + // + String type (find_name (base + L"_type", set_)); + cc.set ("type", type); + + // Handle the nested class. + // + { + cc.set (member_set_key, NameSet ()); + NameSet& name_set (cc.get (member_set_key)); + + // Add both base and type names so that we get consistent + // naming for nested choices if any. + // + name_set.insert (base); + name_set.insert (type); + + traverse_nested (c, name_set, map); + + // Tags. + // + String arm (find_name (base + L"_arm", name_set)); + cc.set ("arm", arm); + cc.set ("arm-tag", find_name (arm + L"_tag", name_set)); + + { + UnsignedLong count (name_set.size ()); + + ParticleTag particle (*this, name_set); + Traversal::ContainsParticle contains (particle); + + Choice::contains (c, contains); + + count = name_set.size () - count; + cc.set ("arm-tag-count", count); + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (c)) + mark_variable (c); + + String name (find_name ("custom_data", name_set)); + + cc.set ("cd-name", name); + + cc.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + cc.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + cc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + if (c.max () != 1) + { + cc.set ("sequence", find_name (base + L"_sequence", set_)); + cc.set ("iterator", find_name (base + L"_iterator", set_)); + cc.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (c.min () == 0) + cc.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (cc.get (member_set_key)); + traverse_nested (c, name_set, 0); + + // Tags. + // + cc.set ("arm-member", + find_name (cc.get ("arm") + L"_", name_set)); + cc.set ("member", find_name (base + L"_", name_set)); + + // Custom data. + // + if (cc.count ("cd-name")) + { + String const& base (cc.get ("cd-name")); + cc.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (c.max () == 1 && c.min () == 0) + { + if (fixed_length (c)) + cc.set ("present-member", + find_name (cc.get ("present") + L"_", set_)); + } + + cc.set ("member", find_name (base + L"_", set_)); + } + } + else + { + Choice::contains (c); + + if (!data_members_) + { + String arm (find_name (base + L"_arm", set_)); + cc.set ("arm", arm); + cc.set ("arm-tag", find_name (arm + L"_tag", set_)); + + { + UnsignedLong count (set_.size ()); + + ParticleTag particle (*this, set_); + Traversal::ContainsParticle contains (particle); + + Choice::contains (c, contains); + + count = set_.size () - count; + cc.set ("arm-tag-count", count); + } + } + else + { + cc.set ("arm-member", + find_name (cc.get ("arm") + L"_", set_)); + cc.set ("member", find_name (base + L"_", set_)); + } + } + } + + Void SecondaryChoice:: + traverse_nested (SemanticGraph::Choice& c, + NameSet& name_set, + CustomDataMap* map) + { + if (!data_members_) + { + PrimaryElement element (*this, name_set); + PrimaryChoice choice_in_sequence (*this, name_set, false); + PrimarySequence sequence_in_sequence (*this, name_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, name_set, true); + PrimarySequence sequence_in_choice (*this, name_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Choice::contains (c, choice_contains_particle); + } + + SecondaryElement element (*this, name_set, data_members_); + SecondaryChoice choice_in_sequence ( + *this, name_set, map, false, data_members_); + SecondarySequence sequence_in_sequence ( + *this, name_set, map, false, data_members_); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, name_set, map, true, data_members_); + SecondarySequence sequence_in_choice ( + *this, name_set, map, true, data_members_); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Choice::contains (c, choice_contains_particle); + } + + Void SecondarySequence:: + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we have nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + SemanticGraph::Context& sc (s.context ()); + String const& base (sc.get ("name")); + + if (!data_members_) + { + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + + if (map_) + { + CustomDataMap::Iterator i (map_->find (base)); + if (i != map_->end ()) + map = i->second.get (); + } + + String type (find_name (base + L"_type", set_)); + sc.set ("type", type); + + // Handle the nested class. + // + { + sc.set (member_set_key, NameSet ()); + NameSet& name_set (sc.get (member_set_key)); + + // Add both base and type names so that we get consistent + // naming for nested sequences if any. + // + name_set.insert (base); + name_set.insert (type); + + traverse_nested (s, name_set, map); + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + // Make the type var-length if we have custom data. + // + if (fixed_length (s)) + mark_variable (s); + + String name (find_name ("custom_data", name_set)); + + sc.set ("cd-name", name); + + sc.set ("cd-sequence", + find_name (name + L"_sequence", name_set)); + + sc.set ("cd-iterator", + find_name (name + L"_iterator", name_set)); + + sc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", name_set)); + } + } + + if (s.max () != 1) + { + sc.set ("sequence", find_name (base + L"_sequence", set_)); + sc.set ("iterator", find_name (base + L"_iterator", set_)); + sc.set ("const-iterator", + find_name (base + L"_const_iterator", set_)); + } + else if (s.min () == 0) + sc.set ("present", find_name (base + L"_present", set_)); + } + else + { + // Handle the nested class. + // + { + NameSet& name_set (sc.get (member_set_key)); + traverse_nested (s, name_set, 0); + + // Custom data. + // + if (sc.count ("cd-name")) + { + String const& base (sc.get ("cd-name")); + sc.set ("cd-member", find_name (base + L"_", name_set)); + } + } + + if (s.max () == 1 && s.min () == 0) + { + if (fixed_length (s)) + sc.set ("present-member", + find_name (sc.get ("present") + L"_", set_)); + } + + sc.set ("member", find_name (base + L"_", set_)); + } + } + else + Sequence::contains (s); + } + + Void SecondarySequence:: + traverse_nested (SemanticGraph::Sequence& s, + NameSet& name_set, + CustomDataMap* map) + { + if (!data_members_) + { + PrimaryElement element (*this, name_set); + PrimaryChoice choice_in_sequence (*this, name_set, false); + PrimarySequence sequence_in_sequence (*this, name_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, name_set, true); + PrimarySequence sequence_in_choice (*this, name_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Sequence::contains (s, sequence_contains_particle); + } + + SecondaryElement element (*this, name_set, data_members_); + SecondaryChoice choice_in_sequence ( + *this, name_set, map, false, data_members_); + SecondarySequence sequence_in_sequence ( + *this, name_set, map, false, data_members_); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, name_set, map, true, data_members_); + SecondarySequence sequence_in_choice ( + *this, name_set, map, true, data_members_); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Sequence::contains (s, sequence_contains_particle); + } + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c, Boolean data_members) + : Context (c), data_members_ (data_members) + { + } + + virtual Void + traverse (Type& c) + { + if (data_members_) + assign_data (c); + else + assign_names (c); + } + + virtual Void + assign_names (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // Check if this type or any of its nested types have + // custom data. + // + CustomDataMap* map (0); + { + CustomDataMap::Iterator i (custom_data_map.find (c.name ())); + if (i != custom_data_map.end ()) + map = i->second.get (); + } + + // Use processed name. + // + String const& name (cc.get ("name")); + + cc.set (member_set_key, NameSet ()); + NameSet& member_set (cc.get (member_set_key)); + + member_set.insert (name); + + // Add our base's members to the initial list. + // + Boolean restriction (false); + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (b.is_a ()) + { + SemanticGraph::Context& bc (b.context ()); + + if (!bc.count (member_set_key)) + dispatch (b); + + NameSet const& bset (bc.get (member_set_key)); + member_set.insert (bset.begin (), bset.end ()); + } + + // Inheritance by restriction from anyType is a special case. + // + restriction = c.inherits ().is_a () && + !b.is_a (); + } + + if (!restriction) + { + // First assign the "primary" names. + // + PrimaryAttribute pri_attribute (*this, member_set); + Traversal::Names pri_names (pri_attribute); + + Complex::names (c, pri_names); + + if (c.contains_compositor_p ()) + { + PrimaryElement element (*this, member_set); + PrimaryAll all (*this, member_set); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + PrimaryChoice choice_in_sequence (*this, member_set, false); + PrimarySequence sequence_in_sequence (*this, member_set, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + PrimaryChoice choice_in_choice (*this, member_set, true); + PrimarySequence sequence_in_choice (*this, member_set, true); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + + // Assign "secondary" names. + // + SecondaryAttribute sec_attribute (*this, member_set, false); + Traversal::Names sec_names (sec_attribute); + + Complex::names (c, sec_names); + + if (c.contains_compositor_p ()) + { + SecondaryElement element (*this, member_set, false); + SecondaryAll all (*this, member_set, map, false); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + SecondaryChoice choice_in_sequence ( + *this, member_set, map, false, false); + SecondarySequence sequence_in_sequence ( + *this, member_set, map, false, false); + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, member_set, map, true, false); + SecondarySequence sequence_in_choice ( + *this, member_set, map, true, false); + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + } + + // Custom data. + // + if (map && map->find (L"") != map->end ()) + { + String name (find_name ("custom_data", member_set)); + + cc.set ("cd-name", name); + + cc.set ("cd-sequence", + find_name (name + L"_sequence", member_set)); + + cc.set ("cd-iterator", + find_name (name + L"_iterator", member_set)); + + cc.set ("cd-const-iterator", + find_name (name + L"_const_iterator", member_set)); + } + } + + virtual Void + assign_data (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + + NameSet& member_set (cc.get (member_set_key)); + + if (!restriction) + { + SecondaryAttribute sec_attribute (*this, member_set, true); + Traversal::Names sec_names (sec_attribute); + + Complex::names (c, sec_names); + + if (c.contains_compositor_p ()) + { + SecondaryElement element (*this, member_set, true); + SecondaryAll all (*this, member_set, 0, true); + Traversal::ContainsParticle all_contains_particle; + + all >> all_contains_particle >> element; + + SecondaryChoice choice_in_sequence ( + *this, member_set, 0, false, true); + + SecondarySequence sequence_in_sequence ( + *this, member_set, 0, false, true); + + Traversal::ContainsParticle sequence_contains_particle; + + sequence_contains_particle >> element; + sequence_contains_particle >> choice_in_sequence; + sequence_contains_particle >> sequence_in_sequence; + sequence_in_sequence >> sequence_contains_particle; + + SecondaryChoice choice_in_choice ( + *this, member_set, 0, true, true); + + SecondarySequence sequence_in_choice ( + *this, member_set, 0, true, true); + + Traversal::ContainsParticle choice_contains_particle; + + sequence_in_choice >> sequence_contains_particle; + choice_contains_particle >> element; + choice_contains_particle >> choice_in_choice; + choice_contains_particle >> sequence_in_choice; + choice_in_choice >> choice_contains_particle; + choice_in_sequence >> choice_contains_particle; + + Traversal::ContainsCompositor contains_compositor; + + contains_compositor >> all; + contains_compositor >> choice_in_sequence; + contains_compositor >> sequence_in_sequence; + + Complex::contains_compositor (c, contains_compositor); + } + } + + // Custom data. + // + if (cc.count ("cd-name")) + { + String const& base (cc.get ("cd-name")); + cc.set ("cd-member", find_name (base + L"_", member_set)); + } + } + + private: + Boolean data_members_; + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + String name (find_name (t.name (), set_)); + t.context ().set ("name", name); + } + + private: + NameSet& set_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + }; + + struct FundType : Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + + { + FundType (Context& c) + : Context (c) + { + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + set_name (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + set_name (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + set_name (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + set_name (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + set_name (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + set_name (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + set_name (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + set_name (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + set_name (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + set_name (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + set_name (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + set_name (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + set_name (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + set_name (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + set_name (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + set_name (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + set_name (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + set_name (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + set_name (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + set_name (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + set_name (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + set_name (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + set_name (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + set_name (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + set_name (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + set_name (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + set_name (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + set_name (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + set_name (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + set_name (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + set_name (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + set_name (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + set_name (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + set_name (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + set_name (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + set_name (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + set_name (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + set_name (t, "gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + set_name (t, "gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + set_name (t, "gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + set_name (t, "gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + set_name (t, "gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + set_name (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + set_name (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + set_name (t, "entities"); + } + + private: + Void + set_name (SemanticGraph::Type& t, String const& name) + { + SemanticGraph::Context& c (t.context ()); + c.set ("name", escape (name)); + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Imports::traverse (i); + } + } + }; + + // Go into implied schemas while making sure we don't process + // the same stuff more than once. + // + struct Implies: Traversal::Implies + { + virtual Void + traverse (SemanticGraph::Implies& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-name-processor-seen")) + { + s.context ().set ("cxx-hybrid-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // Pass one - assign names to fundamental types. + // + { + Traversal::Schema schema; + Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Pass two - assign names to global types. This pass cannot + // be combined with pass three because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count ("cxx-hybrid-name-processor-seen")) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-hybrid-name-processor-seen", true); + + schema.dispatch (tu); + } + + // Pass three - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx, false); + Union union_ (ctx, false); + Complex complex (ctx, false); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + + // Pass four - assign names to data memeber. Here we aslo don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + List list (ctx, true); + Union union_ (ctx, true); + Complex complex (ctx, true); + + ns_names >> list; + ns_names >> union_; + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + } + + Void TreeNameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/hybrid/tree-name-processor.hxx b/xsde/cxx/hybrid/tree-name-processor.hxx new file mode 100644 index 0000000..4d884bc --- /dev/null +++ b/xsde/cxx/hybrid/tree-name-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/hybrid/tree-name-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_NAME_PROCESSOR_HXX +#define CXX_HYBRID_TREE_NAME_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class TreeNameProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_HYBRID_TREE_NAME_PROCESSOR_HXX diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx new file mode 100644 index 0000000..43fa2fc --- /dev/null +++ b/xsde/cxx/hybrid/tree-size-processor.cxx @@ -0,0 +1,850 @@ +// file : xsde/cxx/hybrid/tree-size-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + typedef Cult::Containers::Set TypeSet; + + Boolean + test (SemanticGraph::Type& t) + { + return t.context ().count ("fixed") != 0; + } + + Void + set (SemanticGraph::Type& t, Boolean v) + { + t.context ().set ("fixed", v); + } + + Void + set (SemanticGraph::Compositor& c, Boolean v) + { + c.context ().set ("fixed", v); + } + + Boolean + get (SemanticGraph::Type& t) + { + return t.context ().get ("fixed"); + } + + // + // + struct Particle: Traversal::Element + { + Particle (Boolean& fixed, Traversal::NodeBase& type_traverser) + : fixed_ (fixed), type_traverser_ (type_traverser) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (fixed_) + { + // Check cardinality. + // + if (e.max () != 1) + { + fixed_ = false; + return; + } + + // Check the type. + // + SemanticGraph::Type& t (e.type ()); + + if (!test (t)) + type_traverser_.dispatch (t); + + fixed_ = get (t); + } + } + + /* + virtual Void + traverse (SemanticGraph::Any&) + { + // Types with wildcards are always variable length. + // + if (fixed_) + fixed_ = false; + } + */ + + private: + Boolean& fixed_; + Traversal::NodeBase& type_traverser_; + }; + + struct Compositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence + { + Compositor (Boolean& fixed, Traversal::NodeBase& type_traverser) + : fixed_ (fixed), type_traverser_ (type_traverser) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. In case of an optional + // compositor we need to assign the size for the nested class. + // + if (a.min () == 0) + { + Boolean fixed = true; + + { + Particle particle (fixed, type_traverser_); + Traversal::ContainsParticle contains_particle; + + contains_particle >> particle; + + All::contains (a, contains_particle); + } + + set (a, fixed); + + if (!fixed) + fixed_ = false; + } + else + All::contains (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // Here we need to assign the size for the nested class in + // all three cases because this choice might be in choice. + // + Boolean fixed = true; + + { + Particle particle (fixed, type_traverser_); + Compositor compositor (fixed, type_traverser_); + Traversal::ContainsParticle contains_particle; + + contains_particle >> compositor >> contains_particle; + contains_particle >> particle; + + Choice::contains (c, contains_particle); + } + + set (c, fixed); + + if (c.max () != 1 || !fixed) + fixed_ = false; + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // Here we need to assign the size for the nested class in + // all three cases because this sequence might be in choice. + // + Boolean fixed = true; + + { + Particle particle (fixed, type_traverser_); + Compositor compositor (fixed, type_traverser_); + Traversal::ContainsParticle contains_particle; + + contains_particle >> compositor >> contains_particle; + contains_particle >> particle; + + Sequence::contains (s, contains_particle); + } + + set (s, fixed); + + if (s.max () != 1 || !fixed) + fixed_ = false; + } + + private: + Boolean& fixed_; + Traversal::NodeBase& type_traverser_; + }; + + struct Attribute: Traversal::Attribute + { + Attribute (Boolean& fixed, Traversal::NodeBase& type_traverser) + : fixed_ (fixed), type_traverser_ (type_traverser) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (fixed_) + { + SemanticGraph::Type& t (a.type ()); + + if (!test (t)) + type_traverser_.dispatch (t); + + fixed_ = get (t); + } + } + + /* + virtual Void + traverse (SemanticGraph::AnyAttribute&) + { + // Types with wildcards are always variable length. + // + if (fixed_) + fixed_ = false; + } + */ + + private: + Boolean& fixed_; + Traversal::NodeBase& type_traverser_; + }; + + // + // + struct Type: Traversal::List, + Traversal::Union, + Traversal::Complex + { + Type (TypeSet& custom_data, Boolean stl_) + : custom_data_ (custom_data), stl (stl_) + { + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!test (l)) + set (l, false); + } + + virtual Void + traverse (SemanticGraph::Union& u) + { + if (!test (u)) + { + Boolean fixed (stl); + + // Check for custom data. + // + if (fixed) + { + if (custom_data_.find (u.name ()) != custom_data_.end ()) + fixed = false; + } + + set (u, fixed); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (test (c)) + return; + + if (ctx.count ("recurse")) + set (c, false); + else + { + ctx.set ("recurse", true); + + Boolean fixed = true; + + // First check our base. + // + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!test (b)) + dispatch (b); + + fixed = get (b); + } + + // Check particles. Do this even if fixed is already false + // because we need to calculate sizes for nested classes. + // + if (c.contains_compositor_p ()) + { + Particle particle (fixed, *this); + Compositor compositor (fixed, *this); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor; + + contains_particle >> compositor >> contains_particle; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + + // Check attributes. + // + if (fixed) + { + Attribute attr (fixed, *this); + Traversal::Names names (attr); + + Complex::names (c, names); + } + + // Check for custom data. + // + if (fixed) + { + if (custom_data_.find (c.name ()) != custom_data_.end ()) + fixed = false; + } + + // If we recursed then we should have the value already set. + // + if (!test (c)) + set (c, fixed); + + ctx.remove ("recurse"); + } + } + + private: + TypeSet& custom_data_; + Boolean stl; + }; + + struct FundType : Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + + { + FundType (Boolean stl_) + : stl (stl_) + { + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + set (t, true); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + set (t, true); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + set (t, true); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + set (t, true); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + set (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + set (t, stl); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + set (t, stl); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + set (t, false); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + set (t, stl); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + set (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + set (t, false); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + set (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + set (t, true); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + set (t, stl); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + set (t, false); + } + + private: + Boolean stl; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count ("cxx-hybrid-size-processor-seen")) + { + s.context ().set ("cxx-hybrid-size-processor-seen", true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-size-processor-seen")) + { + s.context ().set ("cxx-hybrid-size-processor-seen", true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-hybrid-size-processor-seen")) + { + s.context ().set ("cxx-hybrid-size-processor-seen", true); + Traversal::Imports::traverse (i); + } + } + }; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&) + { + Boolean stl (!ops.value ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + if (i != tu.names_end () && + i->named ().name () == L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (stl); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // Pass one - assign sizes to fundamental types. + // + { + Traversal::Schema schema; + Traversal::Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (stl); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count ("cxx-hybrid-size-processor-seen")) + { + // Prepare a set of types with custom data. Here we are + // only interested in detecting global types. If a type + // has a nested compositor type which has custom data + // then the type itself will automatically be variable + // size. + // + TypeSet custom_data_types; + + { + typedef Cult::Containers::Vector CustomData; + CustomData const& cd (ops.value ()); + + for (CustomData::ConstIterator i (cd.begin ()); + i != cd.end (); ++i) + { + String n (*i); + custom_data_types.insert (String (n, 0, n.find (L"::"))); + } + } + + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (custom_data_types, stl); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-hybrid-size-processor-seen", true); + + schema.dispatch (tu); + } + } + } + } + + Void TreeSizeProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/hybrid/tree-size-processor.hxx b/xsde/cxx/hybrid/tree-size-processor.hxx new file mode 100644 index 0000000..130451f --- /dev/null +++ b/xsde/cxx/hybrid/tree-size-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/hybrid/tree-size-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX +#define CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class TreeSizeProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx new file mode 100644 index 0000000..d6c3672 --- /dev/null +++ b/xsde/cxx/hybrid/tree-source.cxx @@ -0,0 +1,1672 @@ +// file : xsd/cxx/hybrid/tree-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + struct ChoiceParticle: Traversal::Element, + Traversal::Compositor, + Context + { + enum Action + { + alloc, + free, + copy, + assign + }; + + ChoiceParticle (Context& c, Action action) + : Context (c), + action_ (action), + var_ (c, TypeName::var), + delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Type& t (e.type ()); + + Boolean fund (false); + { + FundamentalType test (fund); + test.dispatch (t); + } + + // Detect cases where we don't need to generate anything. + // + if (fund) + { + switch (action_) + { + case alloc: + { + if (e.max () == 1 && e.min () == 1) + return; + + break; + } + case free: + { + if (e.max () == 1) + return; + + break; + } + default: + break; + } + } + + String const& member (emember (e)); + String const& umember ( + emember (e.contained_particle ().compositor ())); + + os << "case " << etag (e) << ":" + << "{"; + + switch (action_) + { + case alloc: + { + if (e.max () != 1) + { + os << "new (&this->" << umember << "." << member << ") " << + esequence (e) << ";"; + } + else + { + if (fixed_length (t)) + { + if (!fund) + { + os << "new (&this->" << umember << "." << member << ") "; + var_.dispatch (t); + os << ";"; + } + + if (e.min () == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")] = false;"; + } + } + else + os << "this->" << umember << "." << member << " = 0;"; + } + + break; + } + case free: + { + if (e.max () != 1) + { + String const& sequence (esequence (e)); + + os << "typedef " << sequence << " _dtor;" + << "reinterpret_cast< " << sequence << "& > (this->" << + umember << "." << member << ").~_dtor ();"; + } + else + { + if (fixed_length (t)) + { + os << "typedef "; + var_.dispatch (t); + os << " _dtor;"; + + os << "reinterpret_cast< "; + var_.dispatch (t); + os << "& > (this->" << umember << "." << member << ")." + << "~_dtor ();"; + } + else + { + delete_.dispatch (t); + os << " this->" << umember << "." << member << ";"; + } + } + + break; + } + case copy: + { + // Here we only need to handle the fixed-length situation. + // + if (fund) + { + // Use POD copying. + // + os << "this->" << umember << "." << member << " = x." << + umember << "." << member << ";"; + } + else + { + if (e.min () == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")] = x." << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")];" + << "if (this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")])" << endl; + } + + os << "new (&this->" << umember << "." << member << ") "; + var_.dispatch (t); + os << " (reinterpret_cast< const "; + var_.dispatch (t); + os << "& > (x." << umember << "." << member << "));"; + } + + break; + } + case assign: + { + // Here we only need to handle the fixed-length situation. + // + if (fund) + { + // Use POD assignment. + // + os << "this->" << umember << "." << member << " = x." << + umember << "." << member << ";"; + } + else + { + if (e.min () == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")] = x." << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")];" + << "if (this->" << umember << "." << member << + ".data_[sizeof ("; + var_.dispatch (t); + os << ")])" << endl; + } + + os << "reinterpret_cast< "; + var_.dispatch (t); + os << "& > (this->" << umember << "." << member << ") = " << + "reinterpret_cast< const "; + var_.dispatch (t); + os << "& > (x." << umember << "." << member << ");"; + } + + break; + } + } + + os << "break;" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + String const& member (emember (c)); + String const& umember ( + emember (c.contained_particle ().compositor ())); + + os << "case " << etag (c) << ":" + << "{"; + + switch (action_) + { + case alloc: + { + if (c.max () != 1) + { + os << "new (&this->" << umember << "." << member << ") " << + esequence (c) << ";"; + } + else + { + if (fixed_length (c)) + { + String const& type (etype (c)); + + os << "new (&this->" << umember << "." << member << ") " << + type << ";"; + + if (c.min () == 0) + os << "this->" << umember << "." << member << + ".data_[sizeof (" << type << ")] = false;"; + } + else + os << "this->" << umember << "." << member << " = 0;"; + } + + break; + } + case free: + { + if (c.max () != 1) + { + String const& sequence (esequence (c)); + + os << "typedef " << sequence << " _dtor;" + << "reinterpret_cast< " << sequence << "& > (this->" << + umember << "." << member << ").~_dtor ();"; + } + else + { + if (fixed_length (c)) + { + String const& type (etype (c)); + + os << "reinterpret_cast< " << type << "& > (this->" << + umember << "." << member << ").~" << type << " ();"; + } + else + os << "delete this->" << umember << "." << member << ";"; + } + + break; + } + case copy: + { + // Here we only need to handle the fixed-length situation. + // + String const& type (etype (c)); + + if (c.min () == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof (" << type << ")] = x." << umember << + "." << member << ".data_[sizeof (" << type << ")];" + << "if (this->" << umember << "." << member << + ".data_[sizeof (" << type << ")])" << endl; + } + + os << "new (&this->" << umember << "." << member << ") " << + type << " (reinterpret_cast< const " << type << "& > (x." << + umember << "." << member << "));"; + + break; + } + case assign: + { + // Here we only need to handle the fixed-length situation. + // + String const& type (etype (c)); + + if (c.min () == 0) + { + os << "this->" << umember << "." << member << + ".data_[sizeof (" << type << ")] = x." << umember << + "." << member << ".data_[sizeof (" << type << ")];" + << "if (this->" << umember << "." << member << + ".data_[sizeof (" << type << ")])" << endl; + } + + os << "reinterpret_cast< " << type << "& > (this->" << + umember << "." << member << ") = " << + "reinterpret_cast< const " << type << "& > (x." << + umember << "." << member << ");"; + + break; + } + } + + os << "break;" + << "}"; + } + + private: + Action action_; + TypeName var_; + TypeOps delete_; + }; + + // + // Functions. + // + + struct ChoiceFunc: Traversal::Choice, Context + { + ChoiceFunc (Context& c, Boolean in_choice) + : Context (c), + in_choice_ (in_choice), + particle_free_ (c, ChoiceParticle::free), + particle_alloc_ (c, ChoiceParticle::alloc) + { + contains_free_ >> particle_free_; + contains_alloc_ >> particle_alloc_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (!in_choice_ && c.max () == 1 && c.min () == 1) + { + String const& arm_tag (earm_tag (c)); + String const& arm_member (earm_member (c)); + UnsignedLong bad_tag (arm_tag_count (c)); + + // void + // arm (arm_tag) + // + os << "void " << scope (c) << "::" << endl + << earm (c) << " (" << arm_tag << " x)" + << "{" + << "if (this->" << arm_member << " == x)" << endl + << "return;" + << endl + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_free_); + + os << "default:" << endl + << "break;" + << "}" + << "this->" << arm_member << " = " << + arm_tag << " (" << bad_tag << ");" + << endl + << "switch (x)" + << "{"; + + Choice::contains (c, contains_alloc_); + + os << "default:" << endl + << "break;" + << "}" + << "this->" << arm_member << " = x;" + << "}"; + } + } + + private: + Boolean in_choice_; + + ChoiceParticle particle_free_; + Traversal::ContainsParticle contains_free_; + + ChoiceParticle particle_alloc_; + Traversal::ContainsParticle contains_alloc_; + }; + + struct SequenceFunc: Traversal::Sequence, Context + { + SequenceFunc (Context& c, Boolean in_choice) + : Context (c), in_choice_ (in_choice) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (!in_choice_ && s.max () == 1 && s.min () == 1) + Sequence::contains (s); + } + + private: + Boolean in_choice_; + }; + + // + // C-tor initialization. + // + + struct AttributeCtor: Traversal::Attribute, Context + { + AttributeCtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + Boolean fl (fixed_length (a.type ())); + + if (!fl) + os << "this->" << emember (a) << " = 0;"; + + if (fl && a.optional ()) + os << "this->" << epresent_member (a) << " = false;"; + } + }; + + + struct ElementCtor: Traversal::Element, Context + { + ElementCtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () == 1) + { + Boolean fl (fixed_length (e.type ())); + + if (!fl) + os << "this->" << emember (e) << " = 0;"; + + if (fl && e.min () == 0) + os << "this->" << epresent_member (e) << " = false;"; + } + } + }; + + struct AllCtor: Traversal::All, Context + { + AllCtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + if (fixed_length (a)) + os << "this->" << epresent_member (a) << " = false;"; + else + os << "this->" << emember (a) << " = 0;"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceCtor: Traversal::Choice, Context + { + ChoiceInSequenceCtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () == 1) + { + if (c.min () == 0) + { + if (fixed_length (c)) + os << "this->" << epresent_member (c) << " = false;"; + else + os << "this->" << emember (c) << " = 0;"; + } + else + { + os << "this->" << earm_member (c) << " = " << + earm_tag (c) << " (" << arm_tag_count (c) << ");"; + } + } + } + }; + + struct SequenceInSequenceCtor: Traversal::Sequence, Context + { + SequenceInSequenceCtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () == 1) + { + if (s.min () == 0) + { + if (fixed_length (s)) + os << "this->" << epresent_member (s) << " = false;"; + else + os << "this->" << emember (s) << " = 0;"; + } + else + Sequence::contains (s); + } + } + }; + + // + // D-tor cleanup. + // + + struct AttributeDtor: Traversal::Attribute, Context + { + AttributeDtor (Context& c) + : Context (c), delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Type& t (a.type ()); + + if (!fixed_length (t)) + { + delete_.dispatch (t); + os << " this->" << emember (a) << ";"; + } + } + + private: + TypeOps delete_; + }; + + + struct ElementDtor: Traversal::Element, Context + { + ElementDtor (Context& c) + : Context (c), delete_ (c, TypeOps::delete_) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (e.max () == 1) + { + SemanticGraph::Type& t (e.type ()); + + if (!fixed_length (t)) + { + delete_.dispatch (t); + os << " this->" << emember (e) << ";"; + } + } + } + + private: + TypeOps delete_; + }; + + struct AllDtor: Traversal::All, Context + { + AllDtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + if (!fixed_length (a)) + os << "delete this->" << emember (a) << ";"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceDtor: Traversal::Choice, Context + { + ChoiceInSequenceDtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.max () == 1) + { + if (c.min () == 0) + { + if (!fixed_length (c)) + os << "delete this->" << emember (c) << ";"; + } + else + { + os << "this->" << earm (c) << " (" << + earm_tag (c) << " (" << arm_tag_count (c) << "));"; + } + } + } + }; + + struct SequenceInSequenceDtor: Traversal::Sequence, Context + { + SequenceInSequenceDtor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.max () == 1) + { + if (s.min () == 0) + { + if (!fixed_length (s)) + os << "delete this->" << emember (s) << ";"; + } + else + Sequence::contains (s); + } + } + }; + + // + // Copy c-tor. + // + + struct AttributeCopy: Traversal::Attribute, Context + { + AttributeCopy (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + if (a.optional ()) + { + String const& present_member (epresent_member (a)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct ElementCopy: Traversal::Element, Context + { + ElementCopy (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& member (emember (e)); + + if (e.min () == 0) + { + String const& present_member (epresent_member (e)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct AllCopy: Traversal::All, Context + { + AllCopy (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (a.min () == 0) + { + String const& member (emember (a)); + String const& present_member (epresent_member (a)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceCopy: Traversal::Choice, Context + { + ChoiceInSequenceCopy (Context& c) + : Context (c), particle_copy_ (c, ChoiceParticle::copy) + { + contains_copy_ >> particle_copy_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.min () == 0) + { + String const& member (emember (c)); + String const& present_member (epresent_member (c)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + { + String const& arm_member (earm_member (c)); + + os << "this->" << arm_member << " = x." << arm_member << ";" + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_copy_); + + os << "default:" << endl + << "break;" + << "}"; + } + } + + private: + ChoiceParticle particle_copy_; + Traversal::ContainsParticle contains_copy_; + }; + + struct SequenceInSequenceCopy: Traversal::Sequence, Context + { + SequenceInSequenceCopy (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.min () == 0) + { + String const& member (emember (s)); + String const& present_member (epresent_member (s)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + Sequence::contains (s); + } + }; + + // + // Assign c-tor. + // + + struct AttributeAssign: Traversal::Attribute, Context + { + AttributeAssign (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + if (a.optional ()) + { + String const& present_member (epresent_member (a)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct ElementAssign: Traversal::Element, Context + { + ElementAssign (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& member (emember (e)); + + if (e.min () == 0) + { + String const& present_member (epresent_member (e)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct AllAssign: Traversal::All, Context + { + AllAssign (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (a.min () == 0) + { + String const& member (emember (a)); + String const& present_member (epresent_member (a)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + All::contains (a); + } + }; + + struct ChoiceInSequenceAssign: Traversal::Choice, Context + { + ChoiceInSequenceAssign (Context& c) + : Context (c), particle_assign_ (c, ChoiceParticle::assign) + { + contains_assign_ >> particle_assign_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.min () == 0) + { + String const& member (emember (c)); + String const& present_member (epresent_member (c)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + { + String const& arm_member (earm_member (c)); + + os << "this->" << earm (c) << " (x." << arm_member << ");" + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_assign_); + + os << "default:" << endl + << "break;" + << "}"; + } + } + + private: + ChoiceParticle particle_assign_; + Traversal::ContainsParticle contains_assign_; + }; + + struct SequenceInSequenceAssign: Traversal::Sequence, Context + { + SequenceInSequenceAssign (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (s.min () == 0) + { + String const& member (emember (s)); + String const& present_member (epresent_member (s)); + + os << "this->" << present_member << " = x." << present_member << ";" + << "if (this->" << present_member << ")" << endl + << "this->" << member << " = x." << member << ";"; + } + else + Sequence::contains (s); + } + }; + + // + // Nested classes. + // + + struct All: Traversal::All, Context + { + All (Context& c, + Traversal::ContainsParticle& contains_ctor, + Traversal::ContainsParticle& contains_dtor, + Traversal::ContainsParticle& contains_copy, + Traversal::ContainsParticle& contains_assign) + : Context (c), + contains_ctor_ (contains_ctor), + contains_dtor_ (contains_dtor), + contains_copy_ (contains_copy), + contains_assign_ (contains_assign) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it can only contain particles. + // + if (a.min () == 0) + { + String const& type (etype (a)); + String const& scope (Context::scope (a)); + + // c-tor + // + os << scope << "::" << type << "::" << endl + << type << " ()" + << "{"; + + All::contains (a, contains_ctor_); + + os << "}"; + + // d-tor + // + os << scope << "::" << type << "::" << endl + << "~" << type << " ()" + << "{"; + + All::contains (a, contains_dtor_); + + os << "}"; + + if (fixed_length (a)) + { + // copy c-tor + // + os << scope << "::" << type << "::" << endl + << type << " (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + All::contains (a, contains_copy_); + + os << "}"; + + // operator= + // + os << scope << "::" << type << "& " << scope << "::" << + type << "::" << endl + << "operator= (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + All::contains (a, contains_assign_); + + os << "return *this;" + << "}"; + } + } + } + + private: + Traversal::ContainsParticle& contains_ctor_; + Traversal::ContainsParticle& contains_dtor_; + Traversal::ContainsParticle& contains_copy_; + Traversal::ContainsParticle& contains_assign_; + }; + + struct Choice: Traversal::Choice, Context + { + Choice (Context& c, + Boolean in_choice, + Traversal::ContainsParticle& contains_func) + : Context (c), + in_choice_ (in_choice), + contains_func_ (contains_func), + particle_free_ (c, ChoiceParticle::free), + particle_alloc_ (c, ChoiceParticle::alloc), + particle_copy_ (c, ChoiceParticle::copy), + particle_assign_ (c, ChoiceParticle::assign) + { + contains_free_ >> particle_free_; + contains_alloc_ >> particle_alloc_; + contains_copy_ >> particle_copy_; + contains_assign_ >> particle_assign_; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + // When choice is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || c.max () != 1 || c.min () == 0) + { + String const& type (etype (c)); + String const& arm (earm (c)); + String const& arm_tag (earm_tag (c)); + String const& arm_member (earm_member (c)); + UnsignedLong bad_tag (arm_tag_count (c)); + + String const& scope (Context::scope (c)); + + // c-tor () + // + os << scope << "::" << type << "::" << endl + << type << " ()" + << "{" + << "this->" << arm_member << " = " << + arm_tag << " (" << bad_tag << ");" + << "}"; + + // d-tor () + // + os << scope << "::" << type << "::" << endl + << "~" << type << " ()" + << "{" + << "this->" << arm << " (" << + arm_tag << " (" << bad_tag << "));" + << "}"; + + if (fixed_length (c)) + { + // copy c-tor + // + os << scope << "::" << type << "::" << endl + << type << " (const " << type << "& x)" + << "{" + << "this->" << arm_member << " = x." << arm_member << ";" + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_copy_); + + os << "default:" << endl + << "break;" + << "}" + << "}"; + + // operator= + // + os << scope << "::" << type << "& " << scope << "::" << + type << "::" << endl + << "operator= (const " << type << "& x)" + << "{" + << "this->" << arm << " (x." << arm_member << ");" + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_assign_); + + os << "default:" << endl + << "break;" + << "}" + << "return *this;" + << "}"; + } + + // void + // arm (arm_tag) + // + os << "void " << scope << "::" << type << "::" << endl + << arm << " (" << arm_tag << " x)" + << "{" + << "if (this->" << arm_member << " == x)" << endl + << "return;" + << endl + << "switch (this->" << arm_member << ")" + << "{"; + + Choice::contains (c, contains_free_); + + os << "default:" << endl + << "break;" + << "}" + << "this->" << arm_member << " = " << + arm_tag << " (" << bad_tag << ");" + << endl + << "switch (x)" + << "{"; + + Choice::contains (c, contains_alloc_); + + os << "default:" << endl + << "break;" + << "}" + << "this->" << arm_member << " = x;" + << "}"; + + Choice::contains (c, contains_func_); + } + + Choice::contains (c); + } + + private: + Boolean in_choice_; + Traversal::ContainsParticle& contains_func_; + + ChoiceParticle particle_free_; + Traversal::ContainsParticle contains_free_; + + ChoiceParticle particle_alloc_; + Traversal::ContainsParticle contains_alloc_; + + ChoiceParticle particle_copy_; + Traversal::ContainsParticle contains_copy_; + + ChoiceParticle particle_assign_; + Traversal::ContainsParticle contains_assign_; + }; + + + struct Sequence: Traversal::Sequence, Context + { + Sequence (Context& c, + Boolean in_choice, + Traversal::ContainsParticle& contains_ctor, + Traversal::ContainsParticle& contains_dtor, + Traversal::ContainsParticle& contains_copy, + Traversal::ContainsParticle& contains_assign, + Traversal::ContainsParticle& contains_func) + : Context (c), + in_choice_ (in_choice), + contains_ctor_ (contains_ctor), + contains_dtor_ (contains_dtor), + contains_copy_ (contains_copy), + contains_assign_ (contains_assign), + contains_func_ (contains_func) + { + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // When sequence is in choice we generate nested class even + // for min == max == 1. + // + if (in_choice_ || s.max () != 1 || s.min () == 0) + { + String const& type (etype (s)); + String const& scope (Context::scope (s)); + + // c-tor () + // + os << scope << "::" << type << "::" << endl + << type << " ()" + << "{"; + + Sequence::contains (s, contains_ctor_); + + os << "}"; + + // d-tor () + // + os << scope << "::" << type << "::" << endl + << "~" << type << " ()" + << "{"; + + Sequence::contains (s, contains_dtor_); + + os << "}"; + + if (fixed_length (s)) + { + // copy c-tor + // + os << scope << "::" << type << "::" << endl + << type << " (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + Sequence::contains (s, contains_copy_); + + os << "}"; + + // operator= + // + os << scope << "::" << type << "& " << scope << "::" << + type << "::" << endl + << "operator= (const " << type << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + Sequence::contains (s, contains_assign_); + + os << "return *this;" + << "}"; + } + + Sequence::contains (s, contains_func_); + } + + Sequence::contains (s); + } + + private: + Boolean in_choice_; + Traversal::ContainsParticle& contains_ctor_; + Traversal::ContainsParticle& contains_dtor_; + Traversal::ContainsParticle& contains_copy_; + Traversal::ContainsParticle& contains_assign_; + Traversal::ContainsParticle& contains_func_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + base_name_ (c, TypeName::base), + + // Functions. + // + choice_in_choice_func_ (c, true), + choice_in_sequence_func_ (c, false), + sequence_in_choice_func_ (c, true), + sequence_in_sequence_func_ (c, false), + + // C-tor initialization. + // + attribute_ctor_ (c), + element_ctor_ (c), + all_ctor_ (c), + choice_in_sequence_ctor_ (c), + sequence_in_sequence_ctor_ (c), + + // D-tor cleanup. + // + attribute_dtor_ (c), + element_dtor_ (c), + all_dtor_ (c), + choice_in_sequence_dtor_ (c), + sequence_in_sequence_dtor_ (c), + + // Copy. + // + attribute_copy_ (c), + element_copy_ (c), + all_copy_ (c), + choice_in_sequence_copy_ (c), + sequence_in_sequence_copy_ (c), + + // Assign. + // + attribute_assign_ (c), + element_assign_ (c), + all_assign_ (c), + choice_in_sequence_assign_ (c), + sequence_in_sequence_assign_ (c), + + // Nested c-tors, etc. + // + all_ (c, + all_contains_ctor_, + all_contains_dtor_, + all_contains_copy_, + all_contains_assign_), + choice_in_choice_ (c, true, choice_contains_func_), + choice_in_sequence_ (c, false, choice_contains_func_), + sequence_in_choice_ ( + c, + true, + sequence_contains_ctor_, + sequence_contains_dtor_, + sequence_contains_copy_, + sequence_contains_assign_, + sequence_contains_func_), + sequence_in_sequence_ ( + c, + false, + sequence_contains_ctor_, + sequence_contains_dtor_, + sequence_contains_copy_, + sequence_contains_assign_, + sequence_contains_func_) + { + // Functions. + // + sequence_in_choice_func_ >> sequence_contains_func_; + sequence_in_sequence_func_ >> sequence_contains_func_; + sequence_contains_func_ >> choice_in_sequence_func_; + sequence_contains_func_ >> sequence_in_sequence_func_; + + choice_in_choice_func_ >> choice_contains_func_; + choice_in_sequence_func_ >> choice_contains_func_; + choice_contains_func_ >> sequence_in_choice_func_; + choice_contains_func_ >> choice_in_choice_func_; + + contains_compositor_func_ >> choice_in_sequence_func_; + contains_compositor_func_ >> sequence_in_sequence_func_; + + // C-tor initialization. + // + attribute_names_ctor_ >> attribute_ctor_; + + all_ctor_ >> all_contains_ctor_ >> element_ctor_; + + sequence_in_sequence_ctor_ >> sequence_contains_ctor_; + sequence_contains_ctor_ >> element_ctor_; + sequence_contains_ctor_ >> choice_in_sequence_ctor_; + sequence_contains_ctor_ >> sequence_in_sequence_ctor_; + + contains_compositor_ctor_ >> all_ctor_; + contains_compositor_ctor_ >> choice_in_sequence_ctor_; + contains_compositor_ctor_ >> sequence_in_sequence_ctor_; + + // D-tor cleanup. + // + attribute_names_dtor_ >> attribute_dtor_; + + all_dtor_ >> all_contains_dtor_ >> element_dtor_; + + sequence_in_sequence_dtor_ >> sequence_contains_dtor_; + sequence_contains_dtor_ >> element_dtor_; + sequence_contains_dtor_ >> choice_in_sequence_dtor_; + sequence_contains_dtor_ >> sequence_in_sequence_dtor_; + + contains_compositor_dtor_ >> all_dtor_; + contains_compositor_dtor_ >> choice_in_sequence_dtor_; + contains_compositor_dtor_ >> sequence_in_sequence_dtor_; + + // Copy. + // + attribute_names_copy_ >> attribute_copy_; + + all_copy_ >> all_contains_copy_ >> element_copy_; + + sequence_in_sequence_copy_ >> sequence_contains_copy_; + sequence_contains_copy_ >> element_copy_; + sequence_contains_copy_ >> choice_in_sequence_copy_; + sequence_contains_copy_ >> sequence_in_sequence_copy_; + + contains_compositor_copy_ >> all_copy_; + contains_compositor_copy_ >> choice_in_sequence_copy_; + contains_compositor_copy_ >> sequence_in_sequence_copy_; + + // Assign. + // + attribute_names_assign_ >> attribute_assign_; + + all_assign_ >> all_contains_assign_ >> element_assign_; + + sequence_in_sequence_assign_ >> sequence_contains_assign_; + sequence_contains_assign_ >> element_assign_; + sequence_contains_assign_ >> choice_in_sequence_assign_; + sequence_contains_assign_ >> sequence_in_sequence_assign_; + + contains_compositor_assign_ >> all_assign_; + contains_compositor_assign_ >> choice_in_sequence_assign_; + contains_compositor_assign_ >> sequence_in_sequence_assign_; + + // Nested c-tors, etc. + // + all_ >> all_contains_; + + choice_in_choice_ >> choice_contains_; + choice_in_sequence_ >> choice_contains_; + choice_contains_ >> choice_in_choice_; + choice_contains_ >> sequence_in_choice_; + + sequence_in_choice_ >> sequence_contains_; + sequence_in_sequence_ >> sequence_contains_; + sequence_contains_ >> choice_in_sequence_; + sequence_contains_ >> sequence_in_sequence_; + + contains_compositor_ >> all_; + contains_compositor_ >> choice_in_sequence_; + contains_compositor_ >> sequence_in_sequence_; + } + + virtual Void + traverse (Type& c) + { + Boolean restriction (restriction_p (c)); + + String name (ename (c)); + + os << "// " << comment (c.name ()) << endl + << "//" << endl + << endl; + + // c-tor () + // + os << name << "::" << endl + << name << " ()" + << "{"; + + if (!restriction) + { + Complex::names (c, attribute_names_ctor_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_ctor_); + } + + os << "}"; + + + if (!restriction) + { + // d-tor () + // + os << name << "::" << endl + << "~" << name << " ()" + << "{"; + + Complex::names (c, attribute_names_dtor_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_dtor_); + + os << "}"; + + if (fixed_length (c)) + { + // copy c-tor + // + os << name << "::" << endl + << name << " (const " << name << "& x)"; + + if (c.inherits_p ()) + { + os << endl + << ": "; + base_name_.dispatch (c.inherits ().base ()); + os << " (x)"; + } + + os << "{" + << "XSDE_UNUSED (x);"; + + Complex::names (c, attribute_names_copy_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_copy_); + + os << "}"; + + // operator= + // + os << name << "& " << name << "::" << endl + << "operator= (const " << name << "& x)" + << "{" + << "XSDE_UNUSED (x);"; + + if (c.inherits_p ()) + { + os << "static_cast< "; + base_name_.dispatch (c.inherits ().base ()); + os << "& > (*this) = x;"; + } + + Complex::names (c, attribute_names_assign_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_assign_); + + os << "return *this;" + << "}"; + } + + // Functions. + // + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_func_); + + // Nested c-tors, etc. + // + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } + } + + private: + TypeName base_name_; + + // Functions. + // + ChoiceFunc choice_in_choice_func_; + ChoiceFunc choice_in_sequence_func_; + SequenceFunc sequence_in_choice_func_; + SequenceFunc sequence_in_sequence_func_; + Traversal::ContainsParticle choice_contains_func_; + Traversal::ContainsParticle sequence_contains_func_; + + Traversal::ContainsCompositor contains_compositor_func_; + + // C-tor initialization. + // + AttributeCtor attribute_ctor_; + Traversal::Names attribute_names_ctor_; + + ElementCtor element_ctor_; + AllCtor all_ctor_; + ChoiceInSequenceCtor choice_in_sequence_ctor_; + SequenceInSequenceCtor sequence_in_sequence_ctor_; + Traversal::ContainsParticle all_contains_ctor_; + Traversal::ContainsParticle sequence_contains_ctor_; + + Traversal::ContainsCompositor contains_compositor_ctor_; + + // D-tor cleanup. + // + AttributeDtor attribute_dtor_; + Traversal::Names attribute_names_dtor_; + + ElementDtor element_dtor_; + AllDtor all_dtor_; + ChoiceInSequenceDtor choice_in_sequence_dtor_; + SequenceInSequenceDtor sequence_in_sequence_dtor_; + Traversal::ContainsParticle all_contains_dtor_; + Traversal::ContainsParticle sequence_contains_dtor_; + + Traversal::ContainsCompositor contains_compositor_dtor_; + + // Copy. + // + AttributeCopy attribute_copy_; + Traversal::Names attribute_names_copy_; + + ElementCopy element_copy_; + AllCopy all_copy_; + ChoiceInSequenceCopy choice_in_sequence_copy_; + SequenceInSequenceCopy sequence_in_sequence_copy_; + Traversal::ContainsParticle all_contains_copy_; + Traversal::ContainsParticle sequence_contains_copy_; + + Traversal::ContainsCompositor contains_compositor_copy_; + + // Assign. + // + AttributeAssign attribute_assign_; + Traversal::Names attribute_names_assign_; + + ElementAssign element_assign_; + AllAssign all_assign_; + ChoiceInSequenceAssign choice_in_sequence_assign_; + SequenceInSequenceAssign sequence_in_sequence_assign_; + Traversal::ContainsParticle all_contains_assign_; + Traversal::ContainsParticle sequence_contains_assign_; + + Traversal::ContainsCompositor contains_compositor_assign_; + + // Nested c-tors, etc. + // + All all_; + Choice choice_in_choice_; + Choice choice_in_sequence_; + Sequence sequence_in_choice_; + Sequence sequence_in_sequence_; + Traversal::ContainsParticle all_contains_; + Traversal::ContainsParticle choice_contains_; + Traversal::ContainsParticle sequence_contains_; + + Traversal::ContainsCompositor contains_compositor_; + }; + } + + Void + generate_tree_source (Context& ctx) + { + // Needed for placement new. + // + ctx.os << "#include " << endl + << endl; + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + //Union union_ (ctx); + Complex complex (ctx); + //Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + //names >> union_; + names >> complex; + //names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/hybrid/tree-source.hxx b/xsde/cxx/hybrid/tree-source.hxx new file mode 100644 index 0000000..7bd6b9e --- /dev/null +++ b/xsde/cxx/hybrid/tree-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/hybrid/tree-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_SOURCE_HXX +#define CXX_HYBRID_TREE_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + Void + generate_tree_source (Context&); + } +} + +#endif // CXX_HYBRID_TREE_SOURCE_HXX diff --git a/xsde/cxx/hybrid/tree-type-map.cxx b/xsde/cxx/hybrid/tree-type-map.cxx new file mode 100644 index 0000000..990d62e --- /dev/null +++ b/xsde/cxx/hybrid/tree-type-map.cxx @@ -0,0 +1,248 @@ +// file : xsde/cxx/hybrid/tree-type-map.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, SemanticGraph::Schema& root) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()) + { + } + + protected: + Context (Context& c) + : CXX::Context (c) + { + } + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, + TypeMap::Namespace* parser, + TypeMap::Namespace* serializer) + : Context (c), parser_ (parser), serializer_ (serializer) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + String const& xn (t.name ()); + String qn (fq_name (t)); + + if (parser_ != 0) + { + if (t.context ().get ("fixed")) + parser_->types_push_back (xn, qn); + else + parser_->types_push_back (xn, qn + L"*"); + } + + if (serializer_ != 0) + serializer_->types_push_back (xn, L"const " + qn + L"&"); + } + + private: + TypeMap::Namespace* parser_; + TypeMap::Namespace* serializer_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c, + String const* hxx_name, + TypeMap::Namespaces* parser_map, + TypeMap::Namespaces* serializer_map) + : Context (c), + hxx_name_ (hxx_name), + parser_map_ (parser_map), + serializer_map_ (serializer_map) + { + } + + virtual Void + traverse (Type& ns) + { + String include; + + if (hxx_name_ != 0) + include = process_include_path (*hxx_name_); + + String const& name (ns.name ()); + + if (parser_map_ != 0) + { + if (name) + parser_map_->push_back (TypeMap::Namespace (name)); + else + parser_map_->push_back ( + TypeMap::Namespace (TypeMap::Pattern ())); + + if (include) + parser_map_->back ().includes_push_back (include); + } + + if (serializer_map_ != 0) + { + if (name) + serializer_map_->push_back (TypeMap::Namespace (name)); + else + serializer_map_->push_back ( + TypeMap::Namespace (TypeMap::Pattern ())); + + if (include) + serializer_map_->back ().includes_push_back (include); + } + + GlobalType type (*this, + (parser_map_ ? &parser_map_->back () : 0), + (serializer_map_ ? &serializer_map_->back () : 0)); + + Traversal::Names names (type); + Namespace::names (ns, names); + } + + private: + String const* hxx_name_; + TypeMap::Namespaces* parser_map_; + TypeMap::Namespaces* serializer_map_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (SemanticGraph::Schema& root) + { + schema_set_.insert (&root); + } + + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + SemanticGraph::Context& sc (s.context ()); + + if (!sc.count ("cxx-hybrid-tree-type-map-seen")) + { + sc.set ("cxx-hybrid-tree-type-map-seen", true); + Traversal::Sources::traverse (sr); + sc.remove ("cxx-hybrid-tree-type-map-seen"); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (schema_set_.find (&s) == schema_set_.end ()) + { + schema_set_.insert (&s); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (schema_set_.find (&s) == schema_set_.end ()) + { + schema_set_.insert (&s); + Traversal::Imports::traverse (i); + } + } + + private: + Containers::Set schema_set_; + }; + } + + Void + generate_tree_type_map (CLI::Options const& ops, + XSDFrontend::SemanticGraph::Schema& tu, + String const& hxx_name, + TypeMap::Namespaces& parser_map, + TypeMap::Namespaces& serializer_map) + { + if (tu.names_begin ()->named ().name () != + L"http://www.w3.org/2001/XMLSchema") + { + Context ctx (ops, tu); + + // We don't want include in the included/imported/sources + // schema so split the traversal into two part. + // + Traversal::Schema schema; + Traversal::Schema used_schema; + Uses uses (tu); + + schema >> uses >> used_schema >> uses; + + Traversal::Names schema_names; + Namespace ns ( + ctx, &hxx_name, + (ops.value () ? &parser_map : 0), + (ops.value () ? &serializer_map : 0)); + + schema >> schema_names >> ns; + + Traversal::Names used_schema_names; + Namespace used_ns ( + ctx, 0, + (ops.value () ? &parser_map : 0), + (ops.value () ? &serializer_map : 0)); + + used_schema >> used_schema_names >> used_ns; + + // Some twisted schemas do recusive self-inclusion. + // + SemanticGraph::Context& tuc (tu.context ()); + + tuc.set ("cxx-hybrid-tree-type-map-seen", true); + schema.dispatch (tu); + tuc.remove ("cxx-hybrid-tree-type-map-seen"); + } + } + } +} diff --git a/xsde/cxx/hybrid/tree-type-map.hxx b/xsde/cxx/hybrid/tree-type-map.hxx new file mode 100644 index 0000000..e5ad7f5 --- /dev/null +++ b/xsde/cxx/hybrid/tree-type-map.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/hybrid/tree-type-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_TREE_TYPE_MAP_HXX +#define CXX_HYBRID_TREE_TYPE_MAP_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + Void + generate_tree_type_map (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + String const& hxx_name, + TypeMap::Namespaces& parser_type_map, + TypeMap::Namespaces& serializer_type_map); + } +} + +#endif // CXX_HYBRID_TREE_TYPE_MAP_HXX diff --git a/xsde/cxx/hybrid/validator.cxx b/xsde/cxx/hybrid/validator.cxx new file mode 100644 index 0000000..65dd3e2 --- /dev/null +++ b/xsde/cxx/hybrid/validator.cxx @@ -0,0 +1,584 @@ +// file : xsde/cxx/hybrid/validator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +#include + +using std::wcerr; + +namespace CXX +{ + namespace Hybrid + { + namespace + { + class ValidationContext: public Context + { + public: + ValidationContext (SemanticGraph::Schema& root, + CLI::Options const& options, + const WarningSet& disabled_warnings, + Boolean& valid_) + : Context (std::wcerr, root, options, 0, 0, 0), + disabled_warnings_ (disabled_warnings), + disabled_warnings_all_ (false), + valid (valid_), + subst_group_warning_issued (subst_group_warning_issued_), + subst_group_warning_issued_ (false) + { + } + + public: + Boolean + is_disabled (Char const* w) + { + return disabled_warnings_all_ || + disabled_warnings_.find (w) != disabled_warnings_.end (); + } + + public: + String + xpath (SemanticGraph::Nameable& n) + { + if (n.is_a ()) + return L""; // There is a bug if you see this. + + assert (n.named ()); + + SemanticGraph::Scope& scope (n.scope ()); + + if (scope.is_a ()) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + + protected: + ValidationContext (ValidationContext& c) + : Context (c), + disabled_warnings_ (c.disabled_warnings_), + disabled_warnings_all_ (c.disabled_warnings_all_), + valid (c.valid), + subst_group_warning_issued (c.subst_group_warning_issued) + { + } + + protected: + const WarningSet& disabled_warnings_; + Boolean disabled_warnings_all_; + Boolean& valid; + Boolean& subst_group_warning_issued; + Boolean subst_group_warning_issued_; + }; + + // + // + struct Traverser : Traversal::Schema, + Traversal::Complex, + Traversal::Type, + Traversal::Element, + ValidationContext + { + Traverser (ValidationContext& c) + : ValidationContext (c) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Schema; + + traverse (static_cast (c)); + + if (c.inherits_p ()) + { + SemanticGraph::Type& t (c.inherits ().base ()); + + if (t.named () && + types_.find ( + t.scope ().name () + L"#" + t.name ()) == types_.end ()) + { + // Don't worry about types that are in included/imported + // schemas. + // + Schema& s (dynamic_cast (t.scope ().scope ())); + + if (&s == &schema_root || sources_p (schema_root, s)) + { + valid = false; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": error: type '" << xpath (c) << "' inherits from " + << "yet undefined type '" << xpath (t) << "'" << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": info: '" << xpath (t) << "' is defined here" + << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: inheritance from a yet-undefined type is " + << "not supported" << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: re-arrange your schema and try again" + << endl; + } + } + } + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (t.named ()) + { + types_.insert (t.scope ().name () + L"#" + t.name ()); + } + } + + /* + virtual Void + traverse (SemanticGraph::Element& e) + { + if (is_disabled ("H001")) + return; + + if (e.substitutes_p () && + !options.value () && + !subst_group_warning_issued) + { + subst_group_warning_issued = true; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": warning H001: substitution groups are used but " + << "--generate-polymorphic was not specified" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: generated code may not be able to serialize " + << "some conforming instances" << endl; + } + } + */ + + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + }; + + // + // + struct AnonymousMember: protected ValidationContext + { + AnonymousMember (ValidationContext& c, Boolean& error_issued) + : ValidationContext (c), error_issued_ (error_issued) + { + } + + Boolean + traverse_common (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named () + && !t.is_a () + && !t.is_a ()) + { + if (!error_issued_) + { + valid = false; + error_issued_ = true; + + wcerr << t.file () + << ": error: anonymous types detected" + << endl; + + wcerr << t.file () + << ": info: " + << "anonymous types are not supported in this mapping" + << endl; + + wcerr << t.file () + << ": info: consider explicitly naming these types or " + << "remove the --preserve-anonymous option to " + << "automatically name them" + << endl; + + if (!options.value ()) + wcerr << t.file () + << ": info: use --show-anonymous option to see these " + << "types" << endl; + } + + return true; + } + + return false; + } + + private: + Boolean& error_issued_; + }; + + struct AnonymousElement: Traversal::Element, + AnonymousMember + { + AnonymousElement (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (traverse_common (e)) + { + if (options.value ()) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: element '" << xpath (e) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Element::traverse (e); + } + }; + + struct AnonymousAttribute: Traversal::Attribute, + AnonymousMember + { + AnonymousAttribute (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (Type& a) + { + if (traverse_common (a)) + { + if (options.value ()) + { + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: attribute '" << xpath (a) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Attribute::traverse (a); + } + }; + + struct AnonymousType : Traversal::Schema, + Traversal::Complex, + ValidationContext + { + AnonymousType (ValidationContext& c) + : ValidationContext (c), + error_issued_ (false), + element_ (c, error_issued_), + attribute_ (c, error_issued_) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + + *this >> contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> element_; + + *this >> names_attribute_ >> attribute_; + } + + private: + Boolean error_issued_; + + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + Traversal::Names names_; + + Traversal::Compositor compositor_; + AnonymousElement element_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + AnonymousAttribute attribute_; + Traversal::Names names_attribute_; + }; + + struct GlobalElementCount: Traversal::Element + { + GlobalElementCount (UnsignedLong& count) + : count_ (count) + { + } + + virtual Void + traverse (SemanticGraph::Element&) + { + count_++; + } + + private: + UnsignedLong& count_; + }; + + struct ParserValidation: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Traversal::Complex, + ValidationContext + + { + ParserValidation (ValidationContext& c) + : ValidationContext (c), issued_ (false) + { + contains_compositor_ >> *this; + *this >> contains_particle_ >> *this; + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (!issued_ && a.min () == 0) + { + valid = false; + issued_ = true; + + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: complex type '" << type (a).name () << "' " + << "contains optional all compositor" << endl; + + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: parser validation is required to handle this " + << "construct" << endl; + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (!issued_) + { + valid = false; + issued_ = true; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": error: complex type '" << type (c).name () << "' " + << "contains choice compositor" << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": error: parser validation is required to handle this " + << "construct" << endl; + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (!issued_) + { + if (s.max () != 1) + { + issued_ = true; + wcerr << s.file () << ":" << s.line () << ":" << s.column () + << ": error: complex type '" << type (s).name () << "' " + << "contains sequence of sequence compositor" << endl; + } + else if (s.min () == 0) + { + issued_ = true; + wcerr << s.file () << ":" << s.line () << ":" << s.column () + << ": error: complex type '" << type (s).name () << "' " + << "contains optional sequence compositor" << endl; + } + + if (issued_) + { + valid = false; + wcerr << s.file () << ":" << s.line () << ":" << s.column () + << ": error: parser validation is required to handle " + << "this construct" << endl; + } + } + + Traversal::Sequence::traverse (s); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (!issued_ && !restriction_p (c)) + contains_compositor (c, contains_compositor_); + } + + private: + SemanticGraph::Complex& + type (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + + private: + Boolean issued_; + + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + }; + } + + Boolean Validator:: + validate (CLI::Options const& options, + SemanticGraph::Schema& root, + SemanticGraph::Path const&, + const WarningSet& disabled_warnings) + { + Boolean valid (true); + ValidationContext ctx (root, options, disabled_warnings, valid); + + Boolean par (options.value ()); + Boolean ser (options.value ()); + Boolean agg (options.value ()); + + if (agg && !par && !ser && !ctx.is_disabled ("H002")) + { + wcerr << root.file () << ": warning H002: --generate-aggregate " << + "is specified but neither parsing nor serialization code is " << + "generated" << endl; + } + + // Issue a warning if there are more than one global element and we + // are generating aggregate types. + // + if (agg && + !options.value () && + !options.value () && + !options.value () && + !options.value () && + options.value ().empty () && + !ctx.is_disabled ("H003")) + { + UnsignedLong count (0); + + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + GlobalElementCount element (count); + + names >> element; + + schema.dispatch (root); + } + + if (count > 1) + { + wcerr << root.file () << ": warning H003: generating aggregate " << + "types for " << count << " global elements" << endl; + + wcerr << root.file () << ": info: use --root-element-* options " + << "to specify document root(s)" << endl; + } + } + + // Test for anonymout types. + // + { + AnonymousType traverser (ctx); + traverser.dispatch (root); + } + + // Test for constructs that require validation in parser. + // + if (valid && par && + (options.value () || + options.value ())) + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names names; + + schema >> schema_names >> ns >> names; + + ParserValidation type (ctx); + + names >> type; + + schema.dispatch (root); + } + + // Test the rest. + // + if (valid) + { + Traverser traverser (ctx); + traverser.dispatch (root); + } + + return valid; + } + } +} diff --git a/xsde/cxx/hybrid/validator.hxx b/xsde/cxx/hybrid/validator.hxx new file mode 100644 index 0000000..0fb6df6 --- /dev/null +++ b/xsde/cxx/hybrid/validator.hxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/hybrid/validator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_VALIDATOR_HXX +#define CXX_HYBRID_VALIDATOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + using namespace Cult::Types; + + class Validator + { + public: + Boolean + validate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& tu, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // CXX_HYBRID_VALIDATOR_HXX diff --git a/xsde/cxx/parser/attribute-validation-source.cxx b/xsde/cxx/parser/attribute-validation-source.cxx new file mode 100644 index 0000000..19c94fa --- /dev/null +++ b/xsde/cxx/parser/attribute-validation-source.cxx @@ -0,0 +1,468 @@ +// file : xsde/cxx/parser/attribute-validation-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Test: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + Test (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (a.name ()); + + if (a.qualified () && a.namespace_ ().name ()) + { + String const& ns (a.namespace_ ().name ()); + + os << "n == " << L << strlit (name) << " &&" << endl + << "ns == " << L << strlit (ns); + } + else + os << "n == " << L << strlit (name) << " && ns.empty ()"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& ns (a.definition_namespace ().name ()); + + for (SemanticGraph::AnyAttribute::NamespaceIterator + i (a.namespace_begin ()), e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "!n.empty ()"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!ns.empty () && ns != " << L << strlit (ns) << ")"; + } + else + os << "!ns.empty ()"; + } + else if (*i == L"##local") + { + os << "(ns.empty () && !n.empty ())"; + } + else if (*i == L"##targetNamespace") + { + os << "ns == " << L << strlit (ns); + } + else + { + os << "ns == " << L << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + } + }; + + // + // + struct PhaseOne : Traversal::Attribute, Context + { + PhaseOne (Context& c) + : Context (c), test_ (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& name (ename (a)); + String const& inst (emember (a)); + + SemanticGraph::Type& type (a.type ()); + String const& post (post_name (type)); + String const& ret (ret_type (type)); + + os << "if ("; + + test_.traverse (a); + + os << ")" + << "{" + << "if (this->" << inst << ")" + << "{" + << "this->" << inst << "->pre ();" + << endl; + + if (!exceptions) + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + os << "this->" << inst << "->_pre_impl (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_characters (s);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_post_impl ();" + << endl + << "if (!ctx.error_type ())" << endl; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << endl; + else + os << "{" + << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();" + << endl; + + if (!exceptions) + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + if (ret == L"void") + os << "this->" << name << " ();"; + else + os << "this->" << name << " (tmp);" + << "}"; + + os << "}"; + + if (!a.optional ()) + os << "static_cast< v_state_attr_* > (" << + "this->v_state_attr_stack_.top ())->" << name << " = true;"; + + os << "return true;" + << "}"; + } + + private: + Test test_; + }; + + + // + // + struct PhaseTwo : Traversal::AnyAttribute, Context + { + PhaseTwo (Context& c) + : Context (c), test_ (c) + { + } + + virtual Void + traverse (Type& a) + { + os << "if ("; + + test_.traverse (a); + + os << ")" << endl + << "{" + << "this->_any_attribute (ns, n, s);" + << "return true;" + << "}"; + } + + private: + Test test_; + }; + + + // + // + struct AttributeStateInit: Traversal::Attribute, Context + { + AttributeStateInit (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + if (!a.optional ()) + os << "as." << ename (a) << " = false;"; + } + }; + + + // + // + struct AttributeStateCheck: Traversal::Attribute, Context + { + AttributeStateCheck (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + if (!a.optional ()) + { + String ns (a.qualified () ? a.namespace_ ().name () : String ()); + + os << "if (!as." << ename (a) << ")" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_attribute);" + << "return;" + << "}"; + } + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + phase_one_ (c), + phase_two_ (c), + attribute_state_init_ (c), + attribute_state_check_ (c) + { + names_phase_one_ >> phase_one_; + names_phase_two_ >> phase_two_; + + names_attribute_state_init_ >> attribute_state_init_; + names_attribute_state_check_ >> attribute_state_check_; + } + + virtual Void + traverse (Type& c) + { + Boolean has_att (has (c)); + Boolean has_any (has (c)); + + if (!has_att && !has_any) + return; + + Boolean has_req_att (false); + if (has_att) + { + RequiredAttributeTest test (has_req_att); + Traversal::Names names_test (test); + names (c, names_test); + } + + String const& name (ename (c)); + + os <<"// Attribute validation and dispatch functions for " << + name << "." << endl + <<"//" << endl; + + if (has_att) + { + // _attribute_impl_phase_one + // + os << "bool " << name << "::" << endl + << "_attribute_impl_phase_one (const " << string_type << + "& ns," << endl + << "const " << string_type << "& n," << endl + << "const " << string_type << "& s)" << endl + << "{" + << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + names (c, names_phase_one_); + + // Nothing matched - call our base (extension) or return false + // if there is no base (or restriction (even from anyType)). + // + if (c.inherits_p () && + !c.inherits ().is_a ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << "return " << base << + "::_attribute_impl_phase_one (ns, n, s);"; + } + else + os << "return false;"; + + os << "}"; + } + + + if (has_any) + { + // _attribute_impl_phase_two + // + os << "bool " << name << "::" << endl + << "_attribute_impl_phase_two (const " << string_type << + "& ns," << endl + << "const " << string_type << "& n," << endl + << "const " << string_type << "& s)" + << "{"; + + names (c, names_phase_two_); + + // Nothing matched - call our base (extension) or return false + // if there is no base (or restriction (even from anyType)). + // + if (c.inherits_p () && + !c.inherits ().is_a ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << "return " << base << + "::_attribute_impl_phase_two (ns, n, s);"; + } + else + os << "return false;"; + + os << "}"; + } + + if (has_req_att) + { + // _pre_a_validate + // + os << "void " << name << "::" << endl + << "_pre_a_validate ()" + << "{"; + + if (exceptions) + os << "this->v_state_attr_stack_.push ();"; + else + os << "if (this->v_state_attr_stack_.push ())" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + + os << "v_state_attr_& as = *static_cast< v_state_attr_* > (" << + "this->v_state_attr_stack_.top ());" + << endl; + + names (c, names_attribute_state_init_); + + // Call our base (extension) last. + // + if (c.inherits_p () && + !c.inherits ().is_a ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_pre_a_validate ();"; + } + + os << "}"; + + + // _post_a_validate + // + os << "void " << name << "::" << endl + << "_post_a_validate ()" + << "{"; + + // Call our base (extension) first. + // + if (c.inherits_p () && + !c.inherits ().is_a ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_post_a_validate ();" + << endl; + + os << "if (this->_context ().error_type ())" << endl + << "return;" + << endl; + } + + os << "v_state_attr_& as = *static_cast< v_state_attr_* > (" << + "this->v_state_attr_stack_.top ());" + << endl; + + names (c, names_attribute_state_check_); + + os << endl + << "this->v_state_attr_stack_.pop ();" + << "}"; + } + } + + private: + PhaseOne phase_one_; + Traversal::Names names_phase_one_; + + PhaseTwo phase_two_; + Traversal::Names names_phase_two_; + + AttributeStateInit attribute_state_init_; + Traversal::Names names_attribute_state_init_; + + AttributeStateCheck attribute_state_check_; + Traversal::Names names_attribute_state_check_; + }; + } + + Void + generate_attribute_validation_source (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Complex complex (ctx); + + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/attribute-validation-source.hxx b/xsde/cxx/parser/attribute-validation-source.hxx new file mode 100644 index 0000000..70101da --- /dev/null +++ b/xsde/cxx/parser/attribute-validation-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/attribute-validation-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX +#define CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_attribute_validation_source (Context&); + } +} + +#endif // CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX diff --git a/xsde/cxx/parser/characters-validation-source.cxx b/xsde/cxx/parser/characters-validation-source.cxx new file mode 100644 index 0000000..c97a859 --- /dev/null +++ b/xsde/cxx/parser/characters-validation-source.cxx @@ -0,0 +1,76 @@ +// file : xsde/cxx/parser/characters-validation-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + if (!c.mixed ()) + return; + + String const& name (ename (c)); + + os <<"// Character validation functions for " << name << "." << endl + <<"//" << endl; + + // _characters_impl + // + os << "bool " << name << "::" << endl + << "_characters_impl (const " << string_type << "& s)" + << "{" + << "this->_any_characters (s);" + << "return true;" + << "}"; + } + }; + } + + Void + generate_characters_validation_source (Context& ctx) + { + //@@ Most of the time there is no mixed content type so + // we generate an empty namespace which looks ugly. Will + // need to implement smart namespace to handle this at + // some point. + // + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Complex complex (ctx); + + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} + diff --git a/xsde/cxx/parser/characters-validation-source.hxx b/xsde/cxx/parser/characters-validation-source.hxx new file mode 100644 index 0000000..5fab5cc --- /dev/null +++ b/xsde/cxx/parser/characters-validation-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/characters-validation-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX +#define CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_characters_validation_source (Context&); + } +} + +#endif // CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX diff --git a/xsde/cxx/parser/cli.hxx b/xsde/cxx/parser/cli.hxx new file mode 100644 index 0000000..485dd91 --- /dev/null +++ b/xsde/cxx/parser/cli.hxx @@ -0,0 +1,156 @@ +// file : xsde/cxx/parser/cli.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_CLI_HXX +#define CXX_PARSER_CLI_HXX + +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace CLI + { + using namespace Cult::Types; + + typedef Char const Key[]; + + extern Key type_map; + extern Key no_stl; + extern Key no_iostream; + extern Key no_exceptions; + extern Key no_long_long; + extern Key reuse_style_mixin; + extern Key reuse_style_none; + extern Key generate_inline; + extern Key suppress_validation; + extern Key generate_polymorphic; + extern Key runtime_polymorphic; + extern Key suppress_reset; + extern Key generate_noop_impl; + extern Key generate_print_impl; + extern Key generate_test_driver; + extern Key force_overwrite; + extern Key root_element_first; + extern Key root_element_last; + extern Key root_element; + extern Key generate_xml_schema; + extern Key extern_xml_schema; + extern Key output_dir; + extern Key skel_type_suffix; + extern Key skel_file_suffix; + extern Key impl_type_suffix; + extern Key impl_file_suffix; + extern Key namespace_map; + extern Key namespace_regex; + extern Key namespace_regex_trace; + extern Key reserved_name; + extern Key include_with_brackets; + extern Key include_prefix; + extern Key include_regex; + extern Key include_regex_trace; + extern Key guard_prefix; + extern Key hxx_suffix; + extern Key ixx_suffix; + extern Key cxx_suffix; + extern Key hxx_regex; + extern Key ixx_regex; + extern Key cxx_regex; + extern Key hxx_prologue; + extern Key ixx_prologue; + extern Key cxx_prologue; + extern Key prologue; + extern Key hxx_epilogue; + extern Key ixx_epilogue; + extern Key cxx_epilogue; + extern Key epilogue; + extern Key hxx_prologue_file; + extern Key ixx_prologue_file; + extern Key cxx_prologue_file; + extern Key prologue_file; + extern Key hxx_epilogue_file; + extern Key ixx_epilogue_file; + extern Key cxx_epilogue_file; + extern Key epilogue_file; + extern Key show_anonymous; + extern Key show_sloc; + extern Key proprietary_license; + + typedef Cult::CLI::Options< + type_map, Cult::Containers::Vector, + no_stl, Boolean, + no_iostream, Boolean, + no_exceptions, Boolean, + no_long_long, Boolean, + reuse_style_mixin, Boolean, + reuse_style_none, Boolean, + generate_inline, Boolean, + suppress_validation, Boolean, + generate_polymorphic, Boolean, + runtime_polymorphic, Boolean, + suppress_reset, Boolean, + generate_noop_impl, Boolean, + generate_print_impl, Boolean, + generate_test_driver, Boolean, + force_overwrite, Boolean, + root_element_first, Boolean, + root_element_last, Boolean, + root_element, NarrowString, + generate_xml_schema, Boolean, + extern_xml_schema, NarrowString, + output_dir, NarrowString, + skel_type_suffix, NarrowString, + skel_file_suffix, NarrowString, + impl_type_suffix, NarrowString, + impl_file_suffix, NarrowString, + namespace_map, Cult::Containers::Vector, + namespace_regex, Cult::Containers::Vector, + namespace_regex_trace, Boolean, + reserved_name, Cult::Containers::Vector, + include_with_brackets, Boolean, + include_prefix, NarrowString, + include_regex, Cult::Containers::Vector, + include_regex_trace, Boolean, + guard_prefix, NarrowString, + hxx_suffix, NarrowString, + ixx_suffix, NarrowString, + cxx_suffix, NarrowString, + hxx_regex, NarrowString, + ixx_regex, NarrowString, + cxx_regex, NarrowString, + hxx_prologue, Cult::Containers::Vector, + ixx_prologue, Cult::Containers::Vector, + cxx_prologue, Cult::Containers::Vector, + prologue, Cult::Containers::Vector, + hxx_epilogue, Cult::Containers::Vector, + ixx_epilogue, Cult::Containers::Vector, + cxx_epilogue, Cult::Containers::Vector, + epilogue, Cult::Containers::Vector, + hxx_prologue_file, NarrowString, + ixx_prologue_file, NarrowString, + cxx_prologue_file, NarrowString, + prologue_file, NarrowString, + hxx_epilogue_file, NarrowString, + ixx_epilogue_file, NarrowString, + cxx_epilogue_file, NarrowString, + epilogue_file, NarrowString, + show_anonymous, Boolean, + show_sloc, Boolean, + proprietary_license, Boolean + + > Options; + + struct OptionsSpec: Cult::CLI::OptionsSpec {}; + } + } +} + +#endif // CXX_PARSER_CLI_HXX diff --git a/xsde/cxx/parser/driver-source.cxx b/xsde/cxx/parser/driver-source.cxx new file mode 100644 index 0000000..7221741 --- /dev/null +++ b/xsde/cxx/parser/driver-source.cxx @@ -0,0 +1,1139 @@ +// file : xsde/cxx/parser/driver-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + typedef Cult::Containers::Set InstanceSet; + + // For base types we only want member's types, but not the + // base itself. + // + struct BaseType: Traversal::Complex, Context + { + BaseType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + }; + + struct ParserDef: Traversal::Type, + Traversal::List, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set) + : Context (c), map_ (map), set_ (set), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (t)); + map_[&t] = inst; + + os << fq_name (t, "p:impl") << " " << inst << ";"; + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (map_.find (&l) == map_.end ()) + { + String inst (find_instance_name (l)); + map_[&l] = inst; + + os << fq_name (l, "p:impl") << " " << inst << ";"; + + dispatch (l.argumented ().type ()); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (map_.find (&c) == map_.end ()) + { + String inst (find_instance_name (c)); + map_[&c] = inst; + + os << fq_name (c, "p:impl") << " " << inst << ";"; + + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + fund_type (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + fund_type (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fund_type (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fund_type (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fund_type (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + fund_type (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fund_type (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + fund_type (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fund_type (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + fund_type (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fund_type (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fund_type (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fund_type (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fund_type (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fund_type (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fund_type (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + fund_type (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + fund_type (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + fund_type (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + fund_type (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + fund_type (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + fund_type (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + fund_type (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + fund_type (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + fund_type (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + fund_type (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + fund_type (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + fund_type (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + fund_type (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + fund_type (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + fund_type (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + fund_type (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + fund_type (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + fund_type (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + fund_type (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + fund_type (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + fund_type (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + fund_type (t, "day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + fund_type (t, "month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + fund_type (t, "month_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + fund_type (t, "year"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + fund_type (t, "year_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + fund_type (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + fund_type (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + fund_type (t, "entities"); + } + + private: + virtual Void + fund_type (SemanticGraph::Type& t, String const& name) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (name)); + map_[&t] = inst; + + os << fq_name (t, "p:impl") << " " << inst << ";"; + } + } + + String + find_instance_name (String const& raw_name) + { + String base_name (escape (raw_name + L"_p")); + String name (base_name); + + for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i) + { + std::wostringstream os; + os << i; + name = base_name + os.str (); + } + + set_.insert (name); + return name; + } + + String + find_instance_name (SemanticGraph::Type& t) + { + return find_instance_name (t.name ()); + } + + TypeInstanceMap& map_; + InstanceSet& set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + // + // + struct ParticleArg: Traversal::Element, Context + { + ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&e.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct AttributeArg: Traversal::Attribute, Context + { + AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&a.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct ArgList : Traversal::Complex, + Traversal::List, + Context + { + ArgList (Context& c, TypeInstanceMap& map) + : Context (c), + map_ (map), + particle_ (c, map, first_), + attribute_ (c, map, first_), + first_ (true) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&l.argumented ().type ()]; + } + + private: + TypeInstanceMap& map_; + + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleArg particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + AttributeArg attribute_; + + Boolean first_; + }; + + struct ParserConnect: Traversal::List, + Traversal::Complex, + Context + { + ParserConnect (Context& c, TypeInstanceMap& map) + : Context (c), map_ (map), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (type_set_.find (&l) == type_set_.end ()) + { + os << map_[&l] << ".parsers (" << + map_[&l.argumented ().type ()] << ");" + << endl; + + type_set_.insert (&l); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (type_set_.find (&c) == type_set_.end ()) + { + if (has_members (c)) + { + os << map_[&c] << ".parsers ("; + + ArgList args (*this, map_); + args.dispatch (c); + + os << ");" + << endl; + } + + type_set_.insert (&c); + + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + private: + Boolean + has_members (SemanticGraph::Complex& c) + { + using SemanticGraph::Complex; + + if (has (c)) + return true; + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&b)) + return has_members (*cb); + + return b.is_a (); + } + + return false; + } + + private: + TypeInstanceMap& map_; + Cult::Containers::Set type_set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c, SemanticGraph::Element*& element) + : Context (c), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (options.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (String name = options.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + element_ = &e; // Cover root-element-last and no option. + } + + private: + SemanticGraph::Element*& element_; + }; + } + + Void + generate_driver_source (Context& ctx) + { + // Figure out the root element. Validator should have made sure + // it is unique. + // + SemanticGraph::Element* root (0); + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + RootElement global_element (ctx.options, root); + + schema >> schema_names >> ns >> ns_names >> global_element; + + schema.dispatch (ctx.schema_root); + } + + String xs (ctx.xs_ns_name ()); + std::wostream& os (ctx.os); + + InstanceSet set; + TypeInstanceMap map; + SemanticGraph::Type& root_type (root->type ()); + + set.insert ("doc_p"); + + if (ctx.options.value ()) + os << "#include " << endl; + else + os << "#include " << endl; + + os << endl + << "int" << endl + << "main (int argc, char* argv[])" + << "{" + << "const char* input;" + << endl + << "if (argc < 2)" + << "{" + << "input = \"STDIN\";"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"XML file not specified, reading " << + "from STDIN\\n\");"; + else + os << "std::cerr << \"XML file not specified, reading " << + "from STDIN\" << std::endl;"; + + os << "}" + << "else" << endl + << "input = argv[1];" + << endl; + + if (ctx.options.value ()) + { + os << "FILE* f = argc > 1 ? fopen (argv[1], \"rb\") : stdin;" + << endl + << "if (f == 0)" + << "{" + << "fprintf (stderr, \"%s: unable to open\\n\", input);" + << "return 1;" + << "}"; + } + + if (ctx.options.value () || + ctx.options.value ()) + os << "int r = 0;" + << endl; + + if (!ctx.options.value ()) + os << "try" + << "{"; + + os << "// Instantiate individual parsers." << endl + << "//" << endl; + + { + ParserDef def (ctx, map, set); + def.dispatch (root_type); + } + + os << endl + << "// Connect the parsers together." << endl + << "//" << endl; + + { + // @@ I can simply iterate over the map instead of traversing + // the tree all over again. + // + ParserConnect connect (ctx, map); + connect.dispatch (root_type); + } + + String const& root_p (map[&root_type]); + + os << "// Parse the XML document." << endl + << "//" << endl; + + if (ctx.options.value ()) + os << "bool io_error = false;"; + + if (ctx.options.value ()) + os << xs << "::parser_error e;" + << endl + << "do" + << "{"; + + if (root->namespace_().name ()) + os << xs << "::document_pimpl doc_p (" << endl + << root_p << "," << endl + << ctx.strlit (root->namespace_().name ()) << "," << endl + << ctx.strlit (root->name ()) << ");" + << endl; + else + os << xs << "::document_pimpl doc_p (" << root_p << ", " << + ctx.strlit (root->name ()) << ");" + << endl; + + if (ctx.options.value ()) + os << "if (e = doc_p._error ())" << endl + << "break;" + << endl; + + os << root_p << ".pre ();"; + + if (ctx.options.value ()) + os << endl + << "if (e = " << root_p << "._error ())" << endl + << "break;"; + + + if (ctx.options.value ()) + { + os << endl + << "char buf[4096];" + << endl + << "do" + << "{" + << "size_t s = fread (buf, 1, sizeof (buf), f);" + << endl + << "if (s != sizeof (buf) && ferror (f))" + << "{" + << "io_error = true;" + << "break;" + << "}"; + + if (ctx.options.value ()) + os << "doc_p.parse (buf, s, feof (f) != 0);" + << "e = doc_p._error ();" + << "}" + << "while (!e && !feof (f));" + << endl + << "if (io_error || e)" << endl + << "break;" + << endl; + else + os << "doc_p.parse (buf, s, feof (f) != 0);" + << "}" + << "while (!feof (f));" + << endl + << "if (!io_error)" + << "{"; + } + else + { + os << endl + << "if (argc < 2)" << endl + << "doc_p.parse (std::cin);" + << "else" << endl + << "doc_p.parse (argv[1]);" + << endl; + + if (ctx.options.value ()) + os << "if (e = doc_p._error ())" << endl + << "break;" + << endl; + } + + String const& ret (Context::ret_type (root_type)); + String const& post (Context::post_name (root_type)); + + if (ret == L"void") + { + os << root_p << "." << post << " ();"; + + if (ctx.options.value ()) + os << "e = " << root_p << "._error ();"; + } + else + { + os << Context::arg_type (root_type) << " v = " << + root_p << "." << post << " ());" + << endl; + + if (ctx.options.value ()) + os << "if (e = " << root_p << "._error ())" << endl + << "break;" + << endl; + + if (ctx.options.value ()) + { + PrintCall t (ctx, root->name (), "v"); + t.dispatch (root_type); + } + else + { + os << "// TODO" << endl + << "//" << endl; + } + + { + DeleteCall t (ctx, "v"); + t.dispatch (root_type); + } + } + + if (ctx.options.value ()) + os << "}" + << "while (false);" + << endl; + else if (ctx.options.value ()) + os << "}" // if (!io_error) + << "else" + << "{" + << "fprintf (stderr, \"%s: read failure\\n\", input);" + << "r = 1;" + << "}"; + + // Error handling. + // + + if (ctx.options.value ()) + { + os << "// Handle errors." << endl + << "//" << endl; + + if (ctx.options.value ()) + { + os << "if (io_error)" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s: read failure\\n\", input);"; + else + os << "std::cerr << input << \": read failure\" << std::endl;"; + + os << "r = 1;" + << "}" + << "else "; + } + + os << "if (e)" + << "{" + << "switch (e.type ())" + << "{" + << "case " << xs << "::parser_error::sys:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s: %s\\n\", input, e.sys_text ());"; + else + os << "std::cerr << input << \": \" << e.sys_text () << std::endl;"; + + os << "break;" + << "}" + << "case " << xs << "::parser_error::xml:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl + << "input, e.line (), e.column (), e.xml_text ());"; + else + os << "std::cerr << input << ':' << e.line () << ':'" << endl + << " << e.column () << \": \" << e.xml_text () << std::endl;"; + + os << "break;" + << "}"; + + if (!ctx.options.value ()) + { + os << "case " << xs << "::parser_error::schema:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl + << "input, e.line (), e.column (), e.schema_text ());"; + else + os << "std::cerr << input << ':' << e.line () << ':'" << endl + << " << e.column () << \": \" << e.schema_text () << std::endl;"; + + os << "break;" + << "}"; + } + + os << "case " << xs << "::parser_error::app:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s:%lu:%lu: application error %d\\n\"," << endl + << "input, e.line (), e.column (), e.app_code ());"; + else + os << "std::cerr << input << ':' << e.line () << ':'" << endl + << " << e.column () << \": application error \"" << endl + << " << e.app_code () << std::endl;"; + + os << "break;" + << "}" + << "default:" + << "{" + << "break;" + << "}" + << "}" //switch + << "r = 1;" + << "}"; // else if (e) + } + else + { + os << "}" // try + << "catch (const " << xs << "::parser_exception& e)" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl + << "input, e.line (), e.column (), e.text ());" + << "r = 1;"; + else + os << "std::cerr << input << ':' << e.line () << ':'" << endl + << " << e.column () << \": \" << e.text () << std::endl;" + << "return 1;"; + + os << "}"; + + if (!ctx.options.value ()) + { + os << "catch (const std::ios_base::failure&)" + << "{" + << "std::cerr << input << \": unable to open or " << + "read failure\" << std::endl;" + << "return 1;" + << "}"; + } + } + + if (ctx.options.value ()) + os << "if (argc > 1)" << endl + << "fclose (f);" + << endl; + + if (ctx.options.value () || + ctx.options.value ()) + os << "return r;"; + else + os << "return 0;"; + + os << "}"; // main + } + } +} diff --git a/xsde/cxx/parser/driver-source.hxx b/xsde/cxx/parser/driver-source.hxx new file mode 100644 index 0000000..f829d41 --- /dev/null +++ b/xsde/cxx/parser/driver-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/driver-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_DRIVER_SOURCE_HXX +#define CXX_PARSER_DRIVER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_driver_source (Context&); + } +} + +#endif // CXX_PARSER_DRIVER_SOURCE_HXX diff --git a/xsde/cxx/parser/element-validation-source.cxx b/xsde/cxx/parser/element-validation-source.cxx new file mode 100644 index 0000000..e5d3589 --- /dev/null +++ b/xsde/cxx/parser/element-validation-source.cxx @@ -0,0 +1,2120 @@ +// file : xsde/cxx/parser/element-validation-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + typedef Cult::Containers::Vector Particles; + + // Find particle that can be absent. + // + struct OptionalParticleTest: Traversal::Choice + { + OptionalParticleTest (SemanticGraph::Particle*& result) + : is_optional_ (optional_), result_ (result) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Choice; + result_ = 0; + optional_ = false; + + for (Choice::ContainsIterator i (c.contains_begin ()); + result_ == 0 && i != c.contains_end (); + ++i) + { + is_optional_.dispatch (i->particle ()); + if (optional_) + result_ = &i->particle (); + } + } + + struct IsOptional: Traversal::Choice, + Traversal::Sequence, + Traversal::Element, + Traversal::Any + { + IsOptional (Boolean& r) + : r_ (r) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (!r_ && c.min () == 0) + r_ = true; + + // We need at least one particle to be optional for the whole + // choice to be optional. + // + using SemanticGraph::Choice; + + for (Choice::ContainsIterator i (c.contains_begin ()); + !r_ && i != c.contains_end (); + ++i) + { + dispatch (i->particle ()); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (!r_ && s.min () == 0) + r_ = true; + + // We need all particles to be optional for the whole sequence + // to be optional. + // + using SemanticGraph::Sequence; + + for (Sequence::ContainsIterator i (s.contains_begin ()); + !r_ && i != s.contains_end (); + ++i) + { + Boolean r (false); + IsOptional test (r); + test.dispatch (i->particle ()); + if (!r) + return; + } + + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!r_ && e.min () == 0) + r_ = true; + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (!r_ && a.min () == 0) + r_ = true; + } + + private: + Boolean& r_; + }; + + private: + Boolean optional_; + IsOptional is_optional_; + SemanticGraph::Particle*& result_; + }; + + // + // + Void + choice_arm_call (SemanticGraph::Particle* p, + SemanticGraph::Choice* c, + Context* ctx) + { + using SemanticGraph::Choice; + + ctx->os << "this->" << Context::earm (*c) << " (" << + Context::etag (*p) << ");"; + + if ((c = dynamic_cast (p))) + { + OptionalParticleTest test (p); + test.traverse (*c); + + if (p) + choice_arm_call (p, c, ctx); + } + } + + // + // + struct ParticleTest: Traversal::Compositor, + Traversal::Element, + Traversal::Any, + Context + { + ParticleTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& name (e.name ()); + Boolean subst (poly_code && e.global ()); + + if (subst) + os << "("; + + if (e.qualified () && e.namespace_ ().name ()) + { + String const& ns (e.namespace_ ().name ()); + + os << "n == " << L << strlit (name) << " &&" << endl + << "ns == " << L << strlit (ns); + } + else + os << "n == " << L << strlit (name) << " && ns.empty ()"; + + + // Only a globally-defined element can be a subst-group root. + // + if (subst) + { + String root_id (e.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + root_id += L' '; + root_id += ns; + } + + os << ") ||" << endl + << "::xsde::cxx::parser::substitution_map_instance ()" << + ".check (" << endl + << "ns, n, " << strlit (root_id) << ", t)"; + } + + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& ns (a.definition_namespace ().name ()); + + // Note that we need to make sure the "flush" element (both name + // and namespace are empty) does not match any compositor. + // + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "!n.empty ()"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!ns.empty () && ns != " << L << strlit (ns) << ")"; + } + else + os << "!ns.empty ()"; + } + else if (*i == L"##local") + { + os << "(ns.empty () && !n.empty ())"; + } + else if (*i == L"##targetNamespace") + { + os << "ns == " << L << strlit (ns); + } + else + { + os << "ns == " << L << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + // This compositor should already have been tested for + // triviality (empty). + // + Particles const& p (c.context ().get ("p:prefixes")); + + Boolean paren (p.size () != 1); + + for (Particles::ConstIterator i (p.begin ()), e (p.end ()); + i != e;) + { + if (paren) + os << "("; + + dispatch (**i); + + if (paren) + os << ")"; + + if (++i != e) + os << " ||" << endl; + } + } + }; + + + // Generates particle namespace-name pair. Used to generate + // the _expected_element call. + // + struct ParticleName: Traversal::Compositor, + Traversal::Element, + Traversal::Any, + Context + { + ParticleName (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String ns (e.qualified () ? e.namespace_ ().name () : String ()); + + os << L << strlit (ns) << ", " << L << strlit (e.name ()); + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& ns (*a.namespace_begin ()); + + os << L << strlit (ns) << ", " << L << "\"*\""; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + Particles const& p (c.context ().get ("p:prefixes")); + + dispatch (**p.begin ()); + } + }; + + + // Common base for the ParticleIn{All, Choice, Sequence} treversers. + // + struct ParticleInCompositor: protected Context + { + protected: + ParticleInCompositor (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type), particle_test_ (c) + { + } + + + // Generate sub-parser setup code as well as the pre/post calls. + // + Void + pre_post_calls (SemanticGraph::Particle& p) + { + using SemanticGraph::Element; + using SemanticGraph::Complex; + + if (Element* e = dynamic_cast (&p)) + { + SemanticGraph::Type& type (e->type ()); + Boolean poly (poly_code && !anonymous (type)); + + String const& name (ename (*e)); + String inst (poly ? emember_cache (*e) : emember (*e)); + + String def_parser, map; + + if (poly) + { + def_parser = emember (*e); + map = emember_map (*e); + } + + if (poly) + { + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + String fq_type (fq_name (type)); + + os << "if (t == 0 && this->" << def_parser << " != 0)" << endl + << "this->" << inst << " = this->" << def_parser << ";" + << "else" + << "{" + << "const char* ts = " << fq_type << "::_static_type ();" + << endl + << "if (t == 0)" << endl + << "t = ts;" + << endl + << "if (this->" << def_parser << " != 0 && " << + "strcmp (t, ts) == 0)" << endl + << "this->" << inst << " = this->" << def_parser << ";" + << "else" + << "{"; + + // Check that the types are related by inheritance. + // + os << "if (t != ts &&" << endl + << "!::xsde::cxx::parser::validating::" << + "inheritance_map_instance ().check (t, ts))" + << "{" + << "ctx.schema_error (::xsde::cxx::schema_error::not_derived);" + << "return;" + << "}"; + + os << "if (this->" << map << " != 0)" << endl + << "this->" << inst << " = " << cast << "< " << + fq_type << "* > (" << endl + << "this->" << map << "->find (t));" + << "else" << endl + << "this->" << inst << " = 0;" + << "}" + << "}"; + } + + String const& post (post_name (type)); + + os << "if (this->" << inst << ")" + << "{" + << "this->" << inst << "->pre ();"; + + if (!exceptions) + { + // Note that after pre() we need to check both parser and + // context error states because of the recursive parsing. + // + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl; + } + + os << "this->" << inst << "->_pre_impl (ctx);" + << "}" + << "else" << endl + << "ctx.current_.depth_++;" // Ignoring document fragment. + << endl + << "}" + << "else" // start + << "{" + << "if (this->" << inst << ")" + << "{"; + + String const& ret (ret_type (type)); + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();"; + else + os << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();"; + + if (!exceptions) + { + // Note that after post() we need to check both parser and + // context error states because of the recursive parsing. + // + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl; + } + + if (ret == L"void") + os << "this->" << name << " ();"; + else + os << "this->" << name << " (tmp);"; + + os << "}"; + } + else + { + os << "ctx.current_.any_ = true;" + << "ctx.current_.depth_++;" + << endl + << "this->_start_any_element (ns, n" << + (poly_runtime ? (poly_code ? ", t" : ", 0") : "") << ");" + << "}" + << "else" // start + << "{" + << "this->_end_any_element (ns, n);"; + } + } + + + protected: + SemanticGraph::Complex& type_; + ParticleTest particle_test_; + }; + + + + // The 'all' compositor can only contain elements with min={0,1}, max=1. + // + struct ParticleInAll: Traversal::Element, + ParticleInCompositor + { + ParticleInAll (Context& c, SemanticGraph::Complex& type) + : ParticleInCompositor (c, type) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong state (e.context ().get ("p:state")); + + SemanticGraph::Compositor& c ( + e.contained_particle ().compositor ()); + + if (state != 0) + os << "else "; + + os << "if ("; + + particle_test_.traverse (e); + + os << ")" + << "{" + << "if (count[" << state << "UL] == 0)" + << "{" + << "if (start)" + << "{"; + + if (c.min () == 0) + { + // Make the call to _present if we haven't seen any + // elements yet. + // + UnsignedLong state_count ( + c.context().get ("p:state-count")); + + if (state_count > 1) + { + os << "if ("; + + Boolean sub (false); + + for (UnsignedLong i (0); i < state_count; ++i) + { + if (i == state) + continue; + + if (sub) + os << " &&" << endl; + else + sub = true; + + os << "count[" << i << "UL] == 0"; + } + + os << ")" << endl + << "this->" << epresent (c) << " ();" + << endl; + } + } + + pre_post_calls (e); + + os << "count[" << state << "UL] = 1;" + << "}" + << "}" + << "else" // count != 0 + << "{" + << "assert (start);" // Assuming well-formed XML. + + // Since there is never more content after 'all', we could have + // as well thrown here. But instead we will let the code in + // start_element handle this along with other unexpected + // elements. + // + << "state = ~0UL;" + << "}" + << "}"; + } + }; + + + // + // + struct ParticleInChoice: Traversal::Particle, + Traversal::Compositor, + ParticleInCompositor + { + ParticleInChoice (Context& c, SemanticGraph::Complex& type) + : ParticleInCompositor (c, type), particle_name_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Particle& p) + { + using SemanticGraph::Element; + + UnsignedLong state (p.context ().get ("p:state")); + + UnsignedLong min (p.min ()), max (p.max ()); + + os << "case " << state << "UL:" << endl + << "{"; + + if (max != 1) // We don't need the test if max == 1. + { + os << "if ("; + + particle_test_.dispatch (p); + + os << ")" + << "{"; + } + + os << "if (start)" + << "{"; + + pre_post_calls (p); + + switch (max) + { + case 0: + { + os << "count++;"; + break; + } + case 1: + { + // We do not need to increment count because min <= max and + // we do not generate min check for min <= 1 (see below). + // + os << "state = ~0UL;"; + break; + } + default: + { + os << "if (++count == " << max << "UL)" << endl + << "state = ~0UL;"; + } + }; + + os << "}"; // start + + // We've already moved to the final state if max == 1. + // + if (max != 1) + { + os << "}" + << "else" + << "{" + << "assert (start);"; // Assuming well-formed XML + + // Check if min cardinality requirements have been met. Since + // count is always >= 1, don't generate dead code if min <= 1. + // + if (min > 1) + { + os << "if (count < " << min << "UL)" << endl + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);"; + + /* + << "this->_expected_element (" << endl; + particle_name_.dispatch (p); + os << "," << endl + << "ns, n);"; + */ + } + + + os << "state = ~0UL;" + << "}"; + } + + os << "break;" + << "}"; // case + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + using SemanticGraph::Choice; + using SemanticGraph::Sequence; + using SemanticGraph::Compositor; + + Boolean choice (c.is_a ()); + SemanticGraph::Context& cc (c.context ()); + + UnsignedLong max (c.max ()); + UnsignedLong min (cc.get ("p:effective-min")); + UnsignedLong n (cc.get ("p:comp-number")); + UnsignedLong state (cc.get ("p:state")); + + String func (choice ? "choice_" : "sequence_"); + + os << "case " << state << "UL:" << endl + << "{" + << "unsigned long s = ~0UL;" + << endl; + + Boolean first (true); + + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () && !cc.count ("p:comp-number")) + continue; // Empty compositor. + + if (!p.context ().count ("p:prefix")) + break; + + UnsignedLong state (p.context ().get ("p:state")); + + if (first) + first = false; + else + os << "else "; + + os << "if ("; + + particle_test_.dispatch (p); + + os << ")" << endl + << "s = " << state << "UL;"; + } + + if (!choice) + { + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + Choice* pc = dynamic_cast (&ci->particle ()); + + if (pc && pc->min () == 1 && pc->max () == 1 && + pc->context ().get ("p:effective-min") == 0) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + { + UnsignedLong state ( + pc->context ().get ("p:state")); + + os << endl + << "if (s > " << state << "UL)" << endl + << "{"; + choice_arm_call (p, pc, this); + os << "}"; + } + } + } + } + + // This compositor. + // + os << endl + << "if (s != ~0UL)" + << "{" + << "assert (start);"; // End is handled by the sub-machine. + + switch (max) + { + case 0: + { + os << "count++;"; + break; + } + case 1: + { + // We do not need to increment count because min <= max and + // we do not generate min check for min <= 1 (see below). + // + os << "state = ~0UL;"; + break; + } + default: + { + os << "if (++count == " << max << "UL)" << endl + << "state = ~0UL;"; + } + }; + + // Delegate to the sub-machine and call _arm, _present, or _next + // if necessary. + // + + os << endl + << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_& vd = vs.data[vs.size++];" // push + << endl + << "vd.func = &" << ename (type_) << "::" << func << n << ";" + << "vd.state = s;" + << "vd.count = 0;" + << endl; + + if (Choice* pc = dynamic_cast (&c)) + { + os << "this->" << earm (*pc) << " (static_cast< " << + earm_tag (*pc) << " > (s));"; + } + else + { + Sequence& s (dynamic_cast (c)); + + if (max != 1) + os << "this->" << enext (s) << " ();"; + else if (c.min () == 0) + os << "this->" << epresent (s) << " ();"; + } + + os << "this->" << func << n << " (vd.state, vd.count, ns, n, " << + (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);" + << "}"; + + + // Not this compositor. We've elready moved to the final state + // if max == 1. + // + if (max != 1) + { + os << "else" + << "{" + << "assert (start);"; // Assuming well-formed XML + + // Check if min cardinality requirements have been met. Since + // count is always >= 1, don't generate dead code if min <= 1. + // + if (min > 1) + { + os << "if (count < " << min << "UL)" << endl + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);"; + + /* + << "this->_expected_element (" << endl; + particle_name_.dispatch (c); + os << "," << endl + << "ns, n);"; + */ + } + + os << "state = ~0UL;" + << "}"; + } + + os << "break;" + << "}"; // case + } + + private: + ParticleName particle_name_; + }; + + + // + // + struct ParticleInSequence: Traversal::Particle, + Traversal::Compositor, + ParticleInCompositor + { + ParticleInSequence (Context& c, + UnsignedLong state, + UnsignedLong next_state, + SemanticGraph::Complex& type) + : ParticleInCompositor (c, type), + state_ (state), particle_name_ (c) + { + // next_state == 0 indicates the terminal state (~0UL). + // + if (next_state != 0) + { + std::wostringstream ostr; + ostr << next_state; + next_state_ = ostr.str (); + } + else + next_state_ = L"~0"; + } + + virtual Void + traverse (SemanticGraph::Particle& p) + { + UnsignedLong min (p.min ()), max (p.max ()); + + os << "case " << state_ << "UL:" << endl + << "{" + << "if ("; + + particle_test_.dispatch (p); + + os << ")" + << "{"; + + // This element. + // + + os << "if (start)" + << "{"; + + pre_post_calls (p); + + switch (max) + { + case 0: + { + os << "count++;"; + break; + } + case 1: + { + os << "count = 0;" + << "state = " << next_state_ << "UL;"; + break; + } + default: + { + os << "if (++count == " << max << "UL)" + << "{" + << "count = 0;" + << "state = " << next_state_ << "UL;" + << "}"; + } + }; + + os << "}" // start + << "break;" + << "}"; + + // Not this element. + // + + os << "else" + << "{" + << "assert (start);"; // Assuming well-formed XML. + + // Check if min cardinality requirements have been met. Since + // count is always >= 0, don't generate dead code if min == 0. + // + if (min != 0) + { + os << "if (count < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "break;" + << "}"; + + /* + << "this->_expected_element (" << endl; + particle_name_.dispatch (p); + os << "," << endl + << "ns, n);"; + */ + } + + os << "count = 0;" + << "state = " << next_state_ << "UL;" + << "// Fall through." << endl + << "}" // else + << "}"; // case + } + + virtual Void + traverse (SemanticGraph::Compositor& c) + { + using SemanticGraph::Choice; + using SemanticGraph::Sequence; + using SemanticGraph::Compositor; + + Boolean choice (c.is_a ()); + SemanticGraph::Context& cc (c.context ()); + + UnsignedLong max (c.max ()); + UnsignedLong min (cc.get ("p:effective-min")); + UnsignedLong n (cc.get ("p:comp-number")); + + String func (choice ? "choice_" : "sequence_"); + + os << "case " << state_ << "UL:" << endl + << "{" + << "unsigned long s = ~0UL;" + << endl; + + Boolean first (true); + + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () && !cc.count ("p:comp-number")) + continue; // Empty compositor. + + if (!p.context ().count ("p:prefix")) + break; + + UnsignedLong state (p.context ().get ("p:state")); + + if (first) + first = false; + else + os << "else "; + + os << "if ("; + + particle_test_.dispatch (p); + + os << ")" << endl + << "s = " << state << "UL;"; + } + + if (!choice) + { + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + Choice* pc = dynamic_cast (&ci->particle ()); + + if (pc && pc->min () == 1 && pc->max () == 1 && + pc->context ().get ("p:effective-min") == 0) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + { + UnsignedLong state ( + pc->context ().get ("p:state")); + + os << endl + << "if (s > " << state << "UL)" << endl + << "{"; + choice_arm_call (p, pc, this); + os << "}"; + } + } + } + } + + // This element. + // + + os << endl + << "if (s != ~0UL)" + << "{" + << "assert (start);"; // End is handled by the sub-machine. + + switch (max) + { + case 0: + { + os << "count++;" + << endl; + break; + } + case 1: + { + os << "count = 0;" + << "state = " << next_state_ << "UL;" + << endl; + break; + } + default: + { + os << "if (++count == " << max << "UL)" + << "{" + << "count = 0;" + << "state = " << next_state_ << "UL;" + << "}"; + } + }; + + // Delegate to the sub-machine and call _arm, _present, or _next + // if necessary. + // + + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_& vd = vs.data[vs.size++];" // push + << endl + << "vd.func = &" << ename (type_) << "::" << func << n << ";" + << "vd.state = s;" + << "vd.count = 0;" + << endl; + + Choice* pc = dynamic_cast (&c); + + if (pc) + { + os << "this->" << earm (*pc) << " (static_cast< " << + earm_tag (*pc) << " > (s));"; + } + else + { + Sequence& s (dynamic_cast (c)); + + if (max != 1) + os << "this->" << enext (s) << " ();"; + else if (c.min () == 0) + os << "this->" << epresent (s) << " ();"; + } + + os << "this->" << func << n << " (vd.state, vd.count, ns, n, " << + (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);" + << "break;" + << "}"; + + // Not this compositor. + // + + os << "else" + << "{" + << "assert (start);"; // Assuming well-formed XML + + if (pc && c.min () == 1 && min == 0 && max == 1) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + choice_arm_call (p, pc, this); + } + + // Check if min cardinality requirements have been met. Since + // count is always >= 0, don't generate dead code if min == 0. + // + if (min != 0) + { + os << "if (count < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "break;" + << "}"; + } + + os << "count = 0;" + << "state = " << next_state_ << "UL;" + << "// Fall through." << endl + << "}" // else + << "}"; // case + } + + private: + UnsignedLong state_; + String next_state_; + + ParticleName particle_name_; + }; + + + // + // + struct ParticleFunction: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleFunction (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type) + { + *this >> contains_particle_ >> *this; + } + + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context().count ("p:comp-number")) // Empty compositor. + return; + + using SemanticGraph::Element; + using SemanticGraph::Compositor; + + os << "void " << ename (type_) << "::" << endl + << "all_0 (unsigned long& state," << endl + << "unsigned char* count," << endl + << "const " << string_type << "& ns," << endl + << "const " << string_type << "& n," << endl; + + if (poly_runtime) + os << "const char*" << (poly_code ? " t" : "") << "," << endl; + + os << "bool start)" + << "{"; + + if (poly_code) + os << "XSDE_UNUSED (t);" + << endl; + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + for (Compositor::ContainsIterator ci (a.contains_begin ()), + ce (a.contains_end ()); ci != ce; ++ci) + { + ParticleInAll t (*this, type_); + t.dispatch (ci->particle ()); + } + + // Handle the flush. + // + os << "else if (n.empty () && ns.empty ())" + << "{"; + + for (Compositor::ContainsIterator ci (a.contains_begin ()), + ce (a.contains_end ()); ci != ce; ++ci) + { + if (ci->min () == 0) + continue; + + Element& e (dynamic_cast (ci->particle ())); + String ns (e.qualified () ? e.namespace_ ().name () : String ()); + UnsignedLong state (e.context ().get ("p:state")); + + os << "if (count[" << state << "UL] == 0)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + + /* + << "this->_expected_element (" << endl + << L << "\"" << ns << "\", " << + L << "\"" << e.name () << "\");"; + */ + } + + // Error handling code relies on the fact that there is no + // code after the if-else block. + // + os << "state = ~0UL;" + << "}" + << "else" << endl + << "state = ~0UL;" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Compositor; + + SemanticGraph::Context& cc (c.context ()); + + if (!cc.count ("p:comp-number")) // Empty compositor. + return; + + UnsignedLong n (cc.get ("p:comp-number")); + + os << "void " << ename (type_) << "::" << endl + << "choice_" << n << " (unsigned long& state," << endl + << "unsigned long& count," << endl + << "const " << string_type << "& ns," << endl + << "const " << string_type << "& n," << endl; + + if (poly_runtime) + os << "const char*" << (poly_code ? " t" : "") << "," << endl; + + os << "bool start)" + << "{" + << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + os << "XSDE_UNUSED (count);" + << "XSDE_UNUSED (ns);" + << "XSDE_UNUSED (n);" + << "XSDE_UNUSED (ctx);"; + + if (poly_code) + os << "XSDE_UNUSED (t);"; + + + os << endl + << "switch (state)" + << "{"; + + for (Compositor::ContainsIterator ci (c.contains_begin ()), + ce (c.contains_end ()); ci != ce; ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () && !p.context().count ("p:comp-number")) + continue; // Empty compositor. + + ParticleInChoice t (*this, type_); + t.dispatch (p); + } + + // Error handling code relies on the fact that there is no + // code after the switch statement. + // + os << "}" // switch + << "}"; + + + // Generate nested compositor functions. + // + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (!s.context().count ("p:comp-number")) // Empty compositor. + return; + + using SemanticGraph::Compositor; + + UnsignedLong n (s.context ().get ("p:comp-number")); + + os << "void " << ename (type_) << "::" << endl + << "sequence_" << n << " (unsigned long& state," << endl + << "unsigned long& count," << endl + << "const " << string_type << "& ns," << endl + << "const " << string_type << "& n," << endl; + + if (poly_runtime) + os << "const char*" << (poly_code ? " t" : "") << "," << endl; + + os << "bool start)" + << "{" + << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + if (poly_code) + os << "XSDE_UNUSED (t);"; + + os << "XSDE_UNUSED (ctx);" + << endl; + + os << "switch (state)" + << "{"; + + UnsignedLong state (0); + + for (Compositor::ContainsIterator ci (s.contains_begin ()), + ce (s.contains_end ()); ci != ce;) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () && !p.context().count ("p:comp-number")) + { + // Empty compositor. + // + ++ci; + continue; + } + + // Find the next state. + // + do + ++ci; + while (ci != ce && + ci->particle ().is_a () && + !ci->particle ().context().count ("p:comp-number")); + + UnsignedLong next (ci == ce ? 0 : state + 1); + + ParticleInSequence t (*this, state++, next, type_); + t.dispatch (p); + } + + // Error handling code relies on the fact that there is no + // code after the switch statement. + // + os << "case ~0UL:" << endl + << "break;" + << "}" // switch + << "}"; + + // Generate nested compositor functions. + // + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Complex& type_; + Traversal::ContainsParticle contains_particle_; + }; + + // + // + struct CompositorPre: Traversal::All, + Traversal::Compositor, + Context + { + CompositorPre (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // Clear the counts and push the initial state. + // + os << "v_all_count_.push ();" + << endl; + + SemanticGraph::Compositor& c (a); + traverse (c); + } + + virtual Void + traverse (SemanticGraph::Compositor&) // Choice and sequence. + { + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_& vd = vs.data[vs.size++];" // push + << endl + << "vd.func = 0;" + << "vd.state = 0;" + << "vd.count = 0;"; + } + + private: + SemanticGraph::Complex& type_; + }; + + + // + // + struct CompositorStartElement: Traversal::All, + Traversal::Compositor, + Context + { + CompositorStartElement (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type), + particle_test_ (c), particle_name_ (c) + { + } + + virtual Void + traverse (SemanticGraph::All&) + { + // The 'all' state machine reaches the final state only + // on an unknown element, in which case we won't get here + // again (it would be a validation error). Note that 'all' + // compositor cannot contain nested compositors so we don't + // need to re-set vd. + // + os << "all_0 (vd->state, v_all_count_.top (), ns, n, " << + (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);" + << endl + << "if (vd->state != ~0UL || ctx.error_type ())" << endl + << "vd->count++;" + << "else" << endl + << "return false;" // Let our parent handle this. + << endl; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) // Choice and sequence. + { + using SemanticGraph::Choice; + using SemanticGraph::Sequence; + using SemanticGraph::Compositor; + + Boolean choice (c.is_a ()); + SemanticGraph::Context& cc (c.context ()); + + UnsignedLong max (c.max ()); + UnsignedLong min (cc.get ("p:effective-min")); + UnsignedLong n (cc.get ("p:comp-number")); + + String func (choice ? "choice_" : "sequence_"); + + // Invoke the current state machine. If it reaches its + // terminal state, pop it and invoke the next one until + // we reach the top, which requires special handling. + // + os << "while (vd->func != 0)" + << "{" + << "(this->*vd->func) (vd->state, vd->count, ns, n, " << + (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);" + << endl + << "vd = vs.data + (vs.size - 1);" // re-acquire + << endl + << "if (vd->state == ~0UL && !ctx.error_type ())" << endl + << "vd = vs.data + (--vs.size - 1);" // pop + << "else" << endl + << "break;" + << "}"; + + + // Check if we got to the top. This code is pretty much the + // same as the one found in ParticleInSequence. + // + os << "if (vd->func == 0)" + << "{" + << "if (vd->state != ~0UL)" + << "{" + << "unsigned long s = ~0UL;" + << endl; + + Boolean first (true); + + // Note that we don't need to worry about the compositor + // being empty - this case is handled by our caller. + // + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () && !cc.count ("p:comp-number")) + continue; // Empty compositor. + + if (!p.context ().count ("p:prefix")) + break; + + UnsignedLong state (p.context ().get ("p:state")); + + if (first) + first = false; + else + os << "else "; + + os << "if ("; + + particle_test_.dispatch (p); + + os << ")" << endl + << "s = " << state << "UL;"; + } + + if (!choice) + { + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + Choice* pc = dynamic_cast (&ci->particle ()); + + if (pc && pc->min () == 1 && pc->max () == 1 && + pc->context ().get ("p:effective-min") == 0) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + { + UnsignedLong state ( + pc->context ().get ("p:state")); + + os << endl + << "if (s > " << state << "UL)" << endl + << "{"; + choice_arm_call (p, pc, this); + os << "}"; + } + } + } + } + + os << endl + << "if (s != ~0UL)" + << "{"; + + // This element is a prefix of the root compositor. + // + + switch (max) + { + case 0: + { + os << "vd->count++;"; + break; + } + case 1: + { + os << "vd->count++;" + << "vd->state = ~0UL;"; + break; + } + default: + { + os << "if (++vd->count == " << max << "UL)" << endl + << "vd->state = ~0UL;"; + } + }; + + // Delegate to the sub-machine and call _arm, _present, or _next + // if necessary. + // + + os << endl + << "vd = vs.data + vs.size++;" // push + << "vd->func = &" << ename (type_) << "::" << func << n << ";" + << "vd->state = s;" + << "vd->count = 0;" + << endl; + + Choice* pc (dynamic_cast (&c)); + + if (pc) + { + os << "this->" << earm (*pc) << " (static_cast< " << + earm_tag (*pc) << " > (s));"; + } + else + { + Sequence& s (dynamic_cast (c)); + + if (max != 1) + os << "this->" << enext (s) << " ();"; + else if (c.min () == 0) + os << "this->" << epresent (s) << " ();"; + } + + os << "this->" << func << n << " (vd->state, vd->count, ns, n, " << + (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);" + << "}"; + + // This element is not our prefix. + // + + os << "else" + << "{"; + + if (pc && c.min () == 1 && min == 0 && max == 1) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + choice_arm_call (p, pc, this); + } + + // Check if min cardinality requirements have been met. Since + // count is always >= 0, don't generate dead code if min == 0. + // + if (min != 0) + { + // Note that we are returning true in case of an error to + // indicate that no further search is needed. + // + os << "if (vd->count < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return true;" + << "}"; + } + + // Return false to indicate that we are not handling this element. + // + os << "return false;" + << "}" + << "}" // if (state != ~0) + << "else" << endl + << "return false;" + << "}"; // if (function == 0) + } + + private: + SemanticGraph::Complex& type_; + ParticleTest particle_test_; + ParticleName particle_name_; + }; + + + // + // + struct CompositorEndElement: Traversal::All, + Traversal::Compositor, + Context + { + CompositorEndElement (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type) + { + } + + virtual Void + traverse (SemanticGraph::All&) + { + os << "all_0 (vd.state, v_all_count_.top (), " << + "ns, n, " << (poly_runtime ? "0, " : "") << "false);" + << endl; + } + + virtual Void + traverse (SemanticGraph::Compositor&) // Choice and sequence. + { + os << "assert (vd.func != 0);" + << "(this->*vd.func) (vd.state, vd.count, ns, n, " << + (poly_runtime ? "0, " : "") << "false);" + << endl + << "if (vd.state == ~0UL)" << endl + << "vs.size--;" // pop + << endl; + } + + private: + SemanticGraph::Complex& type_; + }; + + + // + // + struct CompositorPost: Traversal::All, + Traversal::Compositor, + Context + { + CompositorPost (Context& c, SemanticGraph::Complex& type) + : Context (c), type_ (type), particle_name_ (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + using SemanticGraph::Element; + + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_& vd = vs.data[vs.size - 1];" + << endl; + + // Flush the state machine with the empty element name. This + // allows us to detect missing content. + // + os << "if (vd.count != 0)" + << "{" + << string_type << " empty;" + << "all_0 (vd.state, v_all_count_.top (), empty, empty, " << + (poly_runtime ? "0, " : "") << "true);" + << "}"; + + if (a.context ().get ("p:effective-min") != 0) + { + os << "else" << endl + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);"; + + /* + << "this->_expected_element (" << endl; + particle_name_.dispatch (a); + os << ");"; + */ + } + + os << endl + << "vs.size--;" // pop + << "v_all_count_.pop ();"; + } + + virtual Void + traverse (SemanticGraph::Compositor& c) // Choice and sequence. + { + using SemanticGraph::Choice; + + UnsignedLong min ( + c.context ().get ("p:effective-min")); + + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_* vd = vs.data + (vs.size - 1);" + << endl; + + + // Flush unfinished state machines with the empty element name. + // This allows us to detect missing content. Note that I am + // not re-setting vd since no new compositors are pushed on + // flush. + // + os << string_type << " empty;" + << "while (vd->func != 0)" + << "{" + << "(this->*vd->func) (vd->state, vd->count, empty, empty, " << + (poly_runtime ? "0, " : "") << "true);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "assert (vd->state == ~0UL);" + << "vd = vs.data + (--vs.size - 1);" // pop + << "}"; + + + Choice* pc (dynamic_cast (&c)); + + if (pc && c.min () == 1 && min == 0 && c.max () == 1) + { + // This is a required choice with effective-min == 0 (i.e., + // it contains optional particle). We need to call the arm + // callback with that optional particle's tag. + // + SemanticGraph::Particle* p (0); + OptionalParticleTest test (p); + test.traverse (*pc); + + if (p) + { + os << "if (vd->count == 0)" << endl + << "{"; + choice_arm_call (p, pc, this); + os << "}"; + } + } + + // Check if min cardinality requirements have been met. Since + // count is always >= 0, don't generate dead code if min == 0. + // + if (min != 0) + { + os << "if (vd->count < " << min << "UL)" << endl + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);"; + } + } + + private: + SemanticGraph::Complex& type_; + ParticleName particle_name_; + }; + + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + // Nothing to generate if we don't have any elements and wildcards. + // + if (!has (c) && + !has_particle (c)) + return; + + using SemanticGraph::Compositor; + + String const& name (ename (c)); + Compositor& comp (c.contains_compositor ().compositor ()); + + // Don't use restriction_p here since we don't want special + // treatment of anyType. + // + Boolean restriction ( + c.inherits_p () && + c.inherits ().is_a ()); + + os <<"// Element validation and dispatch functions for " << + name << "." << endl + <<"//" << endl; + + // _start_element_impl + // + + os << "bool " << name << "::" << endl + << "_start_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n"; + + if (poly_runtime) + os << "," << endl + << "const char*" << (poly_code ? " t" : ""); + + os << ")" + << "{"; + + if (poly_code) + os << "XSDE_UNUSED (t);" + << endl; + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_* vd = vs.data + (vs.size - 1);" + << endl; + + //@@ OPT: I don't really need to call parser_base since it always + // returns false. + // + // In case of an inheritance-by-extension, call our base first. + // We don't need to generate this code for the 'all' compositor + // because it can only inherit from the empty content model. + // Sattes of the root machine for sequence and choice: + // + // 0 - calling base + // 1 - base returned false + // ~0 - terminal state + // + if (!restriction && !comp.is_a ()) + { + os << "if (vd->func == 0 && vd->state == 0)" + << "{"; + + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (c.inherits_p ()) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::"; + + if (poly_runtime) + os << "_start_element_impl (ns, n, " << + (poly_code ? "t" : "0") << "))" << endl; + else + os << "_start_element_impl (ns, n))" << endl; + + os << "return true;" + << "else" << endl + << "vd->state = 1;" + << "}"; + } + + { + CompositorStartElement t (*this, c); + t.dispatch (comp); + } + + os << "return true;" + << "}"; + + + // _end_element_impl + // + + os << "bool " << name << "::" << endl + << "_end_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n)" + << "{"; + + os << "v_state_& vs = *static_cast< v_state_* > (" << + "this->v_state_stack_.top ());" + << "v_state_descr_& vd = vs.data[vs.size - 1];" + << endl; + + //@@ OPT: I don't really need to call parser_base since it always + // returns false. + // + // In case of an inheritance-by-extension, call our base first. + // We don't need to generate this code for the 'all' compositor + // because it can only inherit from the empty content model. + // + if (!restriction && !comp.is_a ()) + { + os << "if (vd.func == 0 && vd.state == 0)" + << "{"; + + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (c.inherits_p ()) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (!" << base << "::_end_element_impl (ns, n))" << endl + << "assert (false);" // Start and end should match. + << "return true;" + << "}"; + } + + { + CompositorEndElement t (*this, c); + t.dispatch (comp); + } + + os << "return true;" + << "}"; + + + // _pre_e_validate + // + os << "void " << name << "::" << endl + << "_pre_e_validate ()" + << "{"; + + if (exceptions) + os << "this->v_state_stack_.push ();"; + else + os << "if (this->v_state_stack_.push ())" + << "{" + << "this->_sys_error (::xsde::cxx::sys_error::no_memory);" + << "return;" + << "}"; + + os << "static_cast< v_state_* > (this->v_state_stack_.top ())->" << + "size = 0;" + << endl; + + { + // Assuming that this code cannot trigger an error. + // + CompositorPre t (*this, c); + t.dispatch (comp); + } + + // In case of an inheritance-by-extension, call our base + // _pre_e_validate. We don't need to generate this code for the + // 'all' compositor because it can only inherit from the empty + // content model. + // + if (!restriction && !comp.is_a ()) + { + // We don't need to call parser_base's implementation + // since it does nothing. + // + if (c.inherits_p ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_pre_e_validate ();"; + } + } + + os << "}"; + + + // _post_e_validate + // + os << "void " << name << "::" << endl + << "_post_e_validate ()" + << "{"; + + if (!comp.is_a ()) + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + // In case of an inheritance-by-extension, call our base + // _post_e_validate. We don't need to generate this code for + // the 'all' compositor because it can only inherit from + // the empty content model. + // + if (!restriction && !comp.is_a ()) + { + // We don't need to call parser_base's implementation + // since it does nothing. + // + if (c.inherits_p ()) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_post_e_validate ();" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + { + CompositorPost t (*this, c); + t.dispatch (c.contains_compositor ().compositor ()); + } + + os << endl + << "this->v_state_stack_.pop ();" + << "}"; + + // + // + ParticleFunction t (*this, c); + t.dispatch (c.contains_compositor ().compositor ()); + } + }; + } + + Void + generate_element_validation_source (Context& ctx) + { + ctx.os << "#include " << endl + << endl; + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Complex complex (ctx); + + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/element-validation-source.hxx b/xsde/cxx/parser/element-validation-source.hxx new file mode 100644 index 0000000..4dbf5e3 --- /dev/null +++ b/xsde/cxx/parser/element-validation-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/element-validation-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX +#define CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_element_validation_source (Context&); + } +} + +#endif // CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX diff --git a/xsde/cxx/parser/elements.cxx b/xsde/cxx/parser/elements.cxx new file mode 100644 index 0000000..e4d9cde --- /dev/null +++ b/xsde/cxx/parser/elements.cxx @@ -0,0 +1,258 @@ +// file : xsde/cxx/parser/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace CXX +{ + namespace Parser + { + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + CLI::Options const& ops, + Regex const* he, + Regex const* ie, + Regex const* hie) + : CXX::Context (o, + root, + "p:name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + options (ops), + xml_parser (xml_parser_), + simple_base (simple_base_), + complex_base (complex_base_), + list_base (list_base_), + parser_map (parser_map_), + validation (!ops.value ()), + exceptions (!ops.value ()), + poly_code (ops.value ()), + poly_runtime (poly_code || ops.value ()), + reset (!ops.value ()), + mixin (ops.value ()), + tiein (!mixin && !ops.value ()), + hxx_expr (he), + ixx_expr (ie), + hxx_impl_expr (hie), + xml_parser_ ("expat") + { + string_type = L"::xsde::cxx::ro_string"; + + simple_base_ = L"::xsde::cxx::parser::"; + simple_base_ += (validation ? L"validating" : L"non_validating"); + simple_base_ += L"::simple_content"; + + complex_base_ = L"::xsde::cxx::parser::"; + complex_base_ += (validation ? L"validating" : L"non_validating"); + complex_base_ += L"::complex_content"; + + list_base_ = L"::xsde::cxx::parser::"; + list_base_ += (validation ? L"validating" : L"non_validating"); + list_base_ += L"::list_base"; + + if (poly_code) + parser_map_ = xs_ns_name () + L"::parser_map"; + } + + String Context:: + real_fq_name (SemanticGraph::Nameable& n) + { + SemanticGraph::Context& c (n.context ()); + + if (c.count ("p:real-name")) + return c.get ("p:real-name"); + else + return fq_name (n); + } + + Content::Value Context:: + content (SemanticGraph::Complex& c) + { + using namespace SemanticGraph; + + if (c.mixed ()) + return Content::mixed; + + if (c.inherits_p ()) + { + Type& base (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&base)) + return content (*cb); + + if (base.is_a ()) + return Content::complex; + + // Everyhting else (built-in type and AnySimpleType) is simple + // content. + // + return Content::simple; + } + else + return Content::complex; + } + + + String const& Context:: + ret_type (SemanticGraph::Type& t) + { + return t.context ().get ("p:ret-type"); + } + + String const& Context:: + arg_type (SemanticGraph::Type& t) + { + return t.context ().get ("p:arg-type"); + } + + String const& Context:: + post_name (SemanticGraph::Type& t) + { + return t.context ().get ("p:post"); + } + + String const& Context:: + epresent (SemanticGraph::Compositor& c) + { + return c.context ().get ("p:present"); + } + + String const& Context:: + enext (SemanticGraph::Sequence& s) + { + return s.context ().get ("p:next"); + } + + String const& Context:: + etag (SemanticGraph::Particle& p) + { + return p.context ().get ("p:tag"); + } + + String const& Context:: + earm (SemanticGraph::Choice& c) + { + return c.context ().get ("p:arm"); + } + + String const& Context:: + earm_tag (SemanticGraph::Choice& c) + { + return c.context ().get ("p:arm-tag"); + } + + String const& Context:: + eparser (SemanticGraph::Member& m) + { + return m.context ().get ("p:parser"); + } + + String const& Context:: + emember (SemanticGraph::Member& m) + { + return m.context ().get ("p:member"); + } + + String const& Context:: + emember_cache (SemanticGraph::Member& m) + { + return m.context ().get ("p:member-cache"); + } + + String const& Context:: + emember_map (SemanticGraph::Member& m) + { + return m.context ().get ("p:member-map"); + } + + String const& Context:: + etiein (SemanticGraph::Type& t) + { + return t.context ().get ("p:tiein"); + } + + String const& Context:: + eimpl (SemanticGraph::Type& t) + { + return t.context ().get ("p:impl"); + } + + // Includes + // + Void TypeForward:: + traverse (SemanticGraph::Type& t) + { + os << "class " << t.context ().get (name_key_) << ";"; + } + + Void Includes:: + traverse_ (SemanticGraph::Uses& u) + { + // Support for weak (forward) inclusion used in the file-per-type + // compilation model. + // + Boolean weak (u.context ().count ("weak")); + + if (weak && (type_ == header || type_ == impl_header)) + { + // Generate forward declarations. We don't really need them + // in the impl files. + // + if (type_ == header) + schema_.dispatch (u.schema ()); + + return; + } + + if (type_ == source && !weak) + return; + + SemanticGraph::Path path (u.path ()); + + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.native_file_string (); + } + + String inc_path; + + switch (type_) + { + case header: + case source: + { + inc_path = ctx_.hxx_expr->merge (path_str); + break; + } + case impl_header: + { + inc_path = ctx_.hxx_impl_expr->merge (path_str); + break; + } + } + + ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl + << endl; + } + } +} diff --git a/xsde/cxx/parser/elements.hxx b/xsde/cxx/parser/elements.hxx new file mode 100644 index 0000000..0bb226e --- /dev/null +++ b/xsde/cxx/parser/elements.hxx @@ -0,0 +1,431 @@ +// file : xsde/cxx/parser/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_ELEMENTS_HXX +#define CXX_PARSER_ELEMENTS_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Parser + { + struct Content + { + enum Value + { + simple, + complex, + mixed + }; + }; + + // + // + class Context: public CXX::Context + { + public: + typedef BackendElements::Regex::Expression Regex; + + public: + Context (std::wostream&, + SemanticGraph::Schema&, + CLI::Options const&, + Regex const* hxx_expr, + Regex const* ixx_expr, + Regex const* hxx_impl_expr); + + protected: + Context (Context& c) + : CXX::Context (c), + options (c.options), + xml_parser (c.xml_parser), + simple_base (c.simple_base), + complex_base (c.complex_base), + list_base (c.list_base), + parser_map (c.parser_map), + validation (c.validation), + exceptions (c.exceptions), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + hxx_impl_expr (c.hxx_impl_expr) + { + } + + Context (Context& c, std::wostream& o) + : CXX::Context (c, o), + options (c.options), + xml_parser (c.xml_parser), + simple_base (c.simple_base), + complex_base (c.complex_base), + list_base (c.list_base), + parser_map (c.parser_map), + validation (c.validation), + exceptions (c.exceptions), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + hxx_impl_expr (c.hxx_impl_expr) + { + } + + public: + Boolean + restriction_p (SemanticGraph::Complex& c) const + { + if (c.inherits_p () && + c.inherits ().is_a ()) + { + // Restriction of anyType is a special case. + // + return !c.inherits ().base ().is_a (); + } + + return false; + } + + // Real (e.g., non-typedef) fq-name. + // + String + real_fq_name (SemanticGraph::Nameable& n); + + public: + static Content::Value + content (SemanticGraph::Complex&); + + public: + static String const& + ret_type (SemanticGraph::Type&); + + static String const& + arg_type (SemanticGraph::Type&); + + static String const& + post_name (SemanticGraph::Type&); + + public: + // Optional. + // + static String const& + epresent (SemanticGraph::Compositor&); + + // Sequence. + // + static String const& + enext (SemanticGraph::Sequence&); + + // Choice. + // + static String const& + etag (SemanticGraph::Particle&); + + static String const& + earm (SemanticGraph::Choice&); + + static String const& + earm_tag (SemanticGraph::Choice&); + + public: + static String const& + eparser (SemanticGraph::Member&); + + static String const& + emember (SemanticGraph::Member&); + + static String const& + emember_cache (SemanticGraph::Member&); + + static String const& + emember_map (SemanticGraph::Member&); + + static String const& + etiein (SemanticGraph::Type&); + + public: + static String const& + eimpl (SemanticGraph::Type&); + + public: + CLI::Options const& options; + String& xml_parser; + String& simple_base; + String& complex_base; + String& list_base; + String& parser_map; + + Boolean validation; + Boolean exceptions; + Boolean poly_code; + Boolean poly_runtime; + Boolean reset; + Boolean mixin; + Boolean tiein; + + Regex const* hxx_expr; + Regex const* ixx_expr; + Regex const* hxx_impl_expr; + + private: + String xml_parser_; + String simple_base_; + String complex_base_; + String list_base_; + String parser_map_; + }; + + // + // + struct RequiredAttributeTest: Traversal::Attribute + { + RequiredAttributeTest (Boolean& result) + : result_ (result) + { + } + + virtual Void + traverse (Type& a) + { + if (!result_ && !a.optional ()) + result_ = true; + } + + private: + Boolean& result_; + }; + + + // + // + struct ParticleParamDecl: Traversal::Element, Context + { + ParticleParamDecl (Context& c, Boolean& first, Boolean name_arg) + : Context (c), first_ (first), name_arg_ (name_arg) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (e.type ()) << "&"; + + if (name_arg_) + os << " " << ename (e); + else + os << " /* " << comment (e.name ()) << " */"; + } + + private: + Boolean& first_; + Boolean name_arg_; + }; + + struct AttributeParamDecl: Traversal::Attribute, Context + { + AttributeParamDecl (Context& c, Boolean& first, Boolean name_arg) + : Context (c), first_ (first), name_arg_ (name_arg) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (a.type ()) << "&"; + + if (name_arg_) + os << " " << ename (a); + else + os << " /* " << comment (a.name ()) << " */"; + } + + private: + Boolean& first_; + Boolean name_arg_; + }; + + struct ParserParamDecl : Traversal::Complex, + Traversal::List, + Context + { + ParserParamDecl (Context& c, Boolean name_arg) + : Context (c), + particle_ (c, first_, name_arg), + attribute_ (c, first_, name_arg), + first_ (true), + name_arg_ (name_arg) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_ >> contains_particle_; + contains_particle_ >> particle_; + contains_particle_ >> compositor_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (l.argumented ().type ()) << "&"; + + if (name_arg_) + os << " " << ename (l) << "_item"; + else + os << " /* " << comment (l.name ()) << " item */"; + } + + private: + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleParamDecl particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + AttributeParamDecl attribute_; + Traversal::Names names_; + + Boolean first_; + Boolean name_arg_; + }; + + // + // + struct TypeForward: Traversal::Type, Context + { + TypeForward (Context& c, Char const* name_key) + : Context (c), name_key_ (name_key) + { + } + + virtual Void + traverse (SemanticGraph::Type& t); + + private: + Char const* name_key_; + }; + + struct Includes : Traversal::Imports, + Traversal::Includes + { + enum Type + { + header, + source, + impl_header + }; + + Includes (Context& c, Type t) + : ctx_ (c), + type_ (t), + namespace_ (c), + type_forward_ (c, t == header ? "p:name" : "p:impl") + { + schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + traverse_ (i); + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + traverse_ (i); + } + + private: + Void + traverse_ (SemanticGraph::Uses&); + + private: + Context& ctx_; + Type type_; + + Traversal::Schema schema_; + Traversal::Names schema_names_; + Namespace namespace_; + Traversal::Names names_; + TypeForward type_forward_; + }; + + // Find root element for the test driver. + // + struct RootElement: Traversal::Element + { + RootElement (CLI::Options const& options, + SemanticGraph::Element*& element) + : options_ (options), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (options_.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (String name = options_.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + element_ = &e; // Cover root-element-last and no option. + } + + private: + CLI::Options const& options_; + SemanticGraph::Element*& element_; + }; + } +} + +#endif // CXX_PARSER_ELEMENTS_HXX diff --git a/xsde/cxx/parser/generator.cxx b/xsde/cxx/parser/generator.cxx new file mode 100644 index 0000000..e552c92 --- /dev/null +++ b/xsde/cxx/parser/generator.cxx @@ -0,0 +1,1615 @@ +// file : xsde/cxx/parser/generator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include "../../../libxsde/xsde/cxx/version.hxx" + +using std::endl; +using std::wcerr; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef +boost::filesystem::wifstream +WideInputFileStream; + +typedef +boost::filesystem::wofstream +WideOutputFileStream; + +typedef +boost::filesystem::ifstream +NarrowInputFileStream; + +namespace CXX +{ + namespace + { + Char const copyright_gpl[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n" + "// to C++ data binding compiler for embedded systems.\n" + "//\n" + "// This program is free software; you can redistribute it and/or modify\n" + "// it under the terms of the GNU General Public License version 2 as\n" + "// published by the Free Software Foundation.\n" + "//\n" + "// This program is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU General Public License\n" + "// along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" + "//\n" + "//\n\n"; + + Char const copyright_proprietary[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n" + "// C++ data binding compiler for embedded systems, in the Proprietary\n" + "// License mode. You should have received a proprietary license from\n" + "// Code Synthesis Tools CC prior to generating this code. See the\n" + "// license text for conditions.\n" + "//\n\n"; + + Char const copyright_impl[] = + "// Not copyrighted - public domain.\n" + "//\n" + "// This sample parser implementation was generated by CodeSynthesis XSD/e,\n" + "// an XML Schema to C++ data binding compiler for embedded systems. You\n" + "// may use it in your programs without any restrictions.\n" + "//\n\n"; + } + + namespace Parser + { + namespace CLI + { + extern Key type_map = "type-map"; + extern Key no_stl = "no-stl"; + extern Key no_iostream = "no-iostream"; + extern Key no_exceptions = "no-exceptions"; + extern Key no_long_long = "no-long-long"; + extern Key reuse_style_mixin = "reuse-style-mixin"; + extern Key reuse_style_none = "reuse-style-none"; + extern Key generate_inline = "generate-inline"; + extern Key suppress_validation = "suppress-validation"; + extern Key generate_polymorphic = "generate-polymorphic"; + extern Key runtime_polymorphic = "runtime-polymorphic"; + extern Key suppress_reset = "suppress-reset"; + extern Key generate_noop_impl = "generate-noop-impl"; + extern Key generate_print_impl = "generate-print-impl"; + extern Key generate_test_driver = "generate-test-driver"; + extern Key force_overwrite = "force-overwrite"; + extern Key root_element_first = "root-element-first"; + extern Key root_element_last = "root-element-last"; + extern Key root_element = "root-element"; + extern Key generate_xml_schema = "generate-xml-schema"; + extern Key extern_xml_schema = "extern-xml-schema"; + extern Key output_dir = "output-dir"; + extern Key skel_type_suffix = "skel-type-suffix"; + extern Key skel_file_suffix = "skel-file-suffix"; + extern Key impl_type_suffix = "impl-type-suffix"; + extern Key impl_file_suffix = "impl-file-suffix"; + extern Key namespace_map = "namespace-map"; + extern Key namespace_regex = "namespace-regex"; + extern Key namespace_regex_trace = "namespace-regex-trace"; + extern Key reserved_name = "reserved-name"; + extern Key include_with_brackets = "include-with-brackets"; + extern Key include_prefix = "include-prefix"; + extern Key include_regex = "include-regex"; + extern Key include_regex_trace = "include-regex-trace"; + extern Key guard_prefix = "guard-prefix"; + extern Key hxx_suffix = "hxx-suffix"; + extern Key ixx_suffix = "ixx-suffix"; + extern Key cxx_suffix = "cxx-suffix"; + extern Key hxx_regex = "hxx-regex"; + extern Key ixx_regex = "ixx-regex"; + extern Key cxx_regex = "cxx-regex"; + extern Key hxx_prologue = "hxx-prologue"; + extern Key ixx_prologue = "ixx-prologue"; + extern Key cxx_prologue = "cxx-prologue"; + extern Key prologue = "prologue"; + extern Key hxx_epilogue = "hxx-epilogue"; + extern Key ixx_epilogue = "ixx-epilogue"; + extern Key cxx_epilogue = "cxx-epilogue"; + extern Key epilogue = "epilogue"; + extern Key hxx_prologue_file = "hxx-prologue-file"; + extern Key ixx_prologue_file = "ixx-prologue-file"; + extern Key cxx_prologue_file = "cxx-prologue-file"; + extern Key prologue_file = "prologue-file"; + extern Key hxx_epilogue_file = "hxx-epilogue-file"; + extern Key ixx_epilogue_file = "ixx-epilogue-file"; + extern Key cxx_epilogue_file = "cxx-epilogue-file"; + extern Key epilogue_file = "epilogue-file"; + extern Key show_anonymous = "show-anonymous"; + extern Key show_sloc = "show-sloc"; + extern Key proprietary_license = "proprietary-license"; + } + } + + Void Parser::Generator:: + usage () + { + std::wostream& e (wcerr); + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + e << "--type-map " << endl + << " Read XML Schema to C++ type mapping information\n" + << " from . Repeat this option to specify\n" + << " several type maps. Type maps are considered in\n" + << " order of appearance and the first match is used." + << endl; + + e << "--no-stl" << endl + << " Generate code that does not use STL." + << endl; + + e << "--no-iostream" << endl + << " Generate code that does not use the iostream\n" + << " library." + << endl; + + e << "--no-exceptions" << endl + << " Generate code that does not use C++ exceptions." + << endl; + + e << "--no-long-long" << endl + << " Generate code that does not use the long long\n" + << " and unsigned long long types." + << endl; + + e << "--reuse-style-mixin" << endl + << " Generate code that supports the mixin base parser\n" + << " implementation reuse style." + << endl; + + e << "--reuse-style-none" << endl + << " Do not generate any support for base parser\n" + << " implementation reuse." + << endl; + + e << "--generate-inline" << endl + << " Generate certain functions inline." + << endl; + + e << "--suppress-validation" << endl + << " Suppress the generation of validation code." + << endl; + + e << "--generate-polymorphic" << endl + << " Generate polymorphism-aware code. Specify this\n" + << " option if you use substitution groups or xsi:type." + << endl; + + e << "--runtime-polymorphic" << endl + << " Generate non-polymorphic code that uses the\n" + << " runtime library configured with polymorphism\n" + << " support." + << endl; + + e << "--suppress-reset" << endl + << " Suppress the generation of parser reset code." + << endl; + + e << "--generate-noop-impl" << endl + << " Generate a sample parser implementation that\n" + << " does nothing (no operation)." + << endl; + + e << "--generate-print-impl" << endl + << " Generate a sample parser implementation that\n" + << " prints the XML data to STDOUT." + << endl; + + e << "--generate-test-driver" << endl + << " Generate a test driver for the sample parser\n" + << " implementation." + << endl; + + e << "--force-overwrite" << endl + << " Force overwriting of the existing implementation\n" + << " and test driver files." + << endl; + + e << "--root-element-first" << endl + << " Indicate that the first global element is the\n" + << " document root." + << endl; + + e << "--root-element-last" << endl + << " Indicate that the last global element is the\n" + << " document root." + << endl; + + e << "--root-element " << endl + << " Indicate that is the document root." + << endl; + + e << "--generate-xml-schema" << endl + << " Generate a C++ header file as if the schema being\n" + << " compiled defines the XML Schema namespace." + << endl; + + e << "--extern-xml-schema " << endl + << " Generate code as if the XML Schema namespace was\n" + << " defined in and xsd:included in the schema\n" + << " being compiled." + << endl; + + e << "--output-dir " << endl + << " Write generated files to instead of the\n" + << " current directory." + << endl; + + e << "--skel-type-suffix " << endl + << " Use instead of the default '_pskel' to\n" + << " construct the names of generated parser skeletons." + << endl; + + e << "--skel-file-suffix " << endl + << " Use instead of the default '-pskel' to\n" + << " construct the names of generated parser skeleton\n" + << " files." + << endl; + + e << "--impl-type-suffix " << endl + << " Use instead of the default '_pimpl' to\n" + << " construct the names of parser implementations for\n" + << " the built-in XML Schema types and sample parser\n" + << " implementations." + << endl; + + e << "--impl-file-suffix " << endl + << " Use instead of the default '-pimpl' to\n" + << " construct the names of generated sample parser\n" + << " implementation files." + << endl; + + e << "--namespace-map =" << endl + << " Map XML Schema namespace to C++ namespace\n" + << " . Repeat this option to specify mapping for\n" + << " more than one XML Schema namespace." + << endl; + + e << "--namespace-regex " << endl + << " Add to the list of regular expressions\n" + << " used to translate XML Schema namespace names to\n" + << " C++ namespace names." + << endl; + + e << "--namespace-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --namespace-regex option." + << endl; + + e << "--reserved-name " << endl + << " Add to the list of names that should not\n" + << " be used as identifiers. The name can optionally\n" + << " be followed by '=' and the replacement name that\n" + << " should be used instead." + << endl; + + e << "--include-with-brackets" << endl + << " Use angle brackets (<>) instead of quotes (\"\") in\n" + << " generated #include directives." + << endl; + + e << "--include-prefix " << endl + << " Add to generated #include directive\n" + << " paths." + << endl; + + e << "--include-regex " << endl + << " Add to the list of regular expressions\n" + << " used to transform #include directive paths." + << endl; + + e << "--include-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --include-regex option." + << endl; + + e << "--guard-prefix " << endl + << " Add to generated header inclusion guards." + << endl; + + e << "--hxx-suffix " << endl + << " Use instead of the default '.hxx' to\n" + << " construct the name of the header file." + << endl; + + e << "--ixx-suffix " << endl + << " Use instead of the default '.ixx' to\n" + << " construct the name of the inline file." + << endl; + + e << "--cxx-suffix " << endl + << " Use instead of the default '.cxx' to\n" + << " construct the name of the source file." + << endl; + + e << "--hxx-regex " << endl + << " Use to construct the name of the header\n" + << " file." + << endl; + + e << "--ixx-regex " << endl + << " Use to construct the name of the inline\n" + << " file." + << endl; + + e << "--cxx-regex " << endl + << " Use to construct the name of the source\n" + << " file." + << endl; + + + // Prologues. + // + e << "--hxx-prologue " << endl + << " Insert at the beginning of the header file." + << endl; + + e << "--ixx-prologue " << endl + << " Insert at the beginning of the inline file." + << endl; + + e << "--cxx-prologue " << endl + << " Insert at the beginning of the source file." + << endl; + + e << "--prologue " << endl + << " Insert at the beginning of each generated\n" + << " file for which there is no file-specific prologue." + << endl; + + + // Epilogues. + // + e << "--hxx-epilogue " << endl + << " Insert at the end of the header file." + << endl; + + e << "--ixx-epilogue " << endl + << " Insert at the end of the inline file." + << endl; + + e << "--cxx-epilogue " << endl + << " Insert at the end of the source file." + << endl; + + e << "--epilogue " << endl + << " Insert at the end of each generated file\n" + << " for which there is no file-specific epilogue." + << endl; + + + // Prologue files. + // + e << "--hxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the header file." + << endl; + + e << "--ixx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the inline file." + << endl; + + e << "--cxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the source file." + << endl; + + e << "--prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of each generated file for which there is no file-\n" + << " specific prologue file." + << endl; + + + // Epilogue files. + // + e << "--hxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the header file." + << endl; + + e << "--ixx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the inline file." + << endl; + + e << "--cxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the source file." + << endl; + + e << "--epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " each generated file for which there is no file-\n" + << " specific epilogue file." + << endl; + + + // Misc. + // + e << "--show-anonymous" << endl + << " Show elements and attributes that are of anonymous\n" + << " types." + << endl; + + e << "--show-sloc" << endl + << " Show the number of generated physical source lines\n" + << " of code (SLOC)." + << endl; + + e << "--sloc-limit " << endl + << " Check that the number of generated physical source\n" + << " lines of code (SLOC) does not exceed ." + << endl; + + e << "--options-file " << endl + << " Read additional options from . Each option\n" + << " should appear on a separate line optionally\n" + << " followed by space and an argument." + << endl; + + e << "--proprietary-license" << endl + << " Indicate that the generated code is licensed under\n" + << " a proprietary license instead of the GPL." + << endl; + } + + Parser::CLI::OptionsSpec Parser::Generator:: + options_spec () + { + CLI::OptionsSpec spec; + + spec.option ().default_value ("-pskel"); + spec.option ().default_value ("_pskel"); + spec.option ().default_value ("-pimpl"); + spec.option ().default_value ("_pimpl"); + + spec.option ().default_value (".hxx"); + spec.option ().default_value (".ixx"); + spec.option ().default_value (".cxx"); + + return spec; + } + + + namespace + { + template + Void + open (S& ifs, NarrowString const& path) + { + try + { + Path fs_path (path, boost::filesystem::native); + ifs.open (fs_path, std::ios_base::in | std::ios_base::binary); + + if (!ifs.is_open ()) + { + wcerr << path.c_str () << ": error: unable to open in read mode" + << endl; + + throw Parser::Generator::Failed (); + } + } + catch (InvalidPath const&) + { + wcerr << "error: '" << path.c_str () << "' is not a valid " + << "filesystem path" << endl; + + throw Parser::Generator::Failed (); + } + } + + Void + append (WideOutputFileStream& os, + NarrowString const& path, + WideInputFileStream& default_is) + { + using std::ios_base; + + if (path) + { + WideInputFileStream is; + open (is, path); + os << is.rdbuf (); + } + else if (default_is.is_open ()) + { + os << default_is.rdbuf (); + default_is.seekg (0, ios_base::beg); + } + } + + Void + append (WideOutputFileStream& os, + Cult::Containers::Vector const& primary, + Cult::Containers::Vector const& def) + { + Cult::Containers::Vector const& v ( + primary.empty () ? def : primary); + + for (Containers::Vector::ConstIterator + i (v.begin ()), e (v.end ()); i != e; ++i) + { + os << i->c_str () << endl; + } + } + } + + + UnsignedLong Parser::Generator:: + generate (Parser::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + TypeMap::Namespaces& type_map, + Boolean gen_driver, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression Regex; + + try + { + Boolean generate_xml_schema (ops.value ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (generate_xml_schema) + { + if (NarrowString name = ops.value ()) + { + if (file_path.native_file_string () != name) + generate_xml_schema = false; + } + } + + Boolean impl (!generate_xml_schema && + (ops.value () || + ops.value ())); + + Boolean driver (gen_driver && !generate_xml_schema && + ops.value ()); + + + // Evaluate the graph for possibility of generating something useful. + // + { + Validator validator; + if (!validator.validate ( + ops, schema, file_path, driver, disabled_warnings)) + throw Failed (); + } + + // Process names. + // + { + NameProcessor proc; + proc.process (ops, schema, file_path); + } + + Boolean validation (!ops.value ()); + + // Compute state machine info. + // + if (validation) + { + StateProcessor proc; + proc.process (schema, file_path); + } + + // Read-in type maps. + // + { + using namespace TypeMap; + typedef Containers::Vector Files; + + Files const& files (ops.value ()); + + for (Files::ConstIterator f (files.begin ()); f != files.end (); ++f ) + { + NarrowInputFileStream ifs; + open (ifs, *f); + + Lexer l (ifs, *f); + TypeMap::Parser p (l, *f); + + if (!p.parse (type_map)) + throw Failed (); + } + + // Add the built-in mappings at the end. + // + String xns; + { + Context ctx (std::wcerr, schema, ops, 0, 0, 0); + xns = ctx.xs_ns_name (); + } + + if (ops.value ()) + { + TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema"); + + String qname (xns + L"::qname*"); + String string_seq (xns + L"::string_sequence*"); + + xsd_std.types_push_back ("string", "char*", "char*"); + xsd_std.types_push_back ("normalizedString", "char*", "char*"); + xsd_std.types_push_back ("token", "char*", "char*"); + xsd_std.types_push_back ("Name", "char*", "char*"); + xsd_std.types_push_back ("NMTOKEN", "char*", "char*"); + xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq); + xsd_std.types_push_back ("NCName", "char*", "char*"); + + xsd_std.types_push_back ("ID", "char*", "char*"); + xsd_std.types_push_back ("IDREF", "char*", "char*"); + xsd_std.types_push_back ("IDREFS", string_seq, string_seq); + + xsd_std.types_push_back ("language", "char*", "char*"); + xsd_std.types_push_back ("anyURI", "char*", "char*"); + xsd_std.types_push_back ("QName", qname, qname); + + type_map.push_back (xsd_std); + } + else + { + TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema"); + + String qname (xns + L"::qname"); + String string_seq (xns + L"::string_sequence*"); + + xsd_std.types_push_back ("string", "::std::string"); + xsd_std.types_push_back ("normalizedString", "::std::string"); + xsd_std.types_push_back ("token", "::std::string"); + xsd_std.types_push_back ("Name", "::std::string"); + xsd_std.types_push_back ("NMTOKEN", "::std::string"); + xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq); + xsd_std.types_push_back ("NCName", "::std::string"); + + xsd_std.types_push_back ("ID", "::std::string"); + xsd_std.types_push_back ("IDREF", "::std::string"); + xsd_std.types_push_back ("IDREFS", string_seq, string_seq); + + xsd_std.types_push_back ("language", "::std::string"); + xsd_std.types_push_back ("anyURI", "::std::string"); + xsd_std.types_push_back ("QName", qname); + + type_map.push_back (xsd_std); + } + + String buffer (xns + L"::buffer*"); + + TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema"); + + xsd.types_push_back ("boolean", "bool", "bool"); + + xsd.types_push_back ("byte", "signed char", "signed char"); + xsd.types_push_back ("unsignedByte", "unsigned char", "unsigned char"); + + xsd.types_push_back ("short", "short", "short"); + xsd.types_push_back ("unsignedShort", "unsigned short", "unsigned short"); + + xsd.types_push_back ("int", "int", "int"); + xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int"); + + if (ops.value ()) + { + xsd.types_push_back ("long", "long", "long"); + xsd.types_push_back ("unsignedLong", "unsigned long", "unsigned long"); + } + else + { + xsd.types_push_back ("long", "long long", "long long"); + xsd.types_push_back ("unsignedLong", "unsigned long long", "unsigned long long"); + } + + xsd.types_push_back ("integer", "long", "long"); + + xsd.types_push_back ("negativeInteger", "long", "long"); + xsd.types_push_back ("nonPositiveInteger", "long", "long"); + + xsd.types_push_back ("positiveInteger", "unsigned long", "unsigned long"); + xsd.types_push_back ("nonNegativeInteger", "unsigned long", "unsigned long"); + + xsd.types_push_back ("float", "float", "float"); + xsd.types_push_back ("double", "double", "double"); + xsd.types_push_back ("decimal", "double", "double"); + + xsd.types_push_back ("base64Binary", buffer, buffer); + xsd.types_push_back ("hexBinary", buffer, buffer); + + xsd.types_push_back ("gDay", xns + L"::gday"); + xsd.types_push_back ("gMonth", xns + L"::gmonth"); + xsd.types_push_back ("gYear", xns + L"::gyear"); + xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day"); + xsd.types_push_back ("gYearMonth", xns + L"::gyear_month"); + xsd.types_push_back ("date", xns + L"::date"); + xsd.types_push_back ("time", xns + L"::time"); + xsd.types_push_back ("dateTime", xns + L"::date_time"); + xsd.types_push_back ("duration", xns + L"::duration"); + + type_map.push_back (xsd); + + // Everyhting else maps to void. + // + TypeMap::Namespace rest (".*"); + rest.types_push_back (".*", "void", "void"); + type_map.push_back (rest); + } + + // Process types. + // + { + TypeProcessor proc; + proc.process (ops, schema, type_map); + } + + // Generate code. + // + Boolean inline_ (ops.value () && + !generate_xml_schema); + + Boolean source (!generate_xml_schema); + + NarrowString name (file_path.leaf ()); + NarrowString skel_suffix (ops.value ()); + NarrowString impl_suffix (ops.value ()); + + NarrowString hxx_suffix (ops.value ()); + NarrowString ixx_suffix (ops.value ()); + NarrowString cxx_suffix (ops.value ()); + + Regex hxx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#" + : ops.value ()); + + Regex ixx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#" + : ops.value ()); + + Regex cxx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#" + : ops.value ()); + + Regex hxx_impl_expr; + Regex cxx_impl_expr; + Regex cxx_driver_expr; + + if (impl || driver) + { + hxx_impl_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"; + + cxx_impl_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"; + + cxx_driver_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1-pdriver" + cxx_suffix + "#"; + } + + if (!hxx_expr.match (name)) + { + wcerr << "error: header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (inline_ && !ixx_expr.match (name)) + { + wcerr << "error: inline expression '" << + ixx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (source && !cxx_expr.match (name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (impl || driver) + { + if (!hxx_impl_expr.match (name)) + { + wcerr << "error: implementation header expression '" << + hxx_impl_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_impl_expr.match (name)) + { + wcerr << "error: implementation source expression '" << + cxx_impl_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_driver_expr.match (name)) + { + wcerr << "error: driver source expression '" << + cxx_driver_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + } + + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ()); + NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ()); + + NarrowString hxx_impl_name; + NarrowString cxx_impl_name; + NarrowString cxx_driver_name; + + if (impl || driver) + { + hxx_impl_name = hxx_impl_expr.merge (name); + cxx_impl_name = cxx_impl_expr.merge (name); + cxx_driver_name = cxx_driver_expr.merge (name); + } + + Path hxx_path (hxx_name, boost::filesystem::native); + Path ixx_path (ixx_name, boost::filesystem::native); + Path cxx_path (cxx_name, boost::filesystem::native); + + Path hxx_impl_path; + Path cxx_impl_path; + Path cxx_driver_path; + + if (impl || driver) + { + hxx_impl_path = Path (hxx_impl_name, boost::filesystem::native); + cxx_impl_path = Path (cxx_impl_name, boost::filesystem::native); + cxx_driver_path = Path (cxx_driver_name, boost::filesystem::native); + } + + if (NarrowString dir = ops.value ()) + { + try + { + Path path (dir, boost::filesystem::native); + + hxx_path = path / hxx_path; + ixx_path = path / ixx_path; + cxx_path = path / cxx_path; + + if (impl || driver) + { + hxx_impl_path = path / hxx_impl_path; + cxx_impl_path = path / cxx_impl_path; + cxx_driver_path = path /cxx_driver_path; + } + + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + // Open the impl files first so that if open fails, the skel files + // are not deleted. + // + WideOutputFileStream hxx_impl; + WideOutputFileStream cxx_impl; + WideOutputFileStream cxx_driver; + + if (impl) + { + if (!ops.value ()) + { + WideInputFileStream tmp (hxx_impl_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << hxx_impl_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + hxx_impl.open (hxx_impl_path, ios_base::out); + + if (!hxx_impl.is_open ()) + { + wcerr << hxx_impl_path << ": error: unable to open in write mode" + << endl; + throw Failed (); + } + + unlinks.add (hxx_impl_path); + file_list.push_back (hxx_impl_path.native_file_string ()); + + if (!ops.value ()) + { + WideInputFileStream tmp (cxx_impl_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << cxx_impl_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + cxx_impl.open (cxx_impl_path, ios_base::out); + + if (!cxx_impl.is_open ()) + { + wcerr << cxx_impl_path << ": error: unable to open in write mode" + << endl; + throw Failed (); + } + + unlinks.add (cxx_impl_path); + file_list.push_back (cxx_impl_path.native_file_string ()); + } + + if (driver) + { + if (!ops.value ()) + { + WideInputFileStream tmp (cxx_driver_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << cxx_driver_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + cxx_driver.open (cxx_driver_path, ios_base::out); + + if (!cxx_driver.is_open ()) + { + wcerr << cxx_driver_path << ": error: unable to open in write " << + "mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_driver_path); + file_list.push_back (cxx_driver_path.native_file_string ()); + } + + // Open the skel files. + // + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream ixx; + WideOutputFileStream cxx; + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + file_list.push_back (hxx_path.native_file_string ()); + + if (inline_) + { + ixx.open (ixx_path, ios_base::out); + + if (!ixx.is_open ()) + { + wcerr << ixx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (ixx_path); + file_list.push_back (ixx_path.native_file_string ()); + } + + if (source) + { + cxx.open (cxx_path, ios_base::out); + + if (!cxx.is_open ()) + { + wcerr << cxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_path); + file_list.push_back (cxx_path.native_file_string ()); + } + + // Print copyright and license. + // + Char const* copyright ( + ops.value () + ? copyright_proprietary + : copyright_gpl); + + hxx << copyright; + + if (inline_) + ixx << copyright; + + if (source) + cxx << copyright; + + if (impl) + { + hxx_impl << copyright_impl; + cxx_impl << copyright_impl; + } + + if (driver) + cxx_driver << copyright_impl; + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name (ops.value ()); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name (ops.value ()); + + if (name) + open (epilogue, name); + } + + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value ()); + + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + + NarrowString guard_prefix (ops.value ()); + + if (!guard_prefix) + guard_prefix = file_path.branch_path ().native_directory_string (); + + if (guard_prefix) + guard_prefix += '_'; + + + // HXX + // + { + Context ctx (hxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip hxx_sloc (hxx); + + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append ( + hxx, ops.value (), ops.value ()); + append (hxx, ops.value (), prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Version check. + // + hxx << "#include " << endl + << endl + << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl + << "#error XSD/e runtime version mismatch" << endl + << "#endif" << endl + << endl; + + // Runtime/generated code compatibility checks. + // + + hxx << "#include " << endl + << endl; + + if (ops.value ()) + { + hxx << "#ifdef XSDE_STL" << endl + << "#error the XSD/e runtime uses STL while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-stl)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_STL" << endl + << "#error the generated code uses STL while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-stl)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_IOSTREAM" << endl + << "#error the XSD/e runtime uses iostream while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-iostream)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_IOSTREAM" << endl + << "#error the generated code uses iostream while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-iostream)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_EXCEPTIONS" << endl + << "#error the XSD/e runtime uses exceptions while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_EXCEPTIONS" << endl + << "#error the generated code uses exceptions while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_LONGLONG" << endl + << "#error the XSD/e runtime uses long long while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-long-long)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_LONGLONG" << endl + << "#error the generated code uses long long while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-long-long)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_PARSER_VALIDATION" << endl + << "#error the XSD/e runtime uses validation while the " << + "generated code does not (reconfigure the runtime or " << + "remove --suppress-validation)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_PARSER_VALIDATION" << endl + << "#error the generated code uses validation while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --suppress-validation)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value () || + ops.value ()) + { + hxx << "#ifndef XSDE_POLYMORPHIC" << endl + << "#error the generated code expects XSD/e runtime with " << + "polymorphism support (reconfigure the runtime or remove " << + "--generate-polymorphic/--runtime-polymorphic)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifdef XSDE_POLYMORPHIC" << endl + << "#error the generated code expects XSD/e runtime " << + "without polymorphism support (reconfigure the runtime or " << + "add --generate-polymorphic/--runtime-polymorphic)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifndef XSDE_REUSE_STYLE_MIXIN" << endl + << "#error the generated code uses the mixin reuse style " << + "while the XSD/e runtime does not (reconfigure the runtime " << + "or remove --reuse-style-mixin)" << endl + << "#endif" << endl + << endl; + } + else if (ops.value ()) + { + hxx << "#ifndef XSDE_REUSE_STYLE_NONE" << endl + << "#error the generated code does not provide support " << + "for parser reuse while the XSD/e runtime does (reconfigure " << + "the runtime or remove --reuse-style-none)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_REUSE_STYLE_TIEIN" << endl + << "#error the generated code uses the tiein reuse style " << + "while the XSD/e runtime does not (reconfigure the runtime " << + "or add --reuse-style-mixin or --reuse-style-none)" << endl + << "#endif" << endl + << endl; + } + + // + // + + hxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip hxx_clip (hxx); + + // Generate. + // + if (!generate_xml_schema) + generate_parser_forward (ctx); + + generate_parser_header (ctx, generate_xml_schema); + + if (inline_) + hxx << "#include " << ctx.process_include_path (ixx_name) << endl + << endl; + + hxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, ops.value (), epilogue); + append ( + hxx, ops.value (), ops.value ()); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + + // IXX + // + if (inline_) + { + Context ctx (ixx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip ixx_sloc (ixx); + + + // Copy prologue. + // + ixx << "// Begin prologue." << endl + << "//" << endl; + + append ( + ixx, ops.value (), ops.value ()); + append (ixx, ops.value (), prologue); + + ixx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip ixx_clip (ixx); + + + // Generate. + // + generate_parser_inline (ctx); + } + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, ops.value (), epilogue); + append ( + ixx, ops.value (), ops.value ()); + + ixx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << ixx_path << ": " + << ixx_sloc.buffer ().count () << endl; + + sloc += ixx_sloc.buffer ().count (); + } + } + + + // CXX + // + if (source) + { + Context ctx (cxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip cxx_sloc (cxx); + + // Copy prologue. + // + cxx << "// Begin prologue." << endl + << "//" << endl; + + append ( + cxx, ops.value (), ops.value ()); + append (cxx, ops.value (), prologue); + + cxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip cxx_clip (cxx); + + cxx << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + if (!inline_) + generate_parser_inline (ctx); + + generate_parser_source (ctx); + + if (validation) + { + generate_element_validation_source (ctx); + generate_attribute_validation_source (ctx); + generate_characters_validation_source (ctx); + } + } + + // Copy epilogue. + // + cxx << "// Begin epilogue." << endl + << "//" << endl; + + append (cxx, ops.value (), epilogue); + append ( + cxx, ops.value (), ops.value ()); + + cxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_path << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + + // HXX impl + // + if (impl) + { + Context ctx (hxx_impl, schema, ops, + &hxx_expr, &ixx_expr, &hxx_impl_expr); + + String guard (guard_expr.merge (guard_prefix + hxx_impl_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx_impl << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip clip (hxx_impl); + + hxx_impl << "#include " << ctx.process_include_path (hxx_name) + << endl << endl; + + generate_impl_header (ctx); + } + + hxx_impl << "#endif // " << guard << endl; + } + + // CXX impl + // + if (impl) + { + Context ctx (cxx_impl, schema, ops, + &hxx_expr, &ixx_expr, &hxx_impl_expr); + + // Set auto-indentation. + // + Indentation::Clip clip (cxx_impl); + + cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name) + << endl << endl; + + generate_impl_source (ctx); + } + + // CXX driver + // + if (driver) + { + Context ctx (cxx_driver, schema, ops, + &hxx_expr, &ixx_expr, &hxx_impl_expr); + + // Set auto-indentation. + // + Indentation::Clip clip (cxx_driver); + + cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name) + << endl << endl; + + generate_driver_source (ctx); + } + + return sloc; + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } +} diff --git a/xsde/cxx/parser/generator.hxx b/xsde/cxx/parser/generator.hxx new file mode 100644 index 0000000..a261eca --- /dev/null +++ b/xsde/cxx/parser/generator.hxx @@ -0,0 +1,56 @@ +// file : xsde/cxx/parser/generator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_GENERATOR_HXX +#define CXX_PARSER_GENERATOR_HXX + +#include + +#include + +#include +#include + +#include // Path +#include + +#include +#include +#include + +namespace CXX +{ + namespace Parser + { + using namespace Cult::Types; + + class Generator + { + public: + static Void + usage (); + + static CLI::OptionsSpec + options_spec (); + + struct Failed {}; + + static UnsignedLong + generate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + TypeMap::Namespaces& type_map, + Boolean gen_driver, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + private: + Generator (); + }; + } +} + +#endif // CXX_PARSER_GENERATOR_HXX diff --git a/xsde/cxx/parser/impl-header.cxx b/xsde/cxx/parser/impl-header.cxx new file mode 100644 index 0000000..5d15ed2 --- /dev/null +++ b/xsde/cxx/parser/impl-header.cxx @@ -0,0 +1,309 @@ +// file : xsde/cxx/parser/impl-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (eimpl (e)); + String const& ret (ret_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + + os << "class " << name << ": " << "public " << + (mixin ? "virtual " : "") << ename (e); + + if (mixin) + os << "," << endl + << " public " << fq_name (base, "p:impl"); + + os << "{" + << "public:" << endl; + + if (tiein) + os << name << " ();" + << endl; + + os << "virtual void" << endl + << "pre ();" + << endl + << "virtual " << ret << endl + << post_name (e) << " ();"; + + if (tiein) + os << endl + << "private:" << endl + << fq_name (base, "p:impl") << " base_impl_;"; + + os << "};"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (eimpl (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String item (unclash (ename (l), "item")); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (l) + << "{" + << "public:" << endl + << "virtual void" << endl + << "pre ();" + << endl; + + // item + // + String const& arg (arg_type (t)); + + os << "virtual void" << endl + << item; + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + + // post + // + String const& ret (ret_type (l)); + + os << "virtual " << ret << endl + << post_name (l) << " ();" + << "};"; + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (eimpl (u)); + String const& ret (ret_type (u)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (u) + << "{" + << "public:" << endl + << "virtual void" << endl + << "pre ();" + << endl + << "virtual void" << endl + << "_characters (const " << string_type << "&);" + << endl + << "virtual " << ret << endl + << post_name (u) << " ();" + << "};"; + } + }; + + + // + // + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& arg (arg_type (e.type ())); + + os << "virtual void" << endl + << ename (e); + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& arg (arg_type (a.type ())); + + os << "virtual void" << endl + << ename (a); + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + } + }; + + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + String const& name (eimpl (c)); + String const& ret (ret_type (c)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (c); + + if (mixin && hb) + os << "," << endl + << " public " << fq_name (c.inherits ().base (), "p:impl"); + + os << "{" + << "public:" << endl; + + if (tiein && hb) + os << name << " ();" + << endl; + + os << "virtual void" << endl + << "pre ();" + << endl; + + // In case of an inheritance-by-restriction, we don't need to + // generate parser callbacks, etc. since they are the same as + // in the base. + // + if (!restriction_p (c)) + { + if (ha) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + + if (he) + { + os << "// Elements." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_callback_); + } + } + + os << "virtual " << ret << endl + << post_name (c) << " ();"; + + if (tiein && hb) + os << endl + << "private:" << endl + << fq_name (c.inherits ().base (), "p:impl") << " base_impl_;"; + + os << "};"; + } + + private: + Traversal::Compositor compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_impl_header (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::impl_header); + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/impl-header.hxx b/xsde/cxx/parser/impl-header.hxx new file mode 100644 index 0000000..43a7584 --- /dev/null +++ b/xsde/cxx/parser/impl-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/impl-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_IMPL_HEADER_HXX +#define CXX_PARSER_IMPL_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_impl_header (Context&); + } +} + +#endif // CXX_PARSER_IMPL_HEADER_HXX diff --git a/xsde/cxx/parser/impl-source.cxx b/xsde/cxx/parser/impl-source.cxx new file mode 100644 index 0000000..6b02425 --- /dev/null +++ b/xsde/cxx/parser/impl-source.cxx @@ -0,0 +1,543 @@ +// file : xsde/cxx/parser/impl-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (eimpl (e)); + String const& ret (ret_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + String const& base_ret (ret_type (base)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein) + os << name << "::" << endl + << name << " ()" << endl + << ": " << ename (e) << " (&base_impl_)" + << "{" + << "}"; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{" + << "}"; + + // post + // + os << ret << " " << name << "::" << endl + << post_name (e) << " ()" + << "{"; + + if (ret == base_ret) + { + os << (ret != L"void" ? "return " : "") << + post_name (base) << " ();"; + } + else if (ret == L"void") + { + os << arg_type (base) << " v = " << post_name (base) << " ();" + << endl; + + if (options.value ()) + os << "if (!_error ())" + << "{"; + + if (options.value ()) + { + PrintCall t (*this, e.name (), "v"); + t.dispatch (base); + } + else + os << "// TODO" << endl + << "//" << endl; + + { + DeleteCall t (*this, "v"); + t.dispatch (base); + } + + if (options.value ()) + os << "}"; + } + else + { + if (base_ret == L"void") + os << post_name (base) << " ();"; + else + { + os << arg_type (base) << " v = " << post_name (base) << " ();" + << endl; + + if (options.value ()) + os << "if (!_error ())" + << "{"; + + os << "// TODO" << endl + << "//" << endl + << "// return ... ;" << endl; + + { + DeleteCall t (*this, "v"); + t.dispatch (base); + } + + if (options.value ()) + os << "}"; + } + } + + os << "}"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (eimpl (l)); + SemanticGraph::Type& type (l.argumented ().type ()); + + String item (unclash (ename (l), "item")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{" + << "}"; + + // item + // + String const& arg (arg_type (type)); + + os << "void " << name << "::" << endl + << item; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << " " << item << ")"; + + os << "{"; + + if (arg != L"void") + { + if (options.value ()) + { + PrintCall t (*this, type.name (), item); + t.dispatch (type); + } + else + os << "// TODO" << endl + << "//" << endl; + + { + DeleteCall t (*this, item); + t.dispatch (type); + } + } + + os << "}"; + + // post + // + String const& ret (ret_type (l)); + + os << ret << " " << name << "::" << endl + << post_name (l) << " ()" + << "{"; + + if (ret != L"void") + os << "// TODO" << endl + << "//" << endl + << "// return ... ;" << endl; + + os << "}"; + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (eimpl (u)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{" + << "}"; + + // _characters + // + os << "void " << name << "::" << endl + << "_characters (const " << string_type << "& s)" + << "{"; + + if (options.value ()) + { + if (options.value ()) + os << "if (s.size () != 0)" + << "{" + << "printf (" << strlit (u.name () + L": ") << ");" + << "fwrite (s.data (), s.size (), 1, stdout);" + << "printf (\"\\n\");" + << "}"; + else + os << "std::cout << " << strlit (u.name () + L": ") << + " << s << std::endl;"; + } + else + os << "// TODO" << endl + << "//" << endl; + + os << "}"; + + // post + // + String const& ret (ret_type (u)); + + os << ret << " " << name << "::" << endl + << post_name (u) << " ()" + << "{"; + + if (ret != L"void") + os << "// TODO" << endl + << "//" << endl + << "// return ... ;" << endl; + + os << "}"; + } + }; + + // + // + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Complex; + + String const& name (ename (e)); + String const& arg (arg_type (e.type ())); + Complex& c (dynamic_cast (e.scope ())); + + os << "void " << eimpl (c) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << " " << name << ")"; + + os << "{"; + + if (arg != L"void") + { + if (options.value ()) + { + PrintCall t (*this, e.name (), name); + t.dispatch (e.type ()); + } + else + os << "// TODO" << endl + << "//" << endl; + + { + DeleteCall t (*this, name); + t.dispatch (e.type ()); + } + } + + os << "}"; + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Complex; + + String const& name (ename (a)); + String const& arg (arg_type (a.type ())); + Complex& c (dynamic_cast (a.scope ())); + + os << "void " << eimpl (c) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << " " << name << ")"; + + os << "{"; + + if (arg != L"void") + { + if (options.value ()) + { + PrintCall t (*this, a.name (), name); + t.dispatch (a.type ()); + } + else + os << "// TODO" << endl + << "//" << endl; + + { + DeleteCall t (*this, name); + t.dispatch (a.type ()); + } + } + + os << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + + String const& name (eimpl (c)); + String const& ret (ret_type (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein && hb) + os << name << "::" << endl + << name << " ()" << endl + << ": " << ename (c) << " (&base_impl_)" + << "{" + << "}"; + + // pre + // + os << "void " << name << "::" << endl + << "pre ()" + << "{" + << "}"; + + // Parser callbacks. + // + if (!restriction_p (c)) + { + names (c, names_attribute_callback_); + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + os << ret << " " << name << "::" << endl + << post_name (c) << " ()" + << "{"; + + if (hb) + { + SemanticGraph::Type& base (c.inherits ().base ()); + String const& base_ret (ret_type (base)); + + if (ret == base_ret) + { + os << (ret != L"void" ? "return " : "") << + post_name (base) << " ();"; + } + else if (ret == L"void") + { + os << arg_type (base) << " v = " << post_name (base) << " ();" + << endl; + + if (options.value ()) + os << "if (!_error ())" + << "{"; + + if (options.value ()) + { + PrintCall t (*this, c.name (), "v"); + t.dispatch (base); + } + else + os << "// TODO" << endl + << "//" << endl; + + { + DeleteCall t (*this, "v"); + t.dispatch (base); + } + + if (options.value ()) + os << "}"; + } + else + { + if (base_ret == L"void") + os << post_name (base) << " ();"; + else + { + os << arg_type (base) << " v = " << post_name (base) << " ();" + << endl; + + if (options.value ()) + os << "if (!_error ())" + << "{"; + + os << "// TODO" << endl + << "//" << endl + << "// return ... ;" << endl; + + { + DeleteCall t (*this, "v"); + t.dispatch (base); + } + + if (options.value ()) + os << "}"; + } + } + } + else + { + if (ret != L"void") + os << "// TODO" << endl + << "//" << endl + << "// return ... ;" << endl; + } + + os << "}"; + } + + private: + Traversal::Compositor compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_impl_source (Context& ctx) + { + if (ctx.options.value ()) + { + if (ctx.options.value ()) + ctx.os << "#include " << endl + << endl; + else + ctx.os << "#include " << endl + << endl; + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/impl-source.hxx b/xsde/cxx/parser/impl-source.hxx new file mode 100644 index 0000000..98c7961 --- /dev/null +++ b/xsde/cxx/parser/impl-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/impl-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_IMPL_SOURCE_HXX +#define CXX_PARSER_IMPL_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_impl_source (Context&); + } +} + +#endif // CXX_PARSER_IMPL_SOURCE_HXX diff --git a/xsde/cxx/parser/name-processor.cxx b/xsde/cxx/parser/name-processor.cxx new file mode 100644 index 0000000..bc0e7a5 --- /dev/null +++ b/xsde/cxx/parser/name-processor.cxx @@ -0,0 +1,1326 @@ +// file : xsde/cxx/parser/name-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "p:name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + schema_path_ (file), + skel_suffix_ (ops.value ()), + impl_suffix_ (ops.value ()), + schema (root), + schema_path (schema_path_), + impl (ops.value () || + ops.value () || + ops.value ()), + tiein (!ops.value () && + !ops.value ()), + skel_suffix (skel_suffix_), + impl_suffix (impl_suffix_), + global_type_names (global_type_names_), + validation (!ops.value ()), + polymorphic (ops.value ()) + { + } + + protected: + Context (Context& c) + : CXX::Context (c), + schema (c.schema), + schema_path (c.schema_path), + impl (c.impl), + tiein (c.tiein), + skel_suffix (c.skel_suffix), + impl_suffix (c.impl_suffix), + global_type_names (c.global_type_names), + validation (c.validation), + polymorphic (c.polymorphic) + { + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + private: + SemanticGraph::Path const schema_path_; + String const skel_suffix_; + String const impl_suffix_; + + Cult::Containers::Map global_type_names_; + + public: + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + Boolean const impl; + Boolean const tiein; + String const& skel_suffix; + String const& impl_suffix; + + Cult::Containers::Map& global_type_names; + + Boolean validation; + Boolean polymorphic; + }; + + // Primary names. + // + struct PrimaryParticle: Traversal::Element, Context + { + PrimaryParticle (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Element; + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + { + ec.set ("p:name", find_name (e.name (), set_)); + } + else + { + Element* prot ( + ec.get ("xsd-frontend-restriction-correspondence")); + + ec.set ("p:name", prot->context ().get ("p:name")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct PrimaryAttribute: Traversal::Attribute, Context + { + PrimaryAttribute (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Attribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + ac.set ("p:name", find_name (a.name (), set_)); + } + else + { + Attribute* prot ( + ac.get ("xsd-frontend-restriction-correspondence")); + + ac.set ("p:name", prot->context ().get ("p:name")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + + // + // Secondary names. + // + + struct ParticleTag: Traversal::Element, + Traversal::Any, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleTag (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Element; + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + { + String const base (ec.get ("p:name")); + ec.set ("p:tag", find_name (base, L"_tag", set_)); + } + else + { + Element* prot = ec.get ( + "xsd-frontend-restriction-correspondence"); + + ec.set ("p:tag", prot->context ().get ("p:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Any; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + ac.set ("p:tag", find_name (L"any", L"_tag", set_)); + else + { + Any* prot = ac.get ( + "xsd-frontend-restriction-correspondence"); + + ac.set ("p:tag", prot->context ().get ("p:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Compositor; + + SemanticGraph::Context& cc (c.context ()); + + if (!restriction_) + { + cc.set ("p:tag", find_name (L"choice", L"_tag", set_)); + } + else + { + Compositor* prot = cc.get ( + "xsd-frontend-restriction-correspondence"); + + cc.set ("p:tag", prot->context ().get ("p:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + using SemanticGraph::Compositor; + + SemanticGraph::Context& sc (s.context ()); + + if (!restriction_) + { + sc.set ("p:tag", find_name (L"sequence", L"_tag", set_)); + } + else + { + Compositor* prot = sc.get ( + "xsd-frontend-restriction-correspondence"); + + sc.set ("p:tag", prot->context ().get ("p:tag")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct SecondaryCompositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + SecondaryCompositor (Context& c, NameSet& set, Boolean restriction) + : Context (c), + set_ (set), + restriction_ (restriction), + particle_tag_ (c, set, restriction) + { + contain_particle_tag_ >> particle_tag_; + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it cannot be used in restriction. + // + if (a.min () == 0) + { + a.context ().set ( + "p:present", find_name (L"all", L"_present", set_)); + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () == c.contains_end ()) + return; + + SemanticGraph::Context& cc (c.context ()); + + if (!restriction_) + { + cc.set ("p:arm-tag", find_name (L"choice", L"_arm_tag", set_)); + Traversal::Choice::contains (c, contain_particle_tag_); + cc.set ("p:arm", find_name (L"choice", L"_arm", set_)); + } + else + { + SemanticGraph::Compositor& b ( + *cc.get ( + "xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + + cc.set ("p:arm-tag", bc.get ("p:arm-tag")); + Traversal::Choice::contains (c, contain_particle_tag_); + cc.set ("p:arm", bc.get ("p:arm")); + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + SemanticGraph::Context& sc (s.context ()); + + if (!restriction_) + { + if (s.max () != 1) + sc.set ("p:next", find_name (L"sequence", L"_next", set_)); + else if (s.min () == 0) + sc.set ("p:present", find_name (L"sequence", L"_present", set_)); + } + else + { + // Root compositor that models inheritance by extension + // may not have an association. + // + if (sc.count ("xsd-frontend-restriction-correspondence")) + { + SemanticGraph::Compositor& b ( + *sc.get ( + "xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + + if (b.max () != 1) + { + sc.set ("p:next", bc.get ("p:next")); + + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (s.min () == 0) + sc.set ("p:present", + find_name (L"sequence", L"_present", set_)); + } + else if (b.min () == 0) + sc.set ("p:present", bc.get ("p:present")); + } + } + + Traversal::Sequence::traverse (s); + } + + private: + NameSet& set_; + Boolean restriction_; + + ParticleTag particle_tag_; + Traversal::ContainsParticle contain_particle_tag_; + }; + + struct SecondaryParticle: Traversal::Element, Context + { + SecondaryParticle (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + Boolean poly ( + polymorphic && !e.type ().context ().count ("anonymous")); + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + { + String const& base (ec.get ("p:name")); + + ec.set ("p:parser", find_name (base + L"_parser", set_)); + ec.set ("p:member", find_name (base + L"_parser_", set_)); + + if (poly) + { + ec.set ( + "p:member-cache", find_name (base + L"_parser_cache_", set_)); + + ec.set ( + "p:member-map", find_name (base + L"_parser_map_", set_)); + } + } + else + { + SemanticGraph::Context& bc ( + ec.get ( + "xsd-frontend-restriction-correspondence")->context ()); + + ec.set ("p:parser", bc.get ("p:parser")); + ec.set ("p:member", bc.get ("p:member")); + + if (poly) + { + ec.set ("p:member-cache", bc.get ("p:member-cache")); + ec.set ("p:member-map", bc.get ("p:member-map")); + } + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct SecondaryAttribute: Traversal::Attribute, Context + { + SecondaryAttribute (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Attribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + String const& base (ac.get ("p:name")); + + a.context ().set ( + "p:parser", find_name (base + L"_parser", set_)); + + a.context ().set ( + "p:member", find_name (base + L"_parser_", set_)); + } + else + { + SemanticGraph::Context& bc ( + ac.get ( + "xsd-frontend-restriction-correspondence")->context ()); + + ac.set ("p:parser", bc.get ("p:parser")); + ac.set ("p:member", bc.get ("p:member")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // Use processed name. + // + String const& name (cc.get ("p:name")); + + // We leave this set around to allow other mappings to use + // this information. + // + cc.set ("cxx-parser-name-processor-member-set", NameSet ()); + NameSet& member_set ( + cc.get ("cxx-parser-name-processor-member-set")); + + member_set.insert (name); + + // Add our base's members to the initial list unless we are + // inheriting by restriction in which case we need to have + // the same names as our base. + // + Boolean restriction (false); + + if (c.inherits_p ()) + { + // @@ What if this types name is the same as one of base's + // members? + // + SemanticGraph::Type& base (c.inherits ().base ()); + + if (base.is_a ()) + { + if (!base.context ().count ( + "cxx-parser-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_set ( + base.context ().get ( + "cxx-parser-name-processor-member-set")); + + member_set.insert (base_set.begin (), base_set.end ()); + + // Inheritance by restriction from anyType is a special case. + // + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + } + } + + // First assign the "primary" names. + // + { + if (c.contains_compositor_p ()) + { + PrimaryParticle particle (*this, member_set, restriction); + Traversal::Compositor compositor; + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + + // + // + PrimaryAttribute attribute (*this, member_set, restriction); + Traversal::Names names (attribute); + + Complex::names (c, names); + } + + // Assign "secondary" names. + // + { + if (c.contains_compositor_p ()) + { + // In case of validation we generate some extra callbacks + // for compositors. + // + if (validation) + { + SecondaryParticle particle (*this, member_set, restriction); + SecondaryCompositor compositor (*this, member_set, restriction); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + else + { + SecondaryParticle particle (*this, member_set, restriction); + Traversal::Compositor compositor; + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + } + + // + // + SecondaryAttribute attribute (*this, member_set, restriction); + Traversal::Names names (attribute); + + Complex::names (c, names); + } + } + }; + + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& c (t.context ()); + String const& n (t.name ()); + + String name (find_name (n + skel_suffix, set_)); + c.set ("p:name", name); + + // Assign the post_* name. + // + c.set ("p:post", find_post_name (t)); + + if (tiein) + c.set ("p:tiein", escape (n + L"_impl_")); + + // Note that we do not add this name to the set so that it + // does not influence other names. + // + if (impl) + c.set ("p:impl", escape (n + impl_suffix)); + } + + private: + String + find_post_name (SemanticGraph::Type& t) + { + String const& n (t.name ()); + + // It is possible that our base has the same type name (just + // in a different namespaces). Avoid name clash in this case. + // + using SemanticGraph::Complex; + + Complex* c = dynamic_cast (&t); + + if (c == 0 || !c->inherits_p ()) + { + return escape (L"post_" + n); + } + else + { + NameSet set; + + // Collect all base's post_*. In some mutual inclusion cases it + // is possible that our base won't have the post name assigned + // yet. In this situation will will have to figure it out + // ourselves (we can do it since we use the "raw" type name). + // + SemanticGraph::Type* b (&c->inherits ().base ()); + + while (true) + { + if (b->context ().count ("p:post")) + set.insert (b->context ().get ("p:post")); + else + set.insert (find_post_name (*b)); + + Complex* cb (dynamic_cast (b)); + + if (cb != 0 && cb->inherits_p ()) + { + b = &cb->inherits ().base (); + continue; + } + + break; + } + + String base_name (escape (L"post_" + n)); + String post (base_name); + + for (UnsignedLong i (1); set.find (post) != set.end (); ++i) + { + std::wostringstream os; + os << i; + post = base_name + os.str (); + } + + return post; + } + } + + private: + NameSet& set_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + }; + + struct FundType : Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + + { + FundType (Context& c) + : Context (c) + { + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + set_names (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + set_names (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + set_names (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + set_names (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + set_names (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + set_names (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + set_names (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + set_names (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + set_names (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + set_names (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + set_names (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + set_names (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + set_names (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + set_names (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + set_names (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + set_names (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + set_names (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + set_names (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + set_names (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + set_names (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + set_names (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + set_names (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + set_names (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + set_names (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + set_names (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + set_names (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + set_names (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + set_names (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + set_names (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + set_names (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + set_names (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + set_names (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + set_names (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + set_names (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + set_names (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + set_names (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + set_names (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + set_names (t, "gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + set_names (t, "gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + set_names (t, "gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + set_names (t, "gyear");; + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + set_names (t, "gyear_month"); + + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + set_names (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + set_names (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + set_names (t, "entities"); + } + + private: + String + make_skel_name (String const& base) + { + return escape (base + skel_suffix); + } + + String + make_impl_name (String const& base) + { + return escape (base + impl_suffix); + } + + Void + set_names (SemanticGraph::Type& t, String const& name) + { + SemanticGraph::Context& c (t.context ()); + + WideChar const* ns = validation + ? L"::xsde::cxx::parser::validating::" + : L"::xsde::cxx::parser::non_validating::"; + + String skel (make_skel_name (name)); + c.set ("p:name", skel); + c.set ("p:real-name", ns + skel); + + String impl (make_impl_name (name)); + c.set ("p:impl", impl); + c.set ("p:real-impl", ns + impl); + + c.set ("p:post", L"post_" + name); + + if (tiein) + c.set ("p:tiein", name + L"_impl_"); + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count ("cxx-parser-name-processor-seen")) + { + s.context ().set ("cxx-parser-name-processor-seen", true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-parser-name-processor-seen")) + { + s.context ().set ("cxx-parser-name-processor-seen", true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-parser-name-processor-seen")) + { + s.context ().set ("cxx-parser-name-processor-seen", true); + Traversal::Imports::traverse (i); + } + } + }; + + // Go into implied schemas while making sure we don't process + // the same stuff more than once. + // + struct Implies: Traversal::Implies + { + virtual Void + traverse (SemanticGraph::Implies& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-parser-name-processor-seen")) + { + s.context ().set ("cxx-parser-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // Pass one - assign names to fundamental types. + // + { + Traversal::Schema schema; + Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Pass two - assign names to global types. This pass cannot + // be combined with pass three because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count ("cxx-parser-name-processor-seen")) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-parser-name-processor-seen", true); + + schema.dispatch (tu); + } + + // Pass three - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + Complex complex (ctx); + + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + } + + Void NameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/parser/name-processor.hxx b/xsde/cxx/parser/name-processor.hxx new file mode 100644 index 0000000..8d55f30 --- /dev/null +++ b/xsde/cxx/parser/name-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/parser/name-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_NAME_PROCESSOR_HXX +#define CXX_PARSER_NAME_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Parser + { + using namespace Cult::Types; + + class NameProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_PARSER_NAME_PROCESSOR_HXX diff --git a/xsde/cxx/parser/parser-forward.cxx b/xsde/cxx/parser/parser-forward.cxx new file mode 100644 index 0000000..3ce73de --- /dev/null +++ b/xsde/cxx/parser/parser-forward.cxx @@ -0,0 +1,112 @@ +// file : xsde/cxx/parser/parser-forward.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + os << "class " << ename (e) << ";"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + os << "class " << ename (l) << ";"; + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + os << "class " << ename (u) << ";"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + os << "class " << ename (c) << ";"; + } + }; + } + + Void + generate_parser_forward (Context& ctx) + { + ctx.os << "// Forward declarations" << endl + << "//" << endl; + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + + ctx.os << endl; + } + } +} diff --git a/xsde/cxx/parser/parser-forward.hxx b/xsde/cxx/parser/parser-forward.hxx new file mode 100644 index 0000000..1ddeb39 --- /dev/null +++ b/xsde/cxx/parser/parser-forward.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/parser-forward.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_PARSER_FORWARD_HXX +#define CXX_PARSER_PARSER_FORWARD_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_parser_forward (Context&); + } +} + +#endif // CXX_PARSER_PARSER_FORWARD_HXX diff --git a/xsde/cxx/parser/parser-header.cxx b/xsde/cxx/parser/parser-header.cxx new file mode 100644 index 0000000..95642ab --- /dev/null +++ b/xsde/cxx/parser/parser-header.cxx @@ -0,0 +1,1818 @@ +// file : xsde/cxx/parser/parser-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + String fq_base (fq_name (base)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << fq_base + << "{" + << "public:" << endl + << "// Parser callbacks. Override them in your " << + "implementation." << endl + << "//" << endl; + + os << "// virtual void" << endl + << "// pre ();" << endl + << endl; + + String const& ret (ret_type (e)); + String const& base_ret (ret_type (base)); + + Boolean same (ret == base_ret); + + os << "virtual " << ret << endl + << post_name (e) << " ()" << + (same || ret == L"void" ? ";" : " = 0;"); + + if (poly_code) + { + os << endl + << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;"; + } + + if (tiein) + { + os << endl + << "// Constructor." << endl + << "//" << endl + << name << " (" << fq_base << "* tiein);" + << endl; + + os << "// Implementation details." << endl + << "//" << endl; + + // If our base has pure virtual post, override it here. + // + Boolean base_same ( + base.inherits_p () && + base_ret == ret_type (base.inherits ().base ())); + + if (!(base_same || base_ret == L"void")) + os << "virtual " << base_ret << endl + << post_name (base) << " ();" + << endl; + + os << "protected:" << endl + << name << "* " << etiein (e) << ";" + << name << " (" << name << "*, void*);"; + } + + os << "};"; + } + }; + + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + String item_type (fq_name (t)); + + String item (unclash (name, "item")); + + os << "class " << name << ": public " << list_base + << "{" + << "public:" << endl + << "// Parser callbacks. Override them in your " << + "implementation." << endl + << "//" << endl; + + // pre + // + os << "// virtual void" << endl + << "// pre ();" << endl + << endl; + + // item + // + String const& arg (arg_type (t)); + + os << "virtual void" << endl + << item; + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + + // post + // + String const& ret (ret_type (l)); + + os << "virtual " << ret << endl + << post_name (l) << " ()" << (ret == L"void" ? ";" : " = 0;") + << endl; + + + // + // + os << "// Parser construction API." << endl + << "//" << endl; + + // item_parser + // + os << "void" << endl + << unclash (name, "item_parser") << " (" << item_type << "&);" + << endl; + + // parsers + // + os << "void" << endl + << "parsers (" << item_type << "& /* item */);" + << endl; + + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + + // c-tor + // + os << "// Constructor." << endl + << "//" << endl + << name << " ();" + << endl; + + if (poly_code) + { + os << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;" + << endl; + } + + // + // + os << "// Implementation details." << endl + << "//" << endl + << "protected:" << endl; + + if (tiein) + { + os << name << "* " << etiein (l) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + os << "virtual void" << endl + << "_xsde_parse_item (const " << string_type << "&);" + << endl; + + os << "protected:" << endl + << item_type << "* _xsde_" << item << "_;" + << "};"; + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + + os << "class " << name << ": public " << simple_base + << "{" + << "public:" << endl + << "// Parser callbacks. Override them in your " << + "implementation." << endl + << "//" << endl; + + os << "// virtual void" << endl + << "// pre ();" << endl + << "//" << endl + << "// virtual void" << endl + << "// _characters (const " << string_type << "&);" << endl + << endl; + + String const& ret (ret_type (u)); + + os << "virtual " << ret << endl + << post_name (u) << " ()" << (ret == L"void" ? ";" : " = 0;"); + + if (poly_code) + { + os << endl + << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;"; + } + + if (tiein) + { + // c-tor + // + os << endl + << "// Constructor." << endl + << "//" << endl + << name << " ();" + << endl; + + // + // + os << "// Implementation details." << endl + << "//" << endl + << "protected:" << endl + << name << "* " << etiein (u) << ";" + << name << " (" << name << "*, void*);"; + } + + os << "};"; + } + }; + + // + // Callbacks. + // + + struct ParticleTag: Traversal::Particle, Context + { + ParticleTag (Context& c) + : Context (c), first_ (true) + { + } + + virtual Void + traverse (Type& p) + { + if (first_) + first_ = false; + else + os << "," << endl; + + os << etag (p); + } + + private: + Boolean first_; + }; + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (correspondent (a) == 0) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + os << "virtual void" << endl + << epresent (a) << " ();" + << endl; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () == c.contains_end ()) + return; + + if (correspondent (c) == 0) + { + os << "enum " << earm_tag (c) + << "{"; + + { + ParticleTag particle (*this); + Traversal::ContainsParticle contain_particle (particle); + Traversal::Choice::contains (c, contain_particle); + } + + os << "};"; + + os << "virtual void" << endl + << earm (c) << " (" << earm_tag (c) << ");" + << endl; + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // Root compositor that models inheritance by extension + // may not have an association so we may fall through + // in to the 'if' case even though this is a restriction. + // This is ok since such a compositor always has max == + // min == 1 and so nothing is generated. + // + if (SemanticGraph::Compositor* b = correspondent (s)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (b->max () != 1 && s.min () == 0) + { + os << "virtual void" << endl + << epresent (s) << " ();" + << endl; + } + } + else + { + if (s.max () != 1) + { + os << "virtual void" << endl + << enext (s) << " ();" + << endl; + } + else if (s.min () == 0) + { + os << "virtual void" << endl + << epresent (s) << " ();" + << endl; + } + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (correspondent (e) == 0) + { + String const& arg (arg_type (e.type ())); + + os << "virtual void" << endl + << ename (e); + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + } + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& arg (arg_type (a.type ())); + + os << "virtual void" << endl + << ename (a); + + if (arg == L"void") + os << " ();"; + else + os << " (" << arg << ");"; + + os << endl; + } + }; + + + // + // + struct ParticleAccessor: Traversal::Element, Context + { + ParticleAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& parser (eparser (e)); + + os << "void" << endl + << parser << " (" << fq_name (e.type ()) << "&);" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + os << "void" << endl + << parser << " (" << parser_map << "&);" + << endl; + } + } + }; + + struct AttributeAccessor: Traversal::Attribute, Context + { + AttributeAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << "void" << endl + << eparser (a) << " (" << fq_name (a.type ()) << "&);" + << endl; + } + }; + + + // + // + struct ParticleMember: Traversal::Element, Context + { + ParticleMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String type (fq_name (e.type ())); + + os << type << "* " << emember (e) << ";"; + + if (poly_code && !anonymous (e.type ())) + { + os << type << "* " << emember_cache (e) << ";" + << parser_map << "* " << emember_map (e) << ";" + << endl; + } + } + }; + + struct AttributeMember: Traversal::Attribute, Context + { + AttributeMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << fq_name (a.type ()) << "* " << emember (a) << ";"; + } + }; + + // + // + struct Particle: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + Particle (Context& c) + : Context (c) + { + *this >> contains_particle_ >> *this; + } + + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context().count ("p:comp-number")) + return; + + UnsignedLong state_count ( + a.context().get ("p:state-count")); + + os << "void" << endl + << "all_0 (unsigned long&," << endl + << "unsigned char*," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&," << endl; + + if (poly_runtime) + os << "const char*," << endl; + + os << "bool);" + << endl + << "unsigned char v_all_first_[" << state_count << "UL];" + << "::xsde::cxx::parser::validating::all_stack v_all_count_;" + << endl; + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (!c.context().count ("p:comp-number")) + return; + + UnsignedLong n (c.context ().get ("p:comp-number")); + + os << "void" << endl + << "choice_" << n << " (unsigned long&," << endl + << "unsigned long&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&," << endl; + + if (poly_runtime) + os << "const char*," << endl; + + os << "bool);" + << endl; + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (!s.context().count ("p:comp-number")) + return; + + UnsignedLong n (s.context ().get ("p:comp-number")); + + os << "void" << endl + << "sequence_" << n << " (unsigned long&," << endl + << "unsigned long&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&," << endl; + + if (poly_runtime) + os << "const char*," << endl; + + os << "bool);" + << endl; + + Traversal::Sequence::traverse (s); + } + + private: + Traversal::ContainsParticle contains_particle_; + }; + + + // + // + struct AttributeValidationState: Traversal::Attribute, Context + { + AttributeValidationState (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + if (!a.optional ()) + { + os << "bool " << ename (a) << ";"; + } + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_val_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_accessor_ (c), + attribute_accessor_ (c), + particle_member_ (c), + attribute_member_ (c), + attribute_validation_state_ (c) + { + // Callback. + // + if (validation) + { + contains_compositor_callback_ >> compositor_callback_val_; + compositor_callback_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_val_; + } + else + { + contains_compositor_callback_ >> compositor_callback_non_val_; + compositor_callback_non_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_non_val_; + } + + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Accessor. + // + contains_compositor_accessor_ >> compositor_accessor_; + compositor_accessor_ >> contains_particle_accessor_; + contains_particle_accessor_ >> compositor_accessor_; + contains_particle_accessor_ >> particle_accessor_; + + names_attribute_accessor_ >> attribute_accessor_; + + // Member. + // + contains_compositor_member_ >> compositor_member_; + compositor_member_ >> contains_particle_member_; + contains_particle_member_ >> compositor_member_; + contains_particle_member_ >> particle_member_; + + names_attribute_member_ >> attribute_member_; + + // + // + names_attribute_validation_state_ >> attribute_validation_state_; + } + + virtual Void + traverse (Type& c) + { + String const& name (ename (c)); + + // In case of an inheritance-by-restriction, we don't need to + // generate parser callbacks, etc. since they are the same as + // in the base. We only need the parsing/validation code. + // + Boolean hb (c.inherits_p ()); + Boolean restriction (restriction_p (c)); + + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + Boolean haa (has (c)); + + Boolean hra (false); // Has required attribute. + if (ha) + { + RequiredAttributeTest test (hra); + Traversal::Names names_test (test); + names (c, names_test); + } + + // + // + os << "class " << name << ": public "; + + if (hb) + os << (mixin ? "virtual " : "") << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << "{" + << "public:" << endl + << "// Parser callbacks. Override them in your " << + "implementation." << endl + << "//" << endl; + + // pre + // + os << "// virtual void" << endl + << "// pre ();" << endl + << endl; + + // Member callbacks. + // + if (!restriction) + { + if (ha) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + } + + if (!restriction || validation) + { + if (he || hae) + { + if (!restriction) + os << "// Elements." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_callback_); + } + } + + // post + // + String const& ret (ret_type (c)); + Boolean same (hb && ret == ret_type (c.inherits ().base ())); + + os << "virtual " << ret << endl + << post_name (c) << " ()" << + (same || ret == L"void" ? ";" : " = 0;") + << endl; + + // + // + if (!restriction && (he || ha)) + { + os << "// Parser construction API." << endl + << "//" << endl; + + os << "void" << endl + << "parsers ("; + + { + ParserParamDecl decl (*this, false); + decl.traverse (c); + } + + os << ");" + << endl; + + if (ha) + { + os << "// Individual attribute parsers." << endl + << "//" << endl; + + names (c, names_attribute_accessor_); + } + + if (he) + { + os << "// Individual element parsers." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_accessor_); + } + } + + if (!restriction && (he || ha) && reset) + { + os << "virtual void" << endl + << "_reset ();" + << endl; + } + + // Default c-tor. + // + if (tiein || + (!restriction && (he || ha)) || + (validation && (he || hae || hra))) + { + os << "// Constructor." << endl + << "//" << endl; + + if (hb && tiein) + os << name << " (" << fq_name (c.inherits ().base ()) << + "* tiein);" + << endl; + else + os << name << " ();" + << endl; + } + + if (poly_code) + { + os << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;" + << endl; + } + + // Implementation. + // + if (tiein || he || ha || (validation && (hae || haa))) + { + os << "// Implementation details." << endl + << "//" << endl; + } + + if (tiein) + { + if (hb) + { + // If our base has pure virtual post, override it here. + // + SemanticGraph::Type& base (c.inherits ().base ()); + + String const& base_ret (ret_type (base)); + + Boolean base_same ( + base.inherits_p () && + base_ret == ret_type (base.inherits ().base ())); + + if (!(base_same || base_ret == L"void")) + os << "virtual " << base_ret << endl + << post_name (base) << " ();" + << endl; + } + + os << "protected:" << endl + << name << "* " << etiein (c) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + // element + // + if (he || (validation && hae)) + { + os << "protected:" << endl; + + // _start_element_impl + // + os << "virtual bool" << endl + << "_start_element_impl (const " << string_type << "&," << endl + << "const " << string_type << "&"; + + if (poly_runtime) + os << "," << endl + << "const char*"; + + os << ");" + << endl; + + // end_element + // + os << "virtual bool" << endl + << "_end_element_impl (const " << string_type << "&," << endl + << "const " << string_type << "&);" + << endl; + } + + // attribute + // + if (validation) + { + if (ha || haa) + os << "protected:" << endl; + + if (ha) + { + os << "virtual bool" << endl + << "_attribute_impl_phase_one (const " << string_type << + "&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&);" << endl + << endl; + } + + if (haa) + { + os << "virtual bool" << endl + << "_attribute_impl_phase_two (const " << string_type << + "&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&);" + << endl; + } + } + else + { + if (ha) + { + os << "protected:" << endl + << "virtual bool" << endl + << "_attribute_impl (const " << string_type << "&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&);" + << endl; + } + } + + // characters + // + if (validation && c.mixed ()) + { + os << "protected:" << endl + << "virtual bool" << endl + << "_characters_impl (const " << string_type << "&);" + << endl; + } + + if (!restriction && (he || ha)) + { + os << "protected:" << endl; + + if (ha) + names (c, names_attribute_member_); + + if (he) + contains_compositor (c, contains_compositor_member_); + + os << endl; + } + + if (validation && (he || hae)) + { + UnsignedLong depth (c.context ().get ("p:depth")); + + os << "protected:" << endl; + + os << "struct v_state_descr_" + << "{" + << "void (" << fq_name (c) << "::*func) (" << endl + << "unsigned long&," << endl + << "unsigned long&," << endl + << "const " << string_type << "&," << endl + << "const " << string_type << "&," << endl; + + if (poly_runtime) + os << "const char*," << endl; + + os << "bool);" + << "unsigned long state;" + << "unsigned long count;" + << "};"; + + // Allocate one extra slot for the special state. + // + os << "struct v_state_" + << "{" + << "v_state_descr_ data[" << depth + 1 << "UL];" + << "unsigned long size;" + << "};"; + + os << "v_state_ v_state_first_;" + << "::xsde::cxx::parser::stack v_state_stack_;" + << endl; + + os << "virtual void" << endl + << "_pre_e_validate ();" + << endl; + + os << "virtual void" << endl + << "_post_e_validate ();" + << endl; + + Particle t (*this); + t.dispatch (c.contains_compositor ().compositor ()); + } + + if (validation && hra) + { + os << "protected:" << endl; + + os << "struct v_state_attr_" + << "{"; + + names (c, names_attribute_validation_state_); + + os << "};"; + + os << "v_state_attr_ v_state_attr_first_;" + << "::xsde::cxx::parser::stack v_state_attr_stack_;" + << endl; + + os << "virtual void" << endl + << "_pre_a_validate ();" + << endl; + + os << "virtual void" << endl + << "_post_a_validate ();" + << endl; + } + + os << "};"; + } + + private: + // + // + CompositorCallback compositor_callback_val_; + Traversal::Compositor compositor_callback_non_val_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_accessor_; + ParticleAccessor particle_accessor_; + Traversal::ContainsCompositor contains_compositor_accessor_; + Traversal::ContainsParticle contains_particle_accessor_; + + AttributeAccessor attribute_accessor_; + Traversal::Names names_attribute_accessor_; + + // + // + Traversal::Compositor compositor_member_; + ParticleMember particle_member_; + Traversal::ContainsCompositor contains_compositor_member_; + Traversal::ContainsParticle contains_particle_member_; + + AttributeMember attribute_member_; + Traversal::Names names_attribute_member_; + + // + // + AttributeValidationState attribute_validation_state_; + Traversal::Names names_attribute_validation_state_; + }; + + struct FundType : Context, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + { + FundType (Context& c) + : Context (c), xs_ns_ (xs_ns_name ()) + { + impl_ns_ = "::xsde::cxx::parser::"; + impl_ns_ += (validation ? L"validating" : L"non_validating"); + + if (options.value ()) + { + qname_type_ = xs_ns_ + L"::qname*"; + string_type_ = L"char*"; + } + else + { + qname_type_ = xs_ns_ + L"::qname"; + string_type_ = L"::std::string"; + } + + string_seq_type_ = xs_ns_ + L"::string_sequence*"; + buffer_type_ = xs_ns_ + L"::buffer*"; + + if (options.value ()) + { + long_type_ = L"long"; + unsigned_long_type_ = L"unsigned long"; + } + else + { + long_type_ = L"long long"; + unsigned_long_type_ = L"unsigned long long"; + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + gen_typedef (t, "void"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + gen_typedef (t, "void"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + gen_typedef (t, "bool"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + gen_typedef (t, "signed char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + gen_typedef (t, "unsigned char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + gen_typedef (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + gen_typedef (t, "unsigned short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + gen_typedef (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + gen_typedef (t, "unsigned int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + gen_typedef (t, long_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + gen_typedef (t, unsigned_long_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + gen_typedef (t, "unsigned long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + gen_typedef (t, "unsigned long"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + gen_typedef (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + gen_typedef (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + gen_typedef (t, "double"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + nmtoken_ = gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + // NMTOKENS uses NMTOKEN implementation to parse individual items. + // As a result, we don't generate NMTOKENS if we didn't generate + // NMTOKEN. Here we assume NMTOKEN is handled before NMTOKENS. + // + if(nmtoken_) + gen_typedef (t, string_seq_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + gen_typedef (t, string_type_); + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + gen_typedef (t, qname_type_); + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + idref_ = gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + // IDREFS uses IDREF implementation to parse individual items. + // As a result, we don't generate IDREFS if we didn't generate + // IDREF. Here we assume IDREF is handled before IDREFS. + // + if (idref_) + gen_typedef (t, string_seq_type_); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + gen_typedef (t, string_type_); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + gen_typedef (t, buffer_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + gen_typedef (t, buffer_type_); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + gen_typedef (t, xs_ns_ + L"::date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + gen_typedef (t, xs_ns_ + L"::date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + gen_typedef (t, xs_ns_ + L"::duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + gen_typedef (t, xs_ns_ + L"::gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + gen_typedef (t, xs_ns_ + L"::gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + gen_typedef (t, xs_ns_ + L"::gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + gen_typedef (t, xs_ns_ + L"::gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + gen_typedef (t, xs_ns_ + L"::gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + gen_typedef (t, xs_ns_ + L"::time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&) + { + } + + private: + Boolean + gen_typedef (SemanticGraph::Type& t, String const& type) + { + if (ret_type (t) == type) + { + SemanticGraph::Context& c (t.context ()); + + String const& real_name (c.get ("p:real-name")); + String const& name (c.get ("p:name")); + + os << "typedef " << real_name << " " << name << ";"; + + String const& real_impl (c.get ("p:real-impl")); + String const& impl (c.get ("p:impl")); + + os << "typedef " << real_impl << " " << impl << ";" + << endl; + + return true; + } + + return false; + } + + String xs_ns_; + String impl_ns_; + String qname_type_; + String string_type_; + String buffer_type_; + String string_seq_type_; + String long_type_; + String unsigned_long_type_; + + Boolean idref_; + Boolean nmtoken_; + }; + + struct FundNamespace : Namespace, Context + { + FundNamespace (Context& c) + : Namespace (c), Context (c) + { + } + + void + traverse (Type& ns) + { + pre (ns); + + String impl ("::xsde::cxx::parser::"); + impl += (validation ? L"validating" : L"non_validating"); + + String const c (char_type); + + os << "// Built-in XML Schema types mapping." << endl + << "//" << endl + << "using ::xsde::cxx::string_sequence;" + << "using ::xsde::cxx::qname;" + << "using ::xsde::cxx::buffer;" + << "using ::xsde::cxx::time_zone;" + << "using ::xsde::cxx::gday;" + << "using ::xsde::cxx::gmonth;" + << "using ::xsde::cxx::gyear;" + << "using ::xsde::cxx::gmonth_day;" + << "using ::xsde::cxx::gyear_month;" + << "using ::xsde::cxx::date;" + << "using ::xsde::cxx::time;" + << "using ::xsde::cxx::date_time;" + << "using ::xsde::cxx::duration;" + << endl; + + os << "// Base parser skeletons." << endl + << "//" << endl + << "using ::xsde::cxx::parser::parser_base;" + << "typedef " << impl << "::empty_content " << + "parser_empty_content;" + << "typedef " << impl << "::simple_content " << + "parser_simple_content;" + << "typedef " << impl << "::complex_content " << + "parser_complex_content;" + << "typedef " << impl << "::list_base parser_list_base;" + << endl; + + if (poly_code) + { + os << "// Parser map interface and default implementation." << endl + << "//" << endl + << "using ::xsde::cxx::parser::parser_map;" + << "using ::xsde::cxx::parser::parser_map_impl;" + << endl; + + os << "// Substitution and inheritance hashmaps load querying." << endl + << "//" << endl + << "using ::xsde::cxx::parser::parser_smap_buckets;" + << "using ::xsde::cxx::parser::parser_smap_elements;"; + + if (validation) + os << "using ::xsde::cxx::parser::validating::parser_imap_buckets;" + << "using ::xsde::cxx::parser::validating::parser_imap_elements;"; + + os << endl; + } + + os << "// Parser skeletons and implementations for the XML Schema" << endl + << "// built-in types." << endl + << "//" << endl; + + names (ns); + + os << "// Read-only string." << endl + << "//" << endl + << "using ::xsde::cxx::ro_string;" + << endl; + + os << "// Error codes." << endl + << "//" << endl; + + if (!exceptions) + os << "using xsde::cxx::sys_error;"; + + os << "typedef xsde::cxx::parser::expat::xml_error " << + "parser_xml_error;"; + + if (validation) + os << "typedef xsde::cxx::schema_error parser_schema_error;"; + + os << endl; + + if (exceptions) + { + os << "// Exceptions." << endl + << "//" << endl + << "typedef xsde::cxx::parser::exception parser_exception;" + << "typedef xsde::cxx::parser::xml parser_xml;"; + + if (validation) + os << "typedef xsde::cxx::parser::schema parser_schema;"; + + os << endl; + } + else + os << "// Error object." << endl + << "//" << endl + << "typedef xsde::cxx::parser::error parser_error;" + << endl; + + os << "// Document parser." << endl + << "//" << endl + << "using xsde::cxx::parser::expat::document_pimpl;" + << endl; + + os << "// Parser context." << endl + << "//" << endl + << "typedef xsde::cxx::parser::context parser_context;" + << endl; + + post (ns); + } + }; + } + + Void + generate_parser_header (Context& ctx, Boolean generate_xml_schema) + { + NarrowString extern_xml_schema; + + if (!generate_xml_schema) + extern_xml_schema = ctx.options.value (); + + if (extern_xml_schema) + { + String name (ctx.hxx_expr->merge (extern_xml_schema)); + + ctx.os << "#include " << ctx.process_include_path (name) << endl + << endl; + + // Generate includes that came from the type map. + // + if (ctx.schema_root.context ().count ("p:includes")) + { + typedef Cult::Containers::Set Includes; + + Includes& is ( + ctx.schema_root.context ().get ("p:includes")); + + for (Includes::ConstReverseIterator i (is.rbegin ()); + i != is.rend (); ++i) + { + ctx.os << "#include " << *i << endl; + } + + ctx.os << endl; + } + } + else + { + ctx.os << "#include " << endl + << "#include " << endl + << endl; + + // Data types. + // + ctx.os << "#include " << endl + << endl; + + // Error handling. + // + if (ctx.exceptions) + ctx.os << "#include " << endl + << endl; + else + { + ctx.os << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl; + + ctx.os << "#include " << endl + << "#include " << endl + << endl; + } + + // Polymorphism support. + // + if (ctx.poly_code) + { + ctx.os << "#include " << endl + << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl; + + ctx.os << endl; + } + + // Parsers. + // + if (ctx.validation) + ctx.os << "#include " << endl + << "#include " << endl + << "#include " << endl + << endl; + else + ctx.os << "#include " << endl + << "#include " << endl + << "#include " << endl + << endl; + + // Document. + // + ctx.os << "#include " << endl + << endl; + + // Generate includes that came from the type map. + // + if (ctx.schema_root.context ().count ("p:includes")) + { + typedef Cult::Containers::Set Includes; + + Includes& is ( + ctx.schema_root.context ().get ("p:includes")); + + for (Includes::ConstReverseIterator i (is.rbegin ()); + i != is.rend (); ++i) + { + ctx.os << "#include " << *i << endl; + } + + ctx.os << endl; + } + + // Generate fundamental types. + // + if (generate_xml_schema) + { + Traversal::Schema schema; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + } + else + { + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> implies >> xsd >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + } + } + + // Generate user type mapping. + // + if (!generate_xml_schema) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::header); + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/parser/parser-header.hxx b/xsde/cxx/parser/parser-header.hxx new file mode 100644 index 0000000..0baf7bc --- /dev/null +++ b/xsde/cxx/parser/parser-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/parser-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_PARSER_HEADER_HXX +#define CXX_PARSER_PARSER_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_parser_header (Context&, Boolean generate_xml_schema); + } +} + +#endif // CXX_PARSER_PARSER_HEADER_HXX diff --git a/xsde/cxx/parser/parser-inline.cxx b/xsde/cxx/parser/parser-inline.cxx new file mode 100644 index 0000000..689f95f --- /dev/null +++ b/xsde/cxx/parser/parser-inline.cxx @@ -0,0 +1,721 @@ +// file : xsde/cxx/parser/parser-inline.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (tiein) + { + String const& name (ename (e)); + String const& impl (etiein (e)); + + // We have to use "real" (non-typedef) base name in base + // initializer because of some broken compilers (EVC 4.0). + // + SemanticGraph::Type& base (e.inherits ().base ()); + String fq_base (fq_name (base)); + String real_fq_base (real_fq_name (base)); + + os << "// " << name << endl + << "//" << endl + << endl; + + os << inl + << name << "::" << endl + << name << " (" << fq_base << "* tiein)" << endl + << ": " << real_fq_base << " (tiein, 0)," << endl + << " " << impl << " (0)" + << "{" + << "}"; + + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << real_fq_base << " (impl, 0)," << endl + << " " << impl << " (impl)" + << "{" + << "}"; + } + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + String item_type (fq_name (t)); + + String item (unclash (name, "item")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // item_parser + // + os << inl + << "void " << name << "::" << endl + << unclash (name, "item_parser") << " (" << + item_type << "& " << item << ")" + << "{" + << "this->_xsde_" << item << "_ = &" << item << ";" + << "}"; + + // parsers + // + os << inl + << "void " << name << "::" << endl + << "parsers (" << item_type << "& " << item << ")" + << "{" + << "this->_xsde_" << item << "_ = &" << item << ";" + << "}"; + + // c-tor + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": "; + + if (tiein) + os << etiein (l) << " (0)," << endl + << " "; + + os << "_xsde_" << item << "_ (0)" + << "{" + << "}"; + + if (tiein) + { + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << list_base << " (impl, 0)," << endl + << " " << etiein (l) << " (impl)," << endl + << " _xsde_" << item << "_ (0)" + << "{" + << "}"; + } + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + if (tiein) + { + String const& name (ename (u)); + String const& impl (etiein (u)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << impl << " (0)" + << "{" + << "}"; + + // + // + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << simple_base << " (impl, 0)," << endl + << " " << impl << " (impl)" + << "{" + << "}"; + } + } + }; + + // + // + struct ParticleAccessor: Traversal::Element, Context + { + ParticleAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& scope (ename (e.scope ())); + String const& parser (eparser (e)); + + os << inl + << "void " << scope << "::" << endl + << parser << " (" << fq_name (e.type ()) << "& p)" + << "{" + << "this->" << emember (e) << " = &p;" + << "}"; + + if (poly_code && !anonymous (e.type ())) + { + os << inl + << "void " << scope << "::" << endl + << parser << " (" << parser_map << "& m)" + << "{" + << "this->" << emember_map (e) << " = &m;" + << "}"; + } + } + }; + + struct AttributeAccessor: Traversal::Attribute, Context + { + AttributeAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << inl + << "void " << ename (a.scope ()) << "::" << endl + << eparser (a) << " (" << fq_name (a.type ()) << "& p)" + << "{" + << "this->" << emember (a) << " = &p;" + << "}"; + } + }; + + // + // + struct ParticleMemberSet: Traversal::Element, Context + { + ParticleMemberSet (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "this->" << emember (e) << " = &" << ename (e) << ";"; + } + }; + + struct AttributeMemberSet: Traversal::Attribute, Context + { + AttributeMemberSet (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << "this->" << emember (a) << " = &" << ename (a) << ";"; + } + }; + + struct BaseMemberSet: Traversal::Complex, + Traversal::List, + Context + { + BaseMemberSet (Context& c) + : Context (c) + { + inherits_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + String const& name (ename (l)); + String item (unclash (name, "item")); + + os << "this->_xsde_" << item << "_ = &" << name << "_item;"; + } + + private: + Traversal::Inherits inherits_; + }; + + // + // + struct ParticleMemberInit: Traversal::Element, Context + { + ParticleMemberInit (Context& c, Boolean comma) + : Context (c), first_ (!comma) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (first_) + first_ = false; + else + os << "," << endl << " "; + + os << emember (e) << " (0)"; + + if (poly_code && !anonymous (e.type ())) + { + os << "," << endl + << " " << emember_map (e) << " (0)"; + } + } + + Boolean + comma () const + { + return !first_; + } + + private: + Boolean first_; + }; + + struct AttributeMemberInit: Traversal::Attribute, Context + { + AttributeMemberInit (Context& c, Boolean comma) + : Context (c), first_ (!comma) + { + } + + virtual Void + traverse (Type& a) + { + if (first_) + first_ = false; + else + os << "," << endl << " "; + + os << emember (a) << " (0)"; + } + + Boolean + comma () const + { + return !first_; + } + + private: + Boolean first_; + }; + + // + // + struct Particle: Traversal::All, Context + { + Particle (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context().count ("p:comp-number")) + return; + + UnsignedLong state_count ( + a.context().get ("p:state-count")); + + os << "," << endl + << " v_all_count_ (" << state_count << "UL, v_all_first_)"; + } + }; + + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + particle_accessor_ (c), + attribute_accessor_ (c), + base_set_ (c), + particle_set_ (c), + attribute_set_ (c), + particle_ (c) + { + // Accessor. + // + contains_compositor_accessor_ >> compositor_accessor_; + compositor_accessor_ >> contains_particle_accessor_; + contains_particle_accessor_ >> compositor_accessor_; + contains_particle_accessor_ >> particle_accessor_; + + names_attribute_accessor_ >> attribute_accessor_; + + // Member set. + // + inherits_base_set_ >> base_set_; + base_set_ >> contains_compositor_set_; + base_set_ >> names_attribute_set_; + + contains_compositor_set_ >> compositor_set_; + compositor_set_ >> contains_particle_set_; + contains_particle_set_ >> compositor_set_; + contains_particle_set_ >> particle_set_; + + names_attribute_set_ >> attribute_set_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + + Boolean hra (false); // Has required attribute. + if (ha) + { + RequiredAttributeTest test (hra); + Traversal::Names names_test (test); + names (c, names_test); + } + + Boolean restriction (restriction_p (c)); + + if (!(tiein || + (!restriction && (he || ha)) || + (validation && (he || hae || hra)))) + return; + + String const& name (ename (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!restriction && (he || ha)) + { + // _parser () + // + if (ha) + names (c, names_attribute_accessor_); + + if (he) + contains_compositor (c, contains_compositor_accessor_); + + + // parsers () + // + + os << inl + << "void " << name << "::" << endl + << "parsers ("; + + { + ParserParamDecl decl (*this, true); + decl.traverse (c); + } + + os << ")" + << "{"; + + inherits (c, inherits_base_set_); + + if (ha) + names (c, names_attribute_set_); + + if (he) + contains_compositor (c, contains_compositor_set_); + + os << "}"; + } + + // We have to use "real" (non-typedef) base name in base + // initializer because of some broken compilers (EVC 4.0). + // + String real_fq_base; + + if (hb && tiein) + real_fq_base = real_fq_name (c.inherits ().base ()); + + // Default c-tor. + // + os << inl + << name << "::" << endl; + + if (hb && tiein) + os << name << " (" << fq_name (c.inherits ().base ()) << + "* tiein)" << endl; + else + os << name << " ()" << endl; + + os << ": "; + + Boolean comma (false); + + if (hb && tiein) + { + os << real_fq_base << " (tiein, 0)"; + comma = true; + } + + if (tiein) + { + if (comma) + os << "," << endl << " "; + + os << etiein (c) << " (0)"; + comma = true; + } + + if (!restriction && (he || ha)) + { + if (ha) + { + AttributeMemberInit attribute_init (*this, comma); + Traversal::Names names_attribute_init; + + names_attribute_init >> attribute_init; + + names (c, names_attribute_init); + + comma = attribute_init.comma (); + } + + if (he) + { + Traversal::Compositor compositor_init; + ParticleMemberInit particle_init (*this, comma); + Traversal::ContainsCompositor contains_compositor_init; + Traversal::ContainsParticle contains_particle_init; + + contains_compositor_init >> compositor_init; + compositor_init >> contains_particle_init; + contains_particle_init >> compositor_init; + contains_particle_init >> particle_init; + + contains_compositor (c, contains_compositor_init); + + comma = particle_init.comma (); + } + } + + if (validation && (he || hae)) + { + if (comma) + os << "," << endl << " "; + + os << "v_state_stack_ (sizeof (v_state_), &v_state_first_)"; + + particle_.dispatch (c.contains_compositor ().compositor ()); + + comma = true; + } + + if (validation && (hra)) + { + if (comma) + os << "," << endl << " "; + + os << "v_state_attr_stack_ (sizeof (v_state_attr_), " << + "&v_state_attr_first_)"; + } + + os << "{" + << "}"; + + // Tiein c-tor. + // + if (tiein) + { + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": "; + + if (hb) + os << real_fq_base << " (impl, 0)," << endl; + else + os << complex_base << " (impl, 0)," << endl; + + os << " " << etiein (c) << " (impl)"; + + Boolean comma (true); + + if (!restriction && (he || ha)) + { + if (ha) + { + AttributeMemberInit attribute_init (*this, comma); + Traversal::Names names_attribute_init; + + names_attribute_init >> attribute_init; + + names (c, names_attribute_init); + + comma = attribute_init.comma (); + } + + if (he) + { + Traversal::Compositor compositor_init; + ParticleMemberInit particle_init (*this, comma); + Traversal::ContainsCompositor contains_compositor_init; + Traversal::ContainsParticle contains_particle_init; + + contains_compositor_init >> compositor_init; + compositor_init >> contains_particle_init; + contains_particle_init >> compositor_init; + contains_particle_init >> particle_init; + + contains_compositor (c, contains_compositor_init); + + comma = particle_init.comma (); + } + } + + if (validation && (he || hae)) + { + if (comma) + os << "," << endl << " "; + + os << "v_state_stack_ (sizeof (v_state_), &v_state_first_)"; + + particle_.dispatch (c.contains_compositor ().compositor ()); + + comma = true; + } + + if (validation && (hra)) + { + if (comma) + os << "," << endl << " "; + + os << "v_state_attr_stack_ (sizeof (v_state_attr_), " << + "&v_state_attr_first_)"; + } + + os << "{" + << "}"; + } + } + + private: + // + // + Traversal::Compositor compositor_accessor_; + ParticleAccessor particle_accessor_; + Traversal::ContainsCompositor contains_compositor_accessor_; + Traversal::ContainsParticle contains_particle_accessor_; + + AttributeAccessor attribute_accessor_; + Traversal::Names names_attribute_accessor_; + + // + // + BaseMemberSet base_set_; + Traversal::Inherits inherits_base_set_; + + Traversal::Compositor compositor_set_; + ParticleMemberSet particle_set_; + Traversal::ContainsCompositor contains_compositor_set_; + Traversal::ContainsParticle contains_particle_set_; + + AttributeMemberSet attribute_set_; + Traversal::Names names_attribute_set_; + + // + // + Particle particle_; + }; + } + + Void + generate_parser_inline (Context& ctx) + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (!ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Enumeration enumeration (ctx); + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> enumeration; + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/parser-inline.hxx b/xsde/cxx/parser/parser-inline.hxx new file mode 100644 index 0000000..c54f537 --- /dev/null +++ b/xsde/cxx/parser/parser-inline.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/parser-inline.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_PARSER_INLINE_HXX +#define CXX_PARSER_PARSER_INLINE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_parser_inline (Context&); + } +} + +#endif // CXX_PARSER_PARSER_INLINE_HXX diff --git a/xsde/cxx/parser/parser-source.cxx b/xsde/cxx/parser/parser-source.cxx new file mode 100644 index 0000000..5e1e9bd --- /dev/null +++ b/xsde/cxx/parser/parser-source.cxx @@ -0,0 +1,1626 @@ +// file : xsde/cxx/parser/parser-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + String const& ret (ret_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + String const& base_ret (ret_type (base)); + + Boolean same (ret == base_ret); + Boolean base_same ( + base.inherits_p () && + base_ret == ret_type (base.inherits ().base ())); + + if (same || ret == L"void" || poly_code || + (tiein && !(base_same || base_ret == L"void"))) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (same || ret == L"void") + { + String const& post (post_name (e)); + + os << ret << " " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (e)); + + os << "if (this->" << impl << ")" << endl + << (ret != L"void" ? "return " : "") << "this->" << + impl << "->" << post << " ();"; + } + + if (same) + { + if (tiein) + os << "else" << endl; + + if (ret == L"void") + os << post_name (base) << " ();"; + else + os << "return " << post_name (base) << " ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (e.name ()); + + if (String ns = xml_ns_name (e)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (validation) + { + Boolean gen (!anonymous (e)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + e.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein && !(base_same || base_ret == L"void")) + { + String const& impl (etiein (base)); + String const& base_post (post_name (base)); + + os << base_ret << " " << name << "::" << endl + << base_post << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << base_post << " ();" + << "}"; + } + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String item (unclash (name, "item")); + String inst (L"_xsde_" + item + L"_"); + String const& post (post_name (t)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // item + // + String const& arg (arg_type (t)); + + os << "void " << name << "::" << endl + << item; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl (etiein (l)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << item << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + + // post + // + if (ret_type (l) == L"void") + { + String const& post (post_name (l)); + + os << "void " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (l)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << post << " ();"; + } + + os << "}"; + } + + // reset + // + if (reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << list_base << "::_reset ();" + << endl + << "if (this->" << inst << ")" << endl + << "this->" << inst << "->_reset ();" + << "}"; + } + + // parse_item + // + os << "void " << name << "::" << endl + << "_xsde_parse_item (const " << string_type << "& v)" + << "{" + << "if (this->" << inst << ")" + << "{" + << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + // This implementation should work for both validating + // and non-validating cases. + // + if (!exceptions || validation) + { + String const& ret (ret_type (t)); + + os << "this->" << inst << "->pre ();"; + + if (!exceptions) + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + os << "this->" << inst << "->_pre_impl (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_characters (v);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_post_impl ();" + << endl + << "if (!ctx.error_type ())" << endl; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << endl; + else + os << "{" + << arg_type (t) << " tmp = this->" << inst << "->" << + post << " ();" + << endl; + + if (!exceptions) + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + if (ret == L"void") + os << "this->" << item << " ();"; + else + os << "this->" << item << " (tmp);" + << "}"; + } + else + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_characters (v);" + << "this->" << inst << "->_post_impl ();"; + + if (ret_type (t) == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << item << " ();"; + else + os << "this->" << item << " (this->" << inst << "->" << + post << " ());"; + } + + os << "}" + << "}"; + + // + // + if (poly_code) + { + String id (l.name ()); + + if (String ns = xml_ns_name (l)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + String const& ret (ret_type (u)); + + if (ret == L"void" || poly_code) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (ret == L"void") + { + String const& post (post_name (u)); + + os << "void " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (u)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << post << " ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (u.name ()); + + if (String ns = xml_ns_name (u)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct ParticleReset: Traversal::Element, Context + { + ParticleReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& m (emember (e)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + String const& map (emember_map (e)); + + os << "if (this->" << map << ")" << endl + << "this->" << map << "->reset ();" + << endl; + } + } + }; + + struct AttributeReset: Traversal::Attribute, Context + { + AttributeReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& m (emember (a)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + } + }; + + // + // + struct StartElement : Traversal::Element, Context + { + StartElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + Boolean poly (poly_code && !anonymous (e.type ())); + Boolean subst (poly && e.global ()); + String const& inst (poly ? emember_cache (e) : emember (e)); + + if (e.qualified () && e.namespace_ ().name ()) + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " &&" << endl + << "ns == " << strlit (e.namespace_ ().name ()); + } + else + { + os << "if (" << (subst ? "(" : "") << + "n == " << L << strlit (e.name ()) << " && ns.empty ()"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (subst) + { + String root_id (e.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + root_id += L' '; + root_id += ns; + } + + os << ") ||" << endl + << "::xsde::cxx::parser::substitution_map_instance ()" << + ".check (" << endl + << "ns, n, " << strlit (root_id) << ", t)"; + } + + os << ")" + << "{"; + + if (poly) + { + // In case of mixin we use virtual inheritance and only + // dynamic_cast can be used. + // + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + String fq_type (fq_name (e.type ())); + String const& member (emember (e)); + String const& member_map (emember_map (e)); + + os << "if (t == 0 && this->" << member << " != 0)" << endl + << "this->" << inst << " = this->" << member << ";" + << "else" + << "{" + << "const char* ts = " << fq_type << "::_static_type ();" + << endl + << "if (t == 0)" << endl + << "t = ts;" + << endl + << "if (this->" << member << " != 0 && " << + "strcmp (t, ts) == 0)" << endl + << "this->" << inst << " = this->" << member << ";" + << "else if (this->" << member_map << " != 0)" << endl + << "this->" << inst << " = " << cast << "< " << fq_type << + "* > (" << endl + << "this->" << member_map << "->find (t));" + << "else" << endl + << "this->" << inst << " = 0;" + << "}"; + } + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);"; + } + else + { + // Note that after pre() we need to check both parser and + // context error states because of the recursive parsing. + // + os << "this->" << inst << "->pre ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_pre_impl (ctx);"; + } + + os << "}" + << "else" << endl + << "ctx.current_.depth_++;" // Ignoring document fragment. + << endl + << "return true;" + << "}"; + } + }; + + + // + // + struct EndElement : Traversal::Element, Context + { + EndElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + Boolean poly (poly_code && !anonymous (e.type ())); + Boolean subst (poly && e.global ()); + String const& inst (poly ? emember_cache (e) : emember (e)); + + if (e.qualified () && e.namespace_ ().name ()) + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " &&" << endl + << "ns == " << strlit (e.namespace_ ().name ()); + } + else + { + os << "if (" << (subst ? "(" : "") << + "n == " << strlit (e.name ()) << " && ns.empty ()"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (subst) + { + String root_id (e.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + root_id += L' '; + root_id += ns; + } + + os << ") ||" << endl + << "::xsde::cxx::parser::substitution_map_instance ()" << + ".check (" << endl + << "ns, n, " << strlit (root_id) << ")"; + } + + os << ")" + << "{"; + + SemanticGraph::Type& type (e.type ()); + String const& post (post_name (type)); + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret_type (type) == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << name << " ();"; + else + os << "this->" << name << " (this->" << inst << "->" << + post << " ());"; + } + else + { + // Note that after post() we need to check both parser and + // context error states because of the recursive parsing. + // + if (ret_type (type) == L"void") + { + os << "this->" << inst << "->" << post << " ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << name << " ();"; + } + else + { + os << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();" + << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << name << " (tmp);"; + } + } + + os << "}" + << "return true;" + << "}"; + } + }; + + + // + // + struct Attribute : Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& name (ename (a)); + String const& inst (emember (a)); + + if (a.qualified () && a.namespace_ ().name ()) + { + os << "if (n == " << L << strlit (a.name ()) << " &&" << endl + << "ns == " << L << strlit (a.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n == " << L << strlit (a.name ()) << " && ns.empty ())" + << "{"; + } + + SemanticGraph::Type& type (a.type ()); + String const& post (post_name (type)); + String const& ret (ret_type (type)); + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + os << "this->" << inst << "->pre ();" + << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_characters (v);" + << "this->" << inst << "->_post_impl ();"; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << "this->" << name << " ();"; + else + os << "this->" << name << " (this->" << inst << "->" << + post << " ());"; + } + else + { + os << "this->" << inst << "->pre ();" + << endl + << "if (!this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_pre_impl (ctx);" + << "else" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_characters (v);" + << endl + << "if (!ctx.error_type ())" << endl + << "this->" << inst << "->_post_impl ();" + << endl + << "if (!ctx.error_type ())" << endl; + + if (ret == L"void") + os << "this->" << inst << "->" << post << " ();" + << endl; + else + os << "{" + << arg_type (type) << " tmp = this->" << inst << "->" << + post << " ();" + << endl; + + os << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << "else" << endl; + + if (ret == L"void") + os << "this->" << name << " ();"; + else + os << "this->" << name << " (tmp);" + << "}"; + } + + os << "}" + << "return true;" + << "}"; + } + }; + + // + // Callbacks. + // + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (correspondent (a) == 0) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + SemanticGraph::Scope& s (scope (a)); + String const& present (epresent (a)); + + os << "void " << ename (s) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (s))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << present << " ();"; + } + + os << "}"; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () == c.contains_end ()) + return; + + if (correspondent (c) == 0) + { + SemanticGraph::Scope& s (scope (c)); + String const& arm (earm (c)); + + os << "void " << ename (s) << "::" << endl + << arm << " (" << earm_tag (c) << (tiein ? " x" : "") << ")" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (s))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << arm << " (x);"; + } + + os << "}"; + + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // Root compositor that models inheritance by extension + // may not have an association so we may fall through + // in to the 'if' case even though this is a restriction. + // This is ok since such a compositor always has max == + // min == 1 and so nothing is generated. + // + if (SemanticGraph::Compositor* b = correspondent (s)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (b->max () != 1 && s.min () == 0) + { + SemanticGraph::Scope& ss (scope (s)); + + os << "void " << ename (ss) << "::" << endl + << epresent (s) << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << enext (s) << " ();"; + } + else + os << "this->" << enext (s) << " ();"; + + os << "}"; + } + } + else + { + if (s.max () != 1) + { + SemanticGraph::Scope& ss (scope (s)); + String const& next (enext (s)); + + os << "void " << ename (ss) << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << next << " ();"; + } + + os << "}"; + } + else if (s.min () == 0) + { + SemanticGraph::Scope& ss (scope (s)); + String const& present (epresent (s)); + + os << "void " << ename (ss) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (ss))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << present << " ();"; + } + + os << "}"; + } + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + }; + + struct ParticleCallback: Traversal::Element, Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (correspondent (e) == 0) + { + String const& name (ename (e)); + String const& arg (arg_type (e.type ())); + + os << "void " << ename (e.scope ()) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (e.scope ()))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + } + } + }; + + struct AttributeCallback: Traversal::Attribute, Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + String const& arg (arg_type (a.type ())); + + os << "void " << ename (a.scope ()) << "::" << endl + << name; + + if (arg == L"void") + os << " ()"; + else + os << " (" << arg << (tiein ? " x" : "") << ")"; + + os << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (a.scope ()))); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (" << + (arg != L"void" ? "x" : "") << ");"; + } + + os << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_val_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_reset_ (c), + attribute_reset_ (c), + start_element_ (c), + end_element_ (c), + attribute_ (c) + { + // Callback. + // + if (validation) + { + contains_compositor_callback_ >> compositor_callback_val_; + compositor_callback_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_val_; + } + else + { + contains_compositor_callback_ >> compositor_callback_non_val_; + compositor_callback_non_val_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_non_val_; + } + + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Reset. + // + contains_compositor_reset_ >> compositor_reset_; + compositor_reset_ >> contains_particle_reset_; + contains_particle_reset_ >> compositor_reset_; + contains_particle_reset_ >> particle_reset_; + + names_attribute_reset_ >> attribute_reset_; + + // + // + contains_compositor_start_ >> start_compositor_; + start_compositor_ >> contains_particle_start_; + contains_particle_start_ >> start_compositor_; + contains_particle_start_ >> start_element_; + + // + // + contains_compositor_end_ >> end_compositor_; + end_compositor_ >> contains_particle_end_; + contains_particle_end_ >> end_compositor_; + contains_particle_end_ >> end_element_; + + // + // + names_attribute_ >> attribute_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean restriction (restriction_p (c)); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + + Boolean hra (false); // Has required attribute. + if (ha) + { + RequiredAttributeTest test (hra); + Traversal::Names names_test (test); + names (c, names_test); + } + + String const& name (ename (c)); + String const& ret (ret_type (c)); + Boolean same (hb && ret == ret_type (c.inherits ().base ())); + + String base_ret; + Boolean base_same (true); + + if (tiein && hb) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + base_ret = ret_type (base); + base_same = base.inherits_p () && + base_ret == ret_type (base.inherits ().base ()); + } + + if (he || ha || same || ret == L"void" || poly_code || + (tiein && !(base_same || base_ret == L"void"))) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + // Member callbacks. + // + if (!restriction) + { + if (ha) + names (c, names_attribute_callback_); + } + + if (!restriction || validation) + { + if (he || hae) + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + if (same || ret == L"void") + { + String const& post (post_name (c)); + + os << ret << " " << name << "::" << endl + << post << " ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (c)); + + os << "if (this->" << impl << ")" << endl + << (ret != L"void" ? "return " : "") << "this->" << + impl << "->" << post << " ();"; + } + + if (same) + { + if (tiein) + os << "else" << endl; + + SemanticGraph::Type& base (c.inherits ().base ()); + + if (ret == L"void") + os << post_name (base) << " ();"; + else + os << "return " << post_name (base) << " ();"; + } + + os << "}"; + } + + // reset + // + if (!restriction && (he || ha) && reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + // Avoid recursion in case of recursive parsing. + // + if (he) + os << "if (this->resetting_)" << endl + << "return;" + << endl; + + // Reset the base. We cannot use the fully-qualified base name + // directly because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << base << "::_reset ();" + << endl; + + // Reset validation state. + // + if (validation) + { + if (he || hae) + { + os << "this->v_state_stack_.clear ();" + << endl; + + SemanticGraph::Compositor& comp ( + c.contains_compositor ().compositor ()); + + if (comp.is_a () && + comp.context().count ("p:comp-number")) + { + os << "this->v_all_count_.clear ();" + << endl; + } + } + + if (hra) + os << "this->v_state_attr_stack_.clear ();" + << endl; + } + + // Reset member parsers. + // + + if (ha) + names (c, names_attribute_reset_); + + if (he) + { + os << "this->resetting_ = true;" + << endl; + + contains_compositor (c, contains_compositor_reset_); + + os << "this->resetting_ = false;" + << endl; + } + + os << "}"; + } + + // + // + if (poly_code) + { + String id (c.name ()); + + if (String ns = xml_ns_name (c)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (hb && validation) + { + Boolean gen (!anonymous (c)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + c.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + // Base post + // + if (tiein && !(base_same || base_ret == L"void")) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + String const& impl (etiein (base)); + String const& base_post (post_name (base)); + + os << base_ret << " " << name << "::" << endl + << base_post << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << base_post << " ();" + << "}"; + } + + // The rest is parsing/validation code which is generated in + // *-validation-source.cxx. + // + if (validation) + return; + + // Don't use the restriction_p result from here since we don't + // want special treatment of anyType. + // + restriction = hb && c.inherits ().is_a (); + + // _start_element_impl & _end_element_impl + // + if (he) + { + // _start_element_impl + // + + os << "bool " << name << "::" << endl + << "_start_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n"; + + if (poly_runtime) + os << "," << endl + << "const char*" << (poly_code ? " t" : ""); + + os << ")" + << "{"; + + if (poly_code) + os << "XSDE_UNUSED (t);" + << endl; + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::"; + + if (poly_runtime) + os << "_start_element_impl (ns, n, " << + (poly_code ? "t" : "0") << "))" << endl; + else + os << "_start_element_impl (ns, n))" << endl; + + os << "return true;" + << endl; + } + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + contains_compositor (c, contains_compositor_start_); + + os << "return false;" + << "}"; + + + // _end_element_impl + // + os << "bool " << name << "::" << endl + << "_end_element_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n)" + << "{"; + + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::_end_element_impl (ns, n))" << endl + << "return true;" + << endl; + } + + if (!exceptions) + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + contains_compositor (c, contains_compositor_end_); + + os << "return false;" + << "}"; + } + + + if (ha) + { + // _attribute_impl + // + + os << "bool " << name << "::" << endl + << "_attribute_impl (const " << string_type << "& ns," << endl + << "const " << string_type << "& n," << endl + << "const " << string_type << "& v)" + << "{"; + + if (!restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << "if (" << base << "::_attribute_impl (ns, n, v))" + << "{" + << "return true;" + << "}"; + } + + os << "::xsde::cxx::parser::context& ctx = this->_context ();" + << endl; + + names (c, names_attribute_); + + os << "return false;" + << "}"; + } + } + + private: + // + // + CompositorCallback compositor_callback_val_; + Traversal::Compositor compositor_callback_non_val_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_reset_; + ParticleReset particle_reset_; + Traversal::ContainsCompositor contains_compositor_reset_; + Traversal::ContainsParticle contains_particle_reset_; + + AttributeReset attribute_reset_; + Traversal::Names names_attribute_reset_; + + // + // + Traversal::Compositor start_compositor_; + StartElement start_element_; + Traversal::ContainsCompositor contains_compositor_start_; + Traversal::ContainsParticle contains_particle_start_; + + // + // + Traversal::Compositor end_compositor_; + EndElement end_element_; + Traversal::ContainsCompositor contains_compositor_end_; + Traversal::ContainsParticle contains_particle_end_; + + // + // + Attribute attribute_; + Traversal::Names names_attribute_; + }; + + // Generate substitution group map entries. + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (e.substitutes_p ()) + { + String name (escape (e.name ())); + Type& r (e.substitutes ().root ()); + + SemanticGraph::Type& type (e.type ()); + + String m_id (e.name ()); + String r_id (r.name ()); + + if (String const& ns = e.namespace_ ().name ()) + { + m_id += L' '; + m_id += ns; + } + + if (String const& ns = r.namespace_ ().name ()) + { + r_id += L' '; + r_id += ns; + } + + os << "// Substitution map entry for " << comment (e.name ()) << + "." << endl + << "//" << endl + << "static" << endl + << "const ::xsde::cxx::parser::substitution_map_entry" << endl + << "_xsde_" << name << "_substitution_map_entry_ (" << endl + << strlit (m_id) << "," << endl + << strlit (r_id) << "," << endl + << fq_name (type) << "::_static_type ());" + << endl; + } + } + }; + } + + Void + generate_parser_source (Context& ctx) + { + if (ctx.tiein) + ctx.os << "#include " << endl + << endl; + + if (ctx.poly_code) + { + ctx.os << "#include " << endl + << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl + << endl; + else + ctx.os << endl; + + ctx.os << "static" << endl + << "const ::xsde::cxx::parser::substitution_map_init" << endl + << "_xsde_substitution_map_init_;" + << endl; + + if (ctx.validation) + { + ctx.os << "static" << endl + << "const ::xsde::cxx::parser::validating::" << + "inheritance_map_init" << endl + << "_xsde_inheritance_map_init_;" + << endl; + } + } + + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement global_element (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.poly_code) + names >> global_element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/parser/parser-source.hxx b/xsde/cxx/parser/parser-source.hxx new file mode 100644 index 0000000..dcf07d6 --- /dev/null +++ b/xsde/cxx/parser/parser-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/parser/parser-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_PARSER_SOURCE_HXX +#define CXX_PARSER_PARSER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Parser + { + Void + generate_parser_source (Context&); + } +} + +#endif // CXX_PARSER_PARSER_SOURCE_HXX diff --git a/xsde/cxx/parser/print-impl-common.hxx b/xsde/cxx/parser/print-impl-common.hxx new file mode 100644 index 0000000..1815bb7 --- /dev/null +++ b/xsde/cxx/parser/print-impl-common.hxx @@ -0,0 +1,1063 @@ +// file : xsde/cxx/parser/print-impl-common.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_PRINT_IMPL_COMMON_HXX +#define CXX_PARSER_PRINT_IMPL_COMMON_HXX + +#include +#include + +#include + +namespace CXX +{ + namespace Parser + { + struct PrintCall: Traversal::Type, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Context + { + PrintCall (Context& c, String const& tag, String const& arg) + : Context (c), tag_ (tag), arg_ (arg) + { + } + + virtual Void + traverse (SemanticGraph::Type&) + { + gen_user_type (); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + if (default_type (t, "bool")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %u\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + if (default_type (t, "signed char")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + "static_cast (" << arg_ << ") << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + if (default_type (t, "unsigned char")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %u\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + "static_cast (" << arg_ << ") << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + if (default_type (t, "short")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + if (default_type (t, "unsigned short")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %u\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + if (default_type (t, "int")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + if (default_type (t, "unsigned int")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %u\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + if (options.value ()) + { + if (default_type (t, "long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %ld\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + else + { + if (default_type (t, "long long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %lld\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + if (options.value ()) + { + if (default_type (t, "unsigned long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %lu\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + else + { + if (default_type (t, "unsigned long long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %llu\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + if (default_type (t, "long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %ld\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + if (default_type (t, "long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %ld\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + if (default_type (t, "long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %ld\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + if (default_type (t, "unsigned long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %lu\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + if (default_type (t, "unsigned long")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %lu\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + if (default_type (t, "float")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %g\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + if (default_type (t, "double")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %g\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + if (default_type (t, "double")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %g\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + gen_string (t); + } + + // String sequences. + // + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + gen_sequence (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + gen_sequence (t); + } + + // QName + // + + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + if (options.value ()) + { + if (default_type (t, xs_ns_name () + L"::qname*")) + { + if (options.value ()) + os << "if (" << arg_ << "->prefix ()[0] == '\\0')" << endl + << "printf (" << strlit (tag_ + L": %s\n") << ", " << + arg_ << "->name ());" + << "else" << endl + << "printf (" << strlit (tag_ + L": %s:%s\n") << "," << endl + << arg_ << "->prefix ()," << endl + << arg_ << "->name ());"; + else + os << "if (" << arg_ << "->prefix ()[0] == '\\0')" << endl + << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << "->name () << std::endl;" + << "else" << endl + << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << "->prefix ()" << endl + << " << ':' << " << arg_ << "->name () << std::endl;"; + } + else + gen_user_type (); + } + else + { + if (default_type (t, xs_ns_name () + L"::qname")) + { + if (options.value ()) + os << "if (" << arg_ << ".prefix ().empty ())" << endl + << "printf (" << strlit (tag_ + L": %s\n") << ", " << + arg_ << ".name ().c_str ());" + << "else" << endl + << "printf (" << strlit (tag_ + L": %s:%s\n") << "," << endl + << arg_ << ".prefix ().c_str ()," << endl + << arg_ << ".name ().c_str ());"; + else + os << "if (" << arg_ << ".prefix ().empty ())" << endl + << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << ".name () << std::endl;" + << "else" << endl + << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << ".prefix ()" << endl + << " << ':' << " << arg_ << ".name () << std::endl;"; + } + else + gen_user_type (); + } + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + gen_buffer (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + gen_buffer (t); + } + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + if (default_type (t, xs_ns_name () + L"::date")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d-%u-%u") << "," << endl + << arg_ << ".year ()," << endl + << arg_ << ".month ()," << endl + << arg_ << ".day ());" << endl; + else + os << "std::cout << " << strlit (tag_ + L": ") << endl + << " << " << arg_ << ".year () << '-'" << endl + << " << " << arg_ << ".month () << '-'" << endl + << " << " << arg_ << ".day ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + if (default_type (t, xs_ns_name () + L"::date_time")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d-%u-%uT%u:%u:%g") << + "," << endl + << arg_ << ".year ()," << endl + << arg_ << ".month ()," << endl + << arg_ << ".day ()," << endl + << arg_ << ".hours ()," << endl + << arg_ << ".minutes ()," << endl + << arg_ << ".seconds ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << endl + << " << " << arg_ << ".year () << '-'" << endl + << " << " << arg_ << ".month () << '-'" << endl + << " << " << arg_ << ".day () << 'T'" << endl + << " << " << arg_ << ".hours () << ':'" << endl + << " << " << arg_ << ".minutes () << ':'" << endl + << " << " << arg_ << ".seconds ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + if (default_type (t, xs_ns_name () + L"::duration")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": ") << ");" + << endl + << "if (" << arg_ << ".negative ())" << endl + << "printf (\"-\");" + << endl + << "printf (\"P%uY%uM%uDT%uH%uM%gS\\n\"," << endl + << arg_ << ".years ()," << endl + << arg_ << ".months ()," << endl + << arg_ << ".days ()," << endl + << arg_ << ".hours ()," << endl + << arg_ << ".minutes ()," << endl + << arg_ << ".seconds ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << ";" + << endl + << "if (" << arg_ << ".negative ())" << endl + << "std::cout << '-';" + << endl + << "std::cout << 'P'" << endl + << " << " << arg_ << ".years () << 'Y'" << endl + << " << " << arg_ << ".months () << 'M'" << endl + << " << " << arg_ << ".days () << \"DT\"" << endl + << " << " << arg_ << ".hours () << 'H'" << endl + << " << " << arg_ << ".minutes () << 'M'" << endl + << " << " << arg_ << ".seconds () << 'S'" + << " << std::endl;"; + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + if (default_type (t, xs_ns_name () + L"::gday")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": ---%u") << ", " << + arg_ << ".day ());"; + else + os << "std::cout << " << strlit (tag_ + L": ---") << + " << " << arg_ << ".day ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + if (default_type (t, xs_ns_name () + L"::gmonth")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": --%u") << ", " << + arg_ << ".month ());"; + else + os << "std::cout << " << strlit (tag_ + L": --") << + " << " << arg_ << ".month ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + if (default_type (t, xs_ns_name () + L"::gmonth_day")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": --%u-%u") << "," << endl + << arg_ << ".month ()," << endl + << arg_ << ".day ());"; + else + os << "std::cout << " << strlit (tag_ + L": --") << endl + << " << " << arg_ << ".month () << '-'" << endl + << " << " << arg_ << ".day ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + if (default_type (t, xs_ns_name () + L"::gyear")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d") << ", " << + arg_ << ".year ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << + " << " << arg_ << ".year ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + if (default_type (t, xs_ns_name () + L"::gyear_month")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %d-%u") << "," << endl + << arg_ << ".year ()," << endl + << arg_ << ".month ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << endl + << " << " << arg_ << ".year () << '-'" << endl + << " << " << arg_ << ".month ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + if (default_type (t, xs_ns_name () + L"::time")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %u:%u:%g") << "," << endl + << arg_ << ".hours ()," << endl + << arg_ << ".minutes ()," << endl + << arg_ << ".seconds ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << endl + << " << " << arg_ << ".hours () << ':'" << endl + << " << " << arg_ << ".minutes () << ':'" << endl + << " << " << arg_ << ".seconds ();"; + + gen_time_zone (); + } + else + gen_user_type (); + } + + private: + bool + default_type (SemanticGraph::Type& t, String const& def_type) + { + return ret_type (t) == def_type; + } + + void + gen_user_type () + { + os << "// TODO" << endl + << "//" << endl; + } + + void + gen_string (SemanticGraph::Type& t) + { + if (options.value ()) + { + if (default_type (t, "char*")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %s\n") << ", " << + arg_ << ");"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + else + { + if (default_type (t, "::std::string")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %s\n") << ", " << + arg_ << ".c_str ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << " << std::endl;"; + } + else + gen_user_type (); + } + } + + void + gen_sequence (SemanticGraph::Type& t) + { + String type (xs_ns_name () + L"::string_sequence"); + + if (default_type (t, type + L"*")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": ") << ");" + << endl; + else + os << "std::cout << " << strlit (tag_ + L": ") << ";" + << endl; + + os << "for (" << type << "::const_iterator i (" << arg_ << + "->begin ()), e (" << arg_ << "->end ());" << endl + << "i != e;)" + << "{"; + + if (options.value ()) + { + if (options.value ()) + os << "printf (\"%s\", *i++);"; + else + os << "printf (\"%s\", (i++)->c_str ());"; + + os << "if (i != e)" << endl + << "printf (\" \");" + << "}" + << "printf (\"\\n\");"; + } + else + os << "std::cout << *i++;" + << "if (i != e)" << endl + << "std::cout << ' ';" + << "}" + << "std::cout << std::endl;"; + } + else + gen_user_type (); + } + + void + gen_buffer (SemanticGraph::Type& t) + { + if (default_type (t, xs_ns_name () + L"::buffer*")) + { + if (options.value ()) + os << "printf (" << strlit (tag_ + L": %zu bytes\n") << ", " << + arg_ << "->size ());"; + else + os << "std::cout << " << strlit (tag_ + L": ") << " << " << + arg_ << "->size () << \" bytes\" << std::endl;"; + } + else + gen_user_type (); + } + + void + gen_time_zone () + { + os << endl + << "if (" << arg_ << ".zone_present ())" + << "{"; + + if (options.value ()) + os << "if (" << arg_ << ".zone_hours () < 0)" << endl + << "printf (\"%d:%d\", " << arg_ << ".zone_hours (), -" << + arg_ << ".zone_minutes ());" + << "else" << endl + << "printf (\"+%d:%d\", " << arg_ << ".zone_hours (), " << + arg_ << ".zone_minutes ());"; + else + os << "if (" << arg_ << ".zone_hours () < 0)" << endl + << "std::cout << " << arg_ << ".zone_hours () << ':' << -" << + arg_ << ".zone_minutes ();" + << "else" << endl + << "std::cout << '+' << " << arg_ << ".zone_hours () << " << + "':' << " << arg_ << ".zone_minutes ();"; + + os << "}"; + + if (options.value ()) + os << "printf (\"\\n\");"; + else + os << "std::cout << std::endl;"; + } + + private: + String tag_; + String arg_; + }; + + struct DeleteCall: Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Context + { + DeleteCall (Context& c, String const& arg) + : Context (c), arg_ (arg) + { + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + gen_string (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + gen_string (t); + } + + // String sequences. + // + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + gen_sequence (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + gen_sequence (t); + } + + // QName + // + + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + if (options.value () && + default_type (t, xs_ns_name () + L"::qname*")) + { + os << endl + << "delete " << arg_ << ";"; + } + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + gen_buffer (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + gen_buffer (t); + } + + private: + bool + default_type (SemanticGraph::Type& t, String const& def_type) + { + return ret_type (t) == def_type; + } + + void + gen_string (SemanticGraph::Type& t) + { + if (options.value () && default_type (t, "char*")) + { + os << endl + << "delete[] " << arg_ << ";"; + } + } + + void + gen_sequence (SemanticGraph::Type& t) + { + if (default_type (t, xs_ns_name () + L"::string_sequence*")) + { + os << endl + << "delete " << arg_ << ";"; + } + } + + void + gen_buffer (SemanticGraph::Type& t) + { + if (default_type (t, xs_ns_name () + L"::buffer*")) + { + os << endl + << "delete " << arg_ << ";"; + } + } + + private: + String arg_; + }; + } +} + +#endif // CXX_PARSER_PRINT_IMPL_COMMON_HXX diff --git a/xsde/cxx/parser/state-processor.cxx b/xsde/cxx/parser/state-processor.cxx new file mode 100644 index 0000000..3ecc77a --- /dev/null +++ b/xsde/cxx/parser/state-processor.cxx @@ -0,0 +1,319 @@ +// file : xsde/cxx/parser/state-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include +#include + +#include + +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + typedef Cult::Containers::Vector Particles; + + void + print (Particles const& p) + { + using std::wcerr; + using std::endl; + + wcerr << "prefixes: " << endl; + + for (Particles::ConstIterator i (p.begin ()); i != p.end (); ++i) + { + if (SemanticGraph::Element* e = + dynamic_cast (*i)) + { + wcerr << e->name () << endl; + } + else + { + wcerr << "" << endl; + } + } + + wcerr << endl; + } + + // + // + struct Particle: Traversal::All, + Traversal::Choice, + Traversal::Sequence + { + Particle (UnsignedLong& all, + UnsignedLong& choice, + UnsignedLong& sequence, + UnsignedLong& depth) + : all_ (all), + choice_ (choice), + sequence_ (sequence), + depth_ (depth) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If all prefixes of this compositor have minOccurs = 0, then + // the compositor itself effectively has minOccurs = 0 regardless + // of the actual value specified in the schema. + // + // Note that we don't need to care about depth since the 'all' + // compositor cannot contain any nested compositors. + // + + UnsignedLong state (0); + UnsignedLong min (0); + + for (Compositor::ContainsIterator ci (a.contains_begin ()); + ci != a.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + // The 'all' compositor can only include elements. + // + prefixes_.push_back (&p); + + if (min == 0 && ci->min () != 0) + min = 1; + + p.context ().set ("p:prefix", true); + p.context ().set ("p:state", state++); + } + + if (!prefixes_.empty ()) + { + a.context ().set ("p:comp-number", choice_++); + a.context ().set ("p:prefixes", prefixes_); + a.context ().set ("p:state-count", + UnsignedLong (prefixes_.size ())); + + // effective-min = min * actual-min + // + if (min == 1) + min = a.min (); + + a.context ().set ("p:effective-min", min); + + // print (prefixes_); + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If any prefix of this compositor have minOccurs = 0, then the + // compositor itself effectively has minOccurs = 0 regardless of + // the actual value specified in the schema. + // + + UnsignedLong state (0); + UnsignedLong min (1); + + for (Compositor::ContainsIterator ci (c.contains_begin ()); + ci != c.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () || + p.is_a ()) + { + prefixes_.push_back (&p); + + if (min == 1 && ci->min () == 0) + min = 0; + } + else + { + UnsignedLong depth (0); + Particle t (all_, choice_, sequence_, depth); + t.dispatch (p); + + if (t.prefixes_.empty ()) + continue; // Skip empty compositors. + + if (++depth > depth_) // One for this compositor. + depth_ = depth; + + prefixes_.insert (prefixes_.end (), + t.prefixes_.begin ().base (), + t.prefixes_.end ().base ()); + + if (min == 1 && + p.context ().get ("p:effective-min") == 0) + min = 0; + } + + p.context ().set ("p:prefix", true); + p.context ().set ("p:state", state++); + } + + if (!prefixes_.empty ()) + { + c.context ().set ("p:comp-number", choice_++); + c.context ().set ("p:prefixes", prefixes_); + + // effective-min = min * actual-min + // + if (min == 1) + min = c.min (); + + c.context ().set ("p:effective-min", min); + + // print (prefixes_); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + using SemanticGraph::Compositor; + + // Go over particles, collecting "prefix" particles in prefixes_, + // assigning state numbers and calculating effective minOccurs. + // If all prefixes of this compositor have minOccurs = 0, then + // the compositor itself effectively has minOccurs = 0 regardless + // of the actual value specified in the schema. + // + + Boolean prefix (true); + UnsignedLong state (0); + UnsignedLong min (0); + + for (Compositor::ContainsIterator ci (s.contains_begin ()); + ci != s.contains_end (); ++ci) + { + SemanticGraph::Particle& p (ci->particle ()); + + if (p.is_a () || + p.is_a ()) + { + if (prefix) + { + prefixes_.push_back (&p); + + if (ci->min () != 0) + min = 1; + } + } + else + { + UnsignedLong depth (0); + Particle t (all_, choice_, sequence_, depth); + t.dispatch (p); + + if (t.prefixes_.empty ()) + continue; // Skip empty compositors. + + if (++depth > depth_) // One for this compositor. + depth_ = depth; + + if (prefix) + { + prefixes_.insert (prefixes_.end (), + t.prefixes_.begin ().base (), + t.prefixes_.end ().base ()); + + if (p.context ().get ("p:effective-min") != 0) + min = 1; + } + } + + p.context ().set ("p:state", state++); + + if (prefix) + p.context ().set ("p:prefix", true); + + if (prefix && min != 0) + prefix = false; + } + + if (!prefixes_.empty ()) + { + s.context ().set ("p:comp-number", sequence_++); + s.context ().set ("p:prefixes", prefixes_); + + // effective-min = min * actual-min + // + if (min == 1) + min = s.min (); + + s.context ().set ("p:effective-min", min); + + // print (prefixes_); + } + } + + private: + Particles prefixes_; + + UnsignedLong& all_; + UnsignedLong& choice_; + UnsignedLong& sequence_; + + UnsignedLong& depth_; + }; + + + // + // + struct Complex: Traversal::Complex + { + virtual Void + traverse (Type& c) + { + if (c.contains_compositor_p ()) + { + UnsignedLong all (0), choice (0), sequence (0), depth (0); + Particle t (all, choice, sequence, depth); + t.dispatch (c.contains_compositor ().compositor ()); + + // Set the maximum stack depth for this type. Used to + // allocate fixed-size state stack. + // + c.context ().set ("p:depth", depth + 1); + } + } + }; + } + + Void StateProcessor:: + process (SemanticGraph::Schema& tu, SemanticGraph::Path const&) + { + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> ns_names; + + Complex complex_type; + + ns_names >> complex_type; + + schema.dispatch (tu); + } + } +} diff --git a/xsde/cxx/parser/state-processor.hxx b/xsde/cxx/parser/state-processor.hxx new file mode 100644 index 0000000..c276d54 --- /dev/null +++ b/xsde/cxx/parser/state-processor.hxx @@ -0,0 +1,28 @@ +// file : xsde/cxx/parser/state-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_STATE_PROCESSOR_HXX +#define CXX_PARSER_STATE_PROCESSOR_HXX + +#include +#include + +namespace CXX +{ + namespace Parser + { + using namespace Cult::Types; + + class StateProcessor + { + public: + Void + process (XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_PARSER_STATE_PROCESSOR_HXX diff --git a/xsde/cxx/parser/type-processor.cxx b/xsde/cxx/parser/type-processor.cxx new file mode 100644 index 0000000..4e7f65a --- /dev/null +++ b/xsde/cxx/parser/type-processor.cxx @@ -0,0 +1,352 @@ +// file : xsde/cxx/parser/type-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Parser + { + namespace + { + // + // + struct Type: Traversal::Type + { + Type (SemanticGraph::Schema& schema, + TypeMap::Namespaces& type_map, + Boolean add_includes) + : schema_ (schema), + type_map_ (type_map), + add_includes_ (add_includes) + { + } + + virtual Void + traverse (SemanticGraph::Type& type) + { + using TypeMap::Namespace; + using TypeMap::Namespaces; + + SemanticGraph::Context& tc (type.context ()); + + // There are two situations where we may try to process the + // same type more than once. The first is when the type is + // used in several element declarations in the same schema. + // The second situation only occurs when we are in the file- + // per-type mode. In this case the type was processed as part + // of another root schema. In the second case, while the ret + // and arg types are assumed to be the same, we need to re- + // match the type in order to add include directives to the + // new root schema. + // + Boolean set (true); + + if (tc.count ("p:ret-type")) + { + SemanticGraph::Schema* s ( + tc.get ("p:root-schema")); + + if (&schema_ == s) + return; + + set = false; + } + + SemanticGraph::Namespace& ns ( + dynamic_cast (type.scope ())); + + String const& ns_name (ns.name ()); + String const& t_name (type.name ()); + + // std::wcerr << "traversing: " << ns_name << "#" << t_name << endl; + + for (Namespaces::ConstIterator n (type_map_.begin ()); + n != type_map_.end (); ++n) + { + // Check if the namespace matches. + // + Boolean ns_match; + + if (!n->xsd_name ().empty ()) + { + ns_match = n->xsd_name ().match (ns_name); + } + else + ns_match = ns_name.empty (); + + // std::wcerr << "considering ns expr: " << n->xsd_name () << endl; + + if (ns_match) + { + // Namespace matched. See if there is a type that matches. + // + for (Namespace::TypesIterator t (n->types_begin ()); + t != n->types_end (); ++t) + { + if (t->xsd_name ().match (t_name)) + { + if (set) + { + // Got a match. See if the namespace has the C++ + // namespace mapping. + // + String cxx_ns; + + if (n->has_cxx_name ()) + { + if (!n->xsd_name ().empty ()) + { + cxx_ns = n->xsd_name ().merge ( + n->cxx_name (), ns_name, true); + } + else + cxx_ns = n->cxx_name (); + + cxx_ns += L"::"; + } + + // Figure out ret and arg type names. + // + String ret_type (cxx_ns); + + ret_type += t->xsd_name ().merge ( + t->cxx_ret_name (), t_name, true); + + String arg_type; + + if (t->cxx_arg_name ()) + { + arg_type = cxx_ns; + arg_type += t->xsd_name ().merge ( + t->cxx_arg_name (), t_name, true); + } + else + { + if (ret_type == L"void") + arg_type = ret_type; + else + { + WideChar last (ret_type[ret_type.size () - 1]); + + // If it is already a pointer or reference then use + // it as is. + // + if (last == L'*' || last == L'&') + arg_type = ret_type; + else + arg_type = L"const " + ret_type + L"&"; + } + } + + tc.set ("p:ret-type", ret_type); + tc.set ("p:arg-type", arg_type); + } + + tc.set ("p:root-schema", &schema_); + + //std::wcerr << t_name << " -> " << ret_type << endl; + + // See of we need to add any includes to the translations + // unit. + // + if (add_includes_) + { + if (n->includes_begin () != n->includes_end ()) + { + typedef Cult::Containers::Set Includes; + + SemanticGraph::Context& sc (schema_.context ()); + + if (!sc.count ("p:includes")) + sc.set ("p:includes", Includes ()); + + Includes& is (sc.get ("p:includes")); + + for (Namespace::IncludesIterator i (n->includes_begin ()); + i != n->includes_end (); ++i) + { + is.insert (*i); + } + } + } + + return; + } + } + } + } + } + + private: + SemanticGraph::Schema& schema_; + TypeMap::Namespaces& type_map_; + Boolean add_includes_; + }; + + // + // + struct BaseType: Traversal::Complex + { + virtual Void + traverse (SemanticGraph::Complex& c) + { + Complex::inherits (c); + } + }; + + // + // + struct GlobalType: Traversal::Type, + Traversal::List, + Traversal::Complex, + Traversal::Enumeration + { + GlobalType (SemanticGraph::Schema& schema, + TypeMap::Namespaces& type_map, + Boolean add_includes, + Boolean tiein) + : type_ (schema, type_map, add_includes) + { + inherits_ >> type_; + names_ >> instance_ >> belongs_ >> type_; + argumented_ >> type_; + + if (tiein) + { + // In case of a tiein support, we also need to process base's + // base type. + // + inherits_base_ >> base_type_ >> inherits_level_2_ >> type_; + } + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + type_.traverse (t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + type_.traverse (l); + Traversal::List::argumented (l, argumented_); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + type_.traverse (c); + Complex::inherits (c, inherits_); + Complex::inherits (c, inherits_base_); + Complex::names (c, names_); + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + type_.traverse (e); + Complex::inherits (e, inherits_); + } + + private: + Parser::Type type_; + BaseType base_type_; + Traversal::Names names_; + Traversal::Instance instance_; + Traversal::Inherits inherits_; + Traversal::Inherits inherits_base_; + Traversal::Inherits inherits_level_2_; + Traversal::Belongs belongs_; + Traversal::Argumented argumented_; + }; + + Void + process_impl (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema& tu, + TypeMap::Namespaces& type_map) + { + Boolean tiein (!options.value () && + !options.value ()); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalType global_type (tu, type_map, true, tiein); + + schema >> schema_names >> ns >> ns_names >> global_type; + + schema.dispatch (tu); + } + else + { + // If --extern-xml-schema is specified, then we don't want + // includes from the XML Schema type map. + // + Boolean extern_xml_schema ( + options.value ()); + + // Besides types defined in this schema, also process those + // referenced by global elements in case we are generating + // something for them. + // + Traversal::Schema schema; + Traversal::Schema xs_schema; + Traversal::Sources sources; + Traversal::Implies implies; + + schema >> sources >> schema; + schema >> implies >> xs_schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Traversal::Element global_element; + GlobalType global_type (tu, type_map, true, tiein); + + schema >> schema_names >> ns >> ns_names; + + ns_names >> global_element; + ns_names >> global_type; + + Traversal::Belongs element_belongs; + global_element >> element_belongs >> global_type; + + Traversal::Names xs_schema_names; + Traversal::Namespace xs_ns; + Traversal::Names xs_ns_names; + GlobalType xs_global_type (tu, type_map, !extern_xml_schema, tiein); + + xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >> + xs_global_type; + + schema.dispatch (tu); + } + } + } + + Void TypeProcessor:: + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema& s, + TypeMap::Namespaces& tm) + { + process_impl (options, s, tm); + } + } +} diff --git a/xsde/cxx/parser/type-processor.hxx b/xsde/cxx/parser/type-processor.hxx new file mode 100644 index 0000000..5855569 --- /dev/null +++ b/xsde/cxx/parser/type-processor.hxx @@ -0,0 +1,34 @@ +// file : xsde/cxx/parser/type-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_TYPE_PROCESSOR_HXX +#define CXX_PARSER_TYPE_PROCESSOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Parser + { + using namespace Cult::Types; + + class TypeProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + TypeMap::Namespaces&); + }; + } +} + +#endif // CXX_PARSER_TYPE_PROCESSOR_HXX diff --git a/xsde/cxx/parser/validator.cxx b/xsde/cxx/parser/validator.cxx new file mode 100644 index 0000000..570a0bf --- /dev/null +++ b/xsde/cxx/parser/validator.cxx @@ -0,0 +1,704 @@ +// file : xsde/cxx/parser/validator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +#include + +using std::wcerr; + +namespace CXX +{ + namespace Parser + { + namespace + { + class ValidationContext: public Context + { + public: + ValidationContext (SemanticGraph::Schema& root, + CLI::Options const& options, + const WarningSet& disabled_warnings, + Boolean& valid_) + : Context (std::wcerr, root, options, 0, 0, 0), + disabled_warnings_ (disabled_warnings), + disabled_warnings_all_ (false), + valid (valid_), + subst_group_warning_issued (subst_group_warning_issued_), + subst_group_warning_issued_ (false) + { + } + + public: + Boolean + is_disabled (Char const* w) + { + return disabled_warnings_all_ || + disabled_warnings_.find (w) != disabled_warnings_.end (); + } + + public: + String + xpath (SemanticGraph::Nameable& n) + { + if (n.is_a ()) + return L""; // There is a bug if you see this. + + assert (n.named ()); + + SemanticGraph::Scope& scope (n.scope ()); + + if (scope.is_a ()) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + + protected: + ValidationContext (ValidationContext& c) + : Context (c), + disabled_warnings_ (c.disabled_warnings_), + disabled_warnings_all_ (c.disabled_warnings_all_), + valid (c.valid), + subst_group_warning_issued (c.subst_group_warning_issued) + { + } + + protected: + const WarningSet& disabled_warnings_; + Boolean disabled_warnings_all_; + Boolean& valid; + Boolean& subst_group_warning_issued; + Boolean subst_group_warning_issued_; + }; + + // + // + struct Any : Traversal::Any, ValidationContext + { + Any (ValidationContext& c) + : ValidationContext (c) + { + } + + struct Element: Traversal::Element, ValidationContext + { + Element (ValidationContext& c, SemanticGraph::Any& any) + : ValidationContext (c), + any_ (any), + ns_ (any.definition_namespace ().name ()) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Any; + + Boolean q (e.qualified ()); + String ns (q ? e.namespace_ ().name () : ""); + + for (Any::NamespaceIterator i (any_.namespace_begin ()); + i != any_.namespace_end (); ++i) + { + Boolean failed (false); + + if (*i == L"##any") + { + failed = true; + } + else if (*i == L"##other") + { + if (ns_) + { + // Note that here I assume that ##other does not + // include names without target namespace. This + // is not what the spec says but that seems to be + // the consensus. + // + failed = q && ns != ns_; + } + else + { + // No target namespace. + // + failed = q && ns != L""; + } + } + else if (*i == L"##local") + { + failed = !q || ns == L""; + } + else if (*i == L"##targetNamespace") + { + failed = (q && ns_ == ns) || (!q && ns_ == L""); + } + else + { + failed = q && *i == ns; + } + + if (failed) + { + Any& a (any_); + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning P001: namespace '" << *i << "' allows for " + << "element '" << e.name () << "'" << endl; + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning P001: generated code may not associate " + << "element '" << e.name () << "' correctly if it appears " + << "in place of this wildcard" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: element '" << e.name () << "' is defined " + << "here" << endl; + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": info: turn on validation to ensure correct " + << "association" << endl; + } + } + } + + private: + SemanticGraph::Any& any_; + String ns_; + }; + + struct Complex: Traversal::Complex + { + Complex () + : up_ (true), down_ (true) + { + } + + virtual Void + post (Type& c) + { + // Go down the inheritance hierarchy. + // + if (down_) + { + Boolean up = up_; + up_ = false; + + if (c.inherits_p ()) + dispatch (c.inherits ().base ()); + + up_ = up; + } + + // Go up the inheritance hierarchy. + // + if (up_) + { + Boolean down = down_; + down_ = false; + + for (Type::BegetsIterator i (c.begets_begin ()); + i != c.begets_end (); ++i) + { + dispatch (i->derived ()); + } + + down_ = down; + } + } + + private: + Boolean up_, down_; + }; + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Compositor; + + // Find our complex type. + // + Compositor* c (&a.contained_particle ().compositor ()); + + while(!c->contained_compositor_p ()) + c = &c->contained_particle ().compositor (); + + SemanticGraph::Complex& type ( + dynamic_cast ( + c->contained_compositor ().container ())); + + Complex complex; + Traversal::Compositor compositor; + Element element (*this, a); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + complex >> contains_compositor; + contains_compositor >> compositor; + compositor >> contains_particle; + contains_particle >> compositor; + contains_particle >> element; + + complex.dispatch (type); + } + }; + + + // + // + struct Traverser : Traversal::Schema, + Traversal::Complex, + Traversal::Type, + Traversal::Element, + ValidationContext + { + Traverser (ValidationContext& c) + : ValidationContext (c), + any_ (c) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + + // Any + // + if (!validation && !is_disabled ("P001")) + { + *this >> contains_compositor_ >> compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> any_; + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Schema; + + traverse (static_cast (c)); + + if (c.inherits_p ()) + { + SemanticGraph::Type& t (c.inherits ().base ()); + + if (t.named () && + types_.find ( + t.scope ().name () + L"#" + t.name ()) == types_.end ()) + { + // Don't worry about types that are in included/imported + // schemas. + // + Schema& s (dynamic_cast (t.scope ().scope ())); + + if (&s == &schema_root || sources_p (schema_root, s)) + { + valid = false; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": error: type '" << xpath (c) << "' inherits from " + << "yet undefined type '" << xpath (t) << "'" << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": info: '" << xpath (t) << "' is defined here" + << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: inheritance from a yet-undefined type is " + << "not supported" << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: re-arrange your schema and try again" + << endl; + } + } + } + + Complex::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (t.named ()) + { + types_.insert (t.scope ().name () + L"#" + t.name ()); + } + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (is_disabled ("P002")) + return; + + if (e.substitutes_p () && + !options.value () && + !subst_group_warning_issued) + { + subst_group_warning_issued = true; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": warning P002: substitution groups are used but " + << "--generate-polymorphic was not specified" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: generated code may not be able to parse " + << "some conforming instances" << endl; + } + } + + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + + // Any. + // + Any any_; + Traversal::Compositor compositor_; + Traversal::ContainsParticle contains_particle_; + Traversal::ContainsCompositor contains_compositor_; + }; + + // + // + struct AnonymousMember: protected ValidationContext + { + AnonymousMember (ValidationContext& c, Boolean& error_issued) + : ValidationContext (c), error_issued_ (error_issued) + { + } + + Boolean + traverse_common (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named () + && !t.is_a () + && !t.is_a ()) + { + if (!error_issued_) + { + valid = false; + error_issued_ = true; + + wcerr << t.file () + << ": error: anonymous types detected" + << endl; + + wcerr << t.file () + << ": info: " + << "anonymous types are not supported in this mapping" + << endl; + + wcerr << t.file () + << ": info: consider explicitly naming these types or " + << "remove the --preserve-anonymous option to " + << "automatically name them" + << endl; + + if (!options.value ()) + wcerr << t.file () + << ": info: use --show-anonymous option to see these " + << "types" << endl; + } + + return true; + } + + return false; + } + + private: + Boolean& error_issued_; + }; + + struct AnonymousElement: Traversal::Element, + AnonymousMember + { + AnonymousElement (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (traverse_common (e)) + { + if (options.value ()) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: element '" << xpath (e) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Element::traverse (e); + } + }; + + struct AnonymousAttribute: Traversal::Attribute, + AnonymousMember + { + AnonymousAttribute (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (Type& a) + { + if (traverse_common (a)) + { + if (options.value ()) + { + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: attribute '" << xpath (a) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Attribute::traverse (a); + } + }; + + struct AnonymousType : Traversal::Schema, + Traversal::Complex, + ValidationContext + { + AnonymousType (ValidationContext& c) + : ValidationContext (c), + error_issued_ (false), + element_ (c, error_issued_), + attribute_ (c, error_issued_) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + + *this >> contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> element_; + + *this >> names_attribute_ >> attribute_; + } + + private: + Boolean error_issued_; + + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + Traversal::Names names_; + + Traversal::Compositor compositor_; + AnonymousElement element_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + AnonymousAttribute attribute_; + Traversal::Names names_attribute_; + }; + + struct GlobalElement: Traversal::Element, ValidationContext + { + GlobalElement (ValidationContext& c, SemanticGraph::Element*& element) + : ValidationContext (c), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (!valid) + return; + + if (options.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (options.value ()) + { + element_ = &e; + } + else if (String name = options.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + { + if (element_ == 0) + element_ = &e; + else + { + wcerr << schema_root.file () << ": error: unable to generate " + << "the test driver without a unique document root" + << endl; + + wcerr << schema_root.file () << ": info: use --root-element-* " + << "options to specify the document root" << endl; + + valid = false; + } + } + } + + private: + SemanticGraph::Element*& element_; + }; + } + + Boolean Validator:: + validate (CLI::Options const& options, + SemanticGraph::Schema& root, + SemanticGraph::Path const&, + Boolean gen_driver, + const WarningSet& disabled_warnings) + { + Boolean valid (true); + ValidationContext ctx (root, options, disabled_warnings, valid); + + // + // + if (options.value () && + options.value ()) + { + wcerr << "error: mutually exclusive options specified: " + << "--generate-noop-impl and --generate-print-impl" + << endl; + + return false; + } + + // + // + { + Boolean ref (options.value ()); + Boolean rel (options.value ()); + Boolean re (options.value ()); + + if ((ref && rel) || (ref && re) || (rel && re)) + { + wcerr << "error: mutually exclusive options specified: " + << "--root-element-last, --root-element-first, and " + << "--root-element" + << endl; + + return false; + } + } + + // + // + if (options.value () && + options.value ()) + { + wcerr << "error: mutually exclusive options specified: " + << "--reuse-style-mixin and --reuse-style-none" + << endl; + + return false; + } + + // + // + if (options.value () && + (options.value () || + options.value ()) && + !ctx.is_disabled ("P003")) + { + wcerr << "warning P003: generating sample implementation without " + << "parser reuse support: the resulting code may not compile" + << endl; + + return false; + } + + // Test for anonymout types. + // + { + AnonymousType traverser (ctx); + traverser.dispatch (root); + } + + // Test the rest. + // + if (valid) + { + Traverser traverser (ctx); + traverser.dispatch (root); + } + + // Test that the document root is unique. + // + if (valid && gen_driver) + { + SemanticGraph::Element* element (0); + + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalElement global_element (ctx, element); + + schema >> schema_names >> ns >> ns_names >> global_element; + + schema.dispatch (root); + + if (valid && element == 0) + { + wcerr << root.file () << ": error: unable to generate the " + << "test driver without a global element (document root)" + << endl; + + valid = false; + } + } + + return valid; + } + } +} diff --git a/xsde/cxx/parser/validator.hxx b/xsde/cxx/parser/validator.hxx new file mode 100644 index 0000000..d602aae --- /dev/null +++ b/xsde/cxx/parser/validator.hxx @@ -0,0 +1,36 @@ +// file : xsde/cxx/parser/validator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_PARSER_VALIDATOR_HXX +#define CXX_PARSER_VALIDATOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Parser + { + using namespace Cult::Types; + + class Validator + { + public: + Boolean + validate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& tu, + Boolean gen_driver, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // CXX_PARSER_VALIDATOR_HXX diff --git a/xsde/cxx/serializer/attribute-validation-source.cxx b/xsde/cxx/serializer/attribute-validation-source.cxx new file mode 100644 index 0000000..59d3cb5 --- /dev/null +++ b/xsde/cxx/serializer/attribute-validation-source.cxx @@ -0,0 +1,463 @@ +// file : xsde/cxx/serializer/attribute-validation-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct AnyAttributeTest: Traversal::AnyAttribute, Context + { + AnyAttributeTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& ns (a.definition_namespace ().name ()); + + for (SemanticGraph::AnyAttribute::NamespaceIterator + i (a.namespace_begin ()), e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + if (stl) + os << "!name.empty ()"; + else + os << "(name != 0 && *name != '\\0')"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + if (stl) + os << "(!ns.empty () && ns != " << strlit (ns) << ")"; + else + os << "(ns != 0 && *ns != '\\0' && " << + "strcmp (ns, " << strlit (ns) << ") != 0)"; + } + else + { + if (stl) + os << "!ns.empty ()"; + else + os << "(ns != 0 && *ns != '\\0')"; + } + } + else if (*i == L"##local") + { + if (stl) + os << "(ns.empty () && !name.empty ())"; + else + os << "((ns == 0 || *ns == '\\0') && " << + "name != 0 && *name != '\\0')"; + } + else if (*i == L"##targetNamespace") + { + if (stl) + os << "ns == " << strlit (ns); + else + os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)"; + } + else + { + if (stl) + os << "ns == " << strlit (*i); + else + os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)"; + } + + if (++i != e) + os << " ||" << endl; + } + } + }; + + struct Attribute: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + Attribute (Context& c) + : Context (c), any_attribute_test_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + + os << "// " << name << endl + << "//" << endl; + + if (a.optional ()) + { + os << "if (this->" << epresent (a) << " ())"; + } + + os << "{"; + + String const& inst (emember (a)); + String const& ret (ret_type (a.type ())); + String const& arg (arg_type (a.type ())); + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (this->" << inst << ")" + << "{"; + + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + if (!exceptions) + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + { + if (a.qualified () && a.namespace_ ().name ()) + os << "this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << ");"; + else + os << "this->_start_attribute (" << strlit (a.name ()) << ");"; + } + else + { + os << "if (!"; + + if (a.qualified () && a.namespace_ ().name ()) + os << "this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << ")"; + else + os << "this->_start_attribute (" << strlit (a.name ()) << ")"; + + os << ")" << endl + << "return;" + << endl; + } + + os << "this->" << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_attribute ();"; + else + os << "if (!this->_end_attribute ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->post ();"; + + if (!exceptions) + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl + << "if (ctx.error_type ())" << endl + << "return;"; + + os << "}"; // if (inst) + + if (!a.optional ()) + { + os << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_attribute);" + << "return;" + << "}"; + } + + os << "}"; + + if (a.optional () && !exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << "while (this->" << enext (a) << " ())" + << "{"; + + if (stl) + { + os << "::std::string ns, name;" + << "this->" << ename (a) << " (ns, name);" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if ("; + + any_attribute_test_.dispatch (a); + + os << ")" + << "{"; + + os << "if (ns.empty ())" + << "{"; + + if (exceptions) + os << "this->_start_attribute (name.c_str ());"; + else + os << "if (!this->_start_attribute (name.c_str ()))" << endl + << "return;"; + + os << "}" + << "else" + << "{"; + + if (exceptions) + os << "this->_start_attribute (ns.c_str (), name.c_str ());"; + else + os << "if (!this->_start_attribute (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;"; + + os << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_attribute ();"; + else + os << "if (!this->_end_attribute ())" << endl + << "return;"; + + os << "}" // test + << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::unexpected_attribute);" + << "return;" + << "}"; + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;" + << "this->" << ename (a) << " (ns, name, free);" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + else + os << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}"; + + os << "if ("; + + any_attribute_test_.dispatch (a); + + os << ")" + << "{"; + + if (exceptions) + os << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_attribute (name);" + << "else" << endl + << "this->_start_attribute (ns, name);" + << endl; + else + os << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_attribute (name);" + << "else" << endl + << "r = this->_start_attribute (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl; + + os << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_attribute ();"; + else + os << "if (!this->_end_attribute ())" << endl + << "return;"; + + os << "}" // test + << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::unexpected_attribute);" + << "return;" + << "}"; + } + + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + + private: + AnyAttributeTest any_attribute_test_; + }; + + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + attribute_ (c) + { + names_attribute_ >> attribute_; + } + + virtual Void + traverse (Type& c) + { + if (!has (c) && + !has (c)) + return; + + // Don't use restriction_p here since we don't want special + // treatment of anyType. + // + Boolean restriction ( + c.inherits_p () && + c.inherits ().is_a ()); + + String const& name (ename (c)); + + os <<"// Attribute validation and serialization for " << + name << "." << endl + <<"//" << endl; + + os << "void " << name << "::" << endl + << "_serialize_attributes ()" + << "{" + << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (c.inherits_p () && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_attributes ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + + names (c, names_attribute_); + + os << "}"; + } + + private: + Attribute attribute_; + Traversal::Names names_attribute_; + }; + } + + Void + generate_attribute_validation_source (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Complex complex (ctx); + + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/attribute-validation-source.hxx b/xsde/cxx/serializer/attribute-validation-source.hxx new file mode 100644 index 0000000..d06890d --- /dev/null +++ b/xsde/cxx/serializer/attribute-validation-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/attribute-validation-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX +#define CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_attribute_validation_source (Context&); + } +} + +#endif // CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX diff --git a/xsde/cxx/serializer/cli.hxx b/xsde/cxx/serializer/cli.hxx new file mode 100644 index 0000000..5b1b7fa --- /dev/null +++ b/xsde/cxx/serializer/cli.hxx @@ -0,0 +1,154 @@ +// file : xsde/cxx/serializer/cli.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_CLI_HXX +#define CXX_SERIALIZER_CLI_HXX + +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace CLI + { + using namespace Cult::Types; + + typedef Char const Key[]; + + extern Key type_map; + extern Key no_stl; + extern Key no_iostream; + extern Key no_exceptions; + extern Key no_long_long; + extern Key reuse_style_mixin; + extern Key reuse_style_none; + extern Key generate_inline; + extern Key suppress_validation; + extern Key generate_polymorphic; + extern Key runtime_polymorphic; + extern Key suppress_reset; + extern Key generate_empty_impl; + extern Key generate_test_driver; + extern Key force_overwrite; + extern Key root_element_first; + extern Key root_element_last; + extern Key root_element; + extern Key generate_xml_schema; + extern Key extern_xml_schema; + extern Key output_dir; + extern Key skel_type_suffix; + extern Key skel_file_suffix; + extern Key impl_type_suffix; + extern Key impl_file_suffix; + extern Key namespace_map; + extern Key namespace_regex; + extern Key namespace_regex_trace; + extern Key reserved_name; + extern Key include_with_brackets; + extern Key include_prefix; + extern Key include_regex; + extern Key include_regex_trace; + extern Key guard_prefix; + extern Key hxx_suffix; + extern Key ixx_suffix; + extern Key cxx_suffix; + extern Key hxx_regex; + extern Key ixx_regex; + extern Key cxx_regex; + extern Key hxx_prologue; + extern Key ixx_prologue; + extern Key cxx_prologue; + extern Key prologue; + extern Key hxx_epilogue; + extern Key ixx_epilogue; + extern Key cxx_epilogue; + extern Key epilogue; + extern Key hxx_prologue_file; + extern Key ixx_prologue_file; + extern Key cxx_prologue_file; + extern Key prologue_file; + extern Key hxx_epilogue_file; + extern Key ixx_epilogue_file; + extern Key cxx_epilogue_file; + extern Key epilogue_file; + extern Key show_anonymous; + extern Key show_sloc; + extern Key proprietary_license; + + typedef Cult::CLI::Options< + type_map, Cult::Containers::Vector, + no_stl, Boolean, + no_iostream, Boolean, + no_exceptions, Boolean, + no_long_long, Boolean, + reuse_style_mixin, Boolean, + reuse_style_none, Boolean, + generate_inline, Boolean, + suppress_validation, Boolean, + generate_polymorphic, Boolean, + runtime_polymorphic, Boolean, + suppress_reset, Boolean, + generate_empty_impl, Boolean, + generate_test_driver, Boolean, + force_overwrite, Boolean, + root_element_first, Boolean, + root_element_last, Boolean, + root_element, NarrowString, + generate_xml_schema, Boolean, + extern_xml_schema, NarrowString, + output_dir, NarrowString, + skel_type_suffix, NarrowString, + skel_file_suffix, NarrowString, + impl_type_suffix, NarrowString, + impl_file_suffix, NarrowString, + namespace_map, Cult::Containers::Vector, + namespace_regex, Cult::Containers::Vector, + namespace_regex_trace, Boolean, + reserved_name, Cult::Containers::Vector, + include_with_brackets, Boolean, + include_prefix, NarrowString, + include_regex, Cult::Containers::Vector, + include_regex_trace, Boolean, + guard_prefix, NarrowString, + hxx_suffix, NarrowString, + ixx_suffix, NarrowString, + cxx_suffix, NarrowString, + hxx_regex, NarrowString, + ixx_regex, NarrowString, + cxx_regex, NarrowString, + hxx_prologue, Cult::Containers::Vector, + ixx_prologue, Cult::Containers::Vector, + cxx_prologue, Cult::Containers::Vector, + prologue, Cult::Containers::Vector, + hxx_epilogue, Cult::Containers::Vector, + ixx_epilogue, Cult::Containers::Vector, + cxx_epilogue, Cult::Containers::Vector, + epilogue, Cult::Containers::Vector, + hxx_prologue_file, NarrowString, + ixx_prologue_file, NarrowString, + cxx_prologue_file, NarrowString, + prologue_file, NarrowString, + hxx_epilogue_file, NarrowString, + ixx_epilogue_file, NarrowString, + cxx_epilogue_file, NarrowString, + epilogue_file, NarrowString, + show_anonymous, Boolean, + show_sloc, Boolean, + proprietary_license, Boolean + + > Options; + + struct OptionsSpec: Cult::CLI::OptionsSpec {}; + } + } +} + +#endif // CXX_SERIALIZER_CLI_HXX diff --git a/xsde/cxx/serializer/driver-source.cxx b/xsde/cxx/serializer/driver-source.cxx new file mode 100644 index 0000000..4a3c7db --- /dev/null +++ b/xsde/cxx/serializer/driver-source.cxx @@ -0,0 +1,1047 @@ +// file : xsde/cxx/serializer/driver-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + typedef + Cult::Containers::Map + TypeInstanceMap; + + typedef Cult::Containers::Set InstanceSet; + + // For base types we only want member's types, but not the + // base itself. + // + struct BaseType: Traversal::Complex, Context + { + BaseType (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + }; + + struct SerializerDef: Traversal::Type, + Traversal::List, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set) + : Context (c), map_ (map), set_ (set), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (t)); + map_[&t] = inst; + + os << fq_name (t, "s:impl") << " " << inst << ";"; + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (map_.find (&l) == map_.end ()) + { + String inst (find_instance_name (l)); + map_[&l] = inst; + + os << fq_name (l, "s:impl") << " " << inst << ";"; + + dispatch (l.argumented ().type ()); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (map_.find (&c) == map_.end ()) + { + String inst (find_instance_name (c)); + map_[&c] = inst; + + os << fq_name (c, "s:impl") << " " << inst << ";"; + + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + fund_type (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + fund_type (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fund_type (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fund_type (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fund_type (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + fund_type (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fund_type (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + fund_type (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fund_type (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + fund_type (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fund_type (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fund_type (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fund_type (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fund_type (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fund_type (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fund_type (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + fund_type (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + fund_type (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + fund_type (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + fund_type (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + fund_type (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + fund_type (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + fund_type (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + fund_type (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + fund_type (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + fund_type (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + fund_type (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + fund_type (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + fund_type (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + fund_type (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + fund_type (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + fund_type (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + fund_type (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + fund_type (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + fund_type (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + fund_type (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + fund_type (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + fund_type (t, "day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + fund_type (t, "month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + fund_type (t, "month_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + fund_type (t, "year"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + fund_type (t, "year_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + fund_type (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + fund_type (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + fund_type (t, "entities"); + } + + private: + virtual Void + fund_type (SemanticGraph::Type& t, String const& name) + { + if (map_.find (&t) == map_.end ()) + { + String inst (find_instance_name (name)); + map_[&t] = inst; + + os << fq_name (t, "s:impl") << " " << inst << ";"; + } + } + + String + find_instance_name (String const& raw_name) + { + String base_name (escape (raw_name + L"_s")); + String name (base_name); + + for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i) + { + std::wostringstream os; + os << i; + name = base_name + os.str (); + } + + set_.insert (name); + return name; + } + + String + find_instance_name (SemanticGraph::Type& t) + { + return find_instance_name (t.name ()); + } + + TypeInstanceMap& map_; + InstanceSet& set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + // + // + struct ParticleArg: Traversal::Element, Context + { + ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&e.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct AttributeArg: Traversal::Attribute, Context + { + AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first) + : Context (c), map_ (map), first_ (first) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&a.type ()]; + } + + private: + TypeInstanceMap& map_; + Boolean& first_; + }; + + struct ArgList : Traversal::Complex, + Traversal::List, + Context + { + ArgList (Context& c, TypeInstanceMap& map) + : Context (c), + map_ (map), + particle_ (c, map, first_), + attribute_ (c, map, first_), + first_ (true) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << map_[&l.argumented ().type ()]; + } + + private: + TypeInstanceMap& map_; + + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleArg particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + AttributeArg attribute_; + + Boolean first_; + }; + + struct SerializerConnect: Traversal::List, + Traversal::Complex, + Context + { + SerializerConnect (Context& c, TypeInstanceMap& map) + : Context (c), map_ (map), base_ (c) + { + *this >> inherits_ >> base_ >> inherits_; + + *this >> contains_compositor_; + base_ >> contains_compositor_; + + *this >> names_; + base_ >> names_; + + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_ >> attribute_; + + particle_ >> belongs_; + attribute_ >> belongs_; + belongs_ >> *this; + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (type_set_.find (&l) == type_set_.end ()) + { + os << map_[&l] << ".serializers (" << + map_[&l.argumented ().type ()] << ");" + << endl; + + type_set_.insert (&l); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (type_set_.find (&c) == type_set_.end ()) + { + if (has_members (c)) + { + os << map_[&c] << ".serializers ("; + + ArgList args (*this, map_); + args.dispatch (c); + + os << ");" + << endl; + } + + type_set_.insert (&c); + + inherits (c); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + } + + private: + Boolean + has_members (SemanticGraph::Complex& c) + { + using SemanticGraph::Complex; + + if (has (c)) + return true; + + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&b)) + return has_members (*cb); + + return b.is_a (); + } + + return false; + } + + private: + TypeInstanceMap& map_; + Cult::Containers::Set type_set_; + + BaseType base_; + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + Traversal::Element particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Traversal::Names names_; + Traversal::Attribute attribute_; + + Traversal::Belongs belongs_; + }; + + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c, SemanticGraph::Element*& element) + : Context (c), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (options.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (String name = options.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + element_ = &e; // Cover root-element-last and no option. + } + + private: + SemanticGraph::Element*& element_; + }; + } + + Void + generate_driver_source (Context& ctx) + { + // Figure out the root element. Validator should have made sure + // it is unique. + // + SemanticGraph::Element* root (0); + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + RootElement global_element (ctx.options, root); + + schema >> schema_names >> ns >> ns_names >> global_element; + + schema.dispatch (ctx.schema_root); + } + + String xs (ctx.xs_ns_name ()); + std::wostream& os (ctx.os); + + InstanceSet set; + TypeInstanceMap map; + SemanticGraph::Type& root_type (root->type ()); + + set.insert ("doc_s"); + + if (ctx.options.value ()) + os << "#include " << endl + << endl; + else + os << "#include " << endl + << endl; + + if (ctx.options.value ()) + { + if (ctx.options.value ()) + { + os << "struct writer: " << xs << "::writer" + << "{" + << "virtual bool" << endl + << "write (const char* s, size_t n)" + << "{" + << "return fwrite (s, n, 1, stdout) == 1;" + << "}" + << "virtual bool" << endl + << "flush ()" + << "{" + << "return fflush (stdout) == 0;" + << "}" + << "};"; + } + else + { + os << "struct io_failure" + << "{" + << "};"; + + os << "struct writer: " << xs << "::writer" + << "{" + << "virtual void" << endl + << "write (const char* s, size_t n)" + << "{" + << "if (fwrite (s, n, 1, stdout) != 1)" << endl + << "throw io_failure ();" + << "}" + << "virtual void" << endl + << "flush ()" + << "{" + << "if (fflush (stdout) != 0)" << endl + << "throw io_failure ();" + << "}" + << "};"; + } + } + + os << "int" << endl + << "main ()" + << "{"; + + if (!ctx.options.value ()) + os << "try" + << "{"; + + os << "// Instantiate individual serializers." << endl + << "//" << endl; + + { + SerializerDef def (ctx, map, set); + def.dispatch (root_type); + } + + os << endl + << "// Connect the serializers together." << endl + << "//" << endl; + + { + // @@ I can simply iterate over the map instead of traversing + // the tree all over again. + // + SerializerConnect connect (ctx, map); + connect.dispatch (root_type); + } + + String const& root_s (map[&root_type]); + + os << "// Serialize the XML document." << endl + << "//" << endl; + + if (ctx.options.value ()) + os << "writer w;"; + + if (ctx.options.value ()) + os << xs << "::serializer_error e;" + << endl + << "do" + << "{"; + + if (root->namespace_().name ()) + os << xs << "::document_simpl doc_s (" << endl + << root_s << "," << endl + << ctx.strlit (root->namespace_().name ()) << "," << endl + << ctx.strlit (root->name ()) << ");" + << endl; + else + os << xs << "::document_simpl doc_s (" << root_s << ", " << + ctx.strlit (root->name ()) << ");" + << endl; + + if (ctx.options.value ()) + os << "if (e = doc_s._error ())" << endl + << "break;" + << endl; + + if (Context::arg_type (root->type ()) != L"void") + os << "// TODO: pass the " << root->name () << " element data " << + "to pre()" << endl + << "//" << endl; + + os << root_s << ".pre ();" + << endl; + + if (ctx.options.value ()) + os << "if (e = " << root_s << "._error ())" << endl + << "break;" + << endl; + + if (ctx.options.value ()) + os << "doc_s.serialize (w);" + << endl; + else + os << "doc_s.serialize (std::cout);" + << endl; + + if (ctx.options.value ()) + os << "if (e = doc_s._error ())" << endl + << "break;" + << endl; + + os << root_s << ".post ();"; + + if (ctx.options.value ()) + os << endl + << "e = " << root_s << "._error ();"; + + if (ctx.options.value ()) + os << "}" + << "while (false);" + << endl; + + // Error handling. + // + + if (ctx.options.value ()) + { + os << "// Handle errors." << endl + << "//" << endl + << "if (e)" + << "{" + << "switch (e.type ())" + << "{" + << "case " << xs << "::serializer_error::sys:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s\\n\", e.sys_text ());"; + else + os << "std::cerr << e.sys_text () << std::endl;"; + + os << "break;" + << "}" + << "case " << xs << "::serializer_error::xml:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s\\n\", e.xml_text ());"; + else + os << "std::cerr << e.xml_text () << std::endl;"; + + os << "break;" + << "}"; + + if (!ctx.options.value ()) + { + os << "case " << xs << "::serializer_error::schema:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"%s\\n\", e.schema_text ());"; + else + os << "std::cerr << e.schema_text () << std::endl;"; + + os << "break;" + << "}"; + } + + os << "case " << xs << "::serializer_error::app:" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"application error %d\\n\", e.app_code ());"; + else + os << "std::cerr << \"application error \" << e.app_code () " << + "<< std::endl;"; + + os << "break;" + << "}" + << "default:" + << "{" + << "break;" + << "}" + << "}" //switch + << "return 1;" + << "}"; // if (e) + } + else + { + os << "}" // try + << "catch (const " << xs << "::serializer_exception& e)" + << "{"; + + if (ctx.options.value ()) + os << "fprintf (stderr, \"error: %s\\n\", e.text ());"; + else + os << "std::cerr << \"error: \" << e.text () << std::endl;"; + + os << "return 1;" + << "}"; + + if (ctx.options.value ()) + os << "catch (const io_failure&)" + << "{" + << "fprintf (stderr, \"error: write failure\\n\");" + << "return 1;" + << "}"; + else + os << "catch (const std::ios_base::failure&)" + << "{" + << "std::cerr << \"error: write failure\" << std::endl;" + << "return 1;" + << "}"; + } + + os << "return 0;" + << "}"; // main + } + } +} diff --git a/xsde/cxx/serializer/driver-source.hxx b/xsde/cxx/serializer/driver-source.hxx new file mode 100644 index 0000000..b29cf34 --- /dev/null +++ b/xsde/cxx/serializer/driver-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/driver-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_DRIVER_SOURCE_HXX +#define CXX_SERIALIZER_DRIVER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_driver_source (Context&); + } +} + +#endif // CXX_SERIALIZER_DRIVER_SOURCE_HXX diff --git a/xsde/cxx/serializer/element-validation-source.cxx b/xsde/cxx/serializer/element-validation-source.cxx new file mode 100644 index 0000000..fd0dfb4 --- /dev/null +++ b/xsde/cxx/serializer/element-validation-source.cxx @@ -0,0 +1,903 @@ +// file : xsde/cxx/serializer/element-validation-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct AnyTest: Traversal::Any, Context + { + AnyTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& ns (a.definition_namespace ().name ()); + + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + if (stl) + os << "!name.empty ()"; + else + os << "(name != 0 && *name != '\\0')"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + if (stl) + os << "(!ns.empty () && ns != " << strlit (ns) << ")"; + else + os << "(ns != 0 && *ns != '\\0' && " << + "strcmp (ns, " << strlit (ns) << ") != 0)"; + } + else + { + if (stl) + os << "!ns.empty ()"; + else + os << "(ns != 0 && *ns != '\\0')"; + } + } + else if (*i == L"##local") + { + if (stl) + os << "(ns.empty () && !name.empty ())"; + else + os << "((ns == 0 || *ns == '\\0') && " << + "name != 0 && *name != '\\0')"; + } + else if (*i == L"##targetNamespace") + { + if (stl) + os << "ns == " << strlit (ns); + else + os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)"; + } + else + { + if (stl) + os << "ns == " << strlit (*i); + else + os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)"; + } + + if (++i != e) + os << " ||" << endl; + } + } + }; + + struct Compositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + Compositor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + UnsignedLong min (a.min ()); + + if (min == 0) + os << "if (this->" << epresent (a) << " ())" + << "{"; + + Traversal::All::traverse (a); + + if (min == 0) + { + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (c) << " ())" + << "{"; + } + else if (max != 1) + { + // We only need to count if max != unbounded || min != 0. + // + if (max != 0 || min != 0) + { + os << "{" + << "size_t i = 0;" + << "for (; "; + + if (max != 0) + os << "i < " << max << "UL && "; + + os << "this->" << enext (c) << " (); ++i)" + << "{"; + } + else + os << "while (this->" << enext (c) << " ())" + << "{"; + } + else if (!exceptions) + { + // Only sequence can have several choice compositors in a row. + // + os << "{"; + } + + if (exceptions) + os << "switch (this->" << earm (c) << " ())"; + else + os << earm_tag (c) << " t = this->" << earm (c) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "switch (t)"; + + + os << "{"; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()); i != c.contains_end (); ++i) + { + os << "case " << etag (i->particle ()) << ":" + << "{"; + + edge_traverser ().dispatch (*i); + + os << "break;" + << "}"; + } + + os << "default:" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::unexpected_element);" + << "return;" + << "}" + << "}"; // switch + + if (min == 0 && max == 1) + { + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + else if (max != 1) + { + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (max != 0 || min != 0) + { + if (min != 0) + { + os << "if (i < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + } + + os << "}"; + } + } + else if (!exceptions) + { + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (s) << " ())" + << "{"; + } + else if (max != 1) + { + // We only need to count if max != unbounded || min != 0. + // + if (max != 0 || min != 0) + { + os << "{" + << "size_t i = 0;" + << "for (; "; + + if (max != 0) + os << "i < " << max << "UL && "; + + os << "this->" << enext (s) << " (); ++i)" + << "{"; + } + else + os << "while (this->" << enext (s) << " ())" + << "{"; + } + + Traversal::Sequence::traverse (s); + + if (min == 0 && max == 1) + { + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + else if (max != 1) + { + os << "}"; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (max != 0 || min != 0) + { + if (min != 0) + { + os << "if (i < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + } + + os << "}"; + } + } + } + }; + + struct Particle: Traversal::Element, + Traversal::Any, + Context + { + Particle (Context& c) + : Context (c), any_test_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& name (ename (e)); + + os << "// " << name << endl + << "//" << endl; + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (e) << " ())"; + } + else if (max != 1) + { + // We only need to count if max != unbounded || min != 0. + // + if (max != 0 || min != 0) + { + os << "{" + << "size_t i = 0;" + << "for (; "; + + if (max != 0) + os << "i < " << max << "UL && "; + + os << "this->" << enext (e) << " (); ++i)"; + } + else + os << "while (this->" << enext (e) << " ())"; + } + + os << "{"; + + String const& ret (ret_type (e.type ())); + String const& arg (arg_type (e.type ())); + String fq_type (fq_name (e.type ())); + + Boolean poly (poly_code && !anonymous (e.type ())); + String inst (poly ? String (L"s") : L"this->" + emember (e)); + + if (poly) + os << "ctx.type_id (0);"; + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (poly) + { + // In case of mixin we use virtual inheritance and only + // dynamic_cast can be used. + // + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + + os << "const void* t = ctx.type_id ();" + << "const char* dt = 0;" + << fq_type << "* " << inst << " = 0;" + << endl + << "if (t == 0 && this->" << emember (e) << " != 0)" << endl + << inst << " = this->" << emember (e) << ";" + << "else if (this->" << emember_map (e) << " != 0)" + << "{" + << serializer_base << "* b = this->" << emember_map (e) << + "->find (t);" + << endl + << "if (b != 0)" + << "{" + << "dt = b->_dynamic_type ();" + << "const char* st = " << fq_type << "::_static_type ();" + << endl + << "if (strcmp (dt, st) == 0)" << endl + << "dt = 0;" + << endl; + + // Check that the types are related by inheritance. + // + os << "if (dt != 0 && !::xsde::cxx::serializer::validating::" << + "inheritance_map_instance ().check (dt, st))" + << "{" + << "ctx.schema_error (::xsde::cxx::schema_error::not_derived);" + << "return;" + << "}"; + + os << inst << " = " << cast << "< " << fq_type << "* > (b);" + << "}" + << "}"; + } + + os << "if (" << inst << ")" + << "{"; + + if (ret == L"void") + os << inst << "->pre ();"; + else + os << inst << "->pre (r);"; + + if (!exceptions) + { + // Note that after pre() we need to check both parser and + // context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + + // Only a globally-defined element can be a subst-group root. + // + if (poly && e.global ()) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "const char* ns = " << + strlit (e.namespace_ ().name ()) << ";"; + else + os << "const char* ns = 0;"; + + os << "const char* n = " << strlit (e.name ()) << ";" + << endl; + + os << "if (dt != 0 && " << + "::xsde::cxx::serializer::substitution_map_instance ()" << + ".check (ns, n, dt))" << endl + << "dt = 0;" + << endl; + + if (exceptions) + { + os << "if (ns != 0)" << endl + << "this->_start_element (ns, n);" + << "else" << endl + << "this->_start_element (n);" + << endl; + } + else + { + os << "if (ns != 0)" + << "{" + << "if (!this->_start_element (ns, n))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_element (n))" << endl + << "return;" + << "}"; + } + } + else + { + if (exceptions) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << ");"; + else + os << "this->_start_element (" << strlit (e.name ()) << ");"; + } + else + { + os << "if (!"; + + if (e.qualified () && e.namespace_ ().name ()) + os << "this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << ")"; + else + os << "this->_start_element (" << strlit (e.name ()) << ")"; + + os << ")" << endl + << "return;" + << endl; + } + } + + if (poly) + { + // Set xsi:type if necessary. + // + if (exceptions) + os << "if (dt != 0)" << endl + << "this->_set_type (dt);" + << endl; + else + os << "if (dt != 0)" + << "{" + << "if (!this->_set_type (dt))" << endl + << "return;" + << "}"; + } + + os << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_attributes ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_element ();"; + else + os << "if (!this->_end_element ())" << endl + << "return;" + << endl; + + os << inst << "->post ();"; + + if (!exceptions) + { + // Note that after post() we need to check both parser and + // context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl + << "if (ctx.error_type ())" << endl + << "return;"; + } + + os << "}"; // if (inst) + + if (min != 0) + { + os << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + } + + os << "}"; + + if (min == 0 && max == 1) + { + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + else if (max != 1) + { + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (max != 0 || min != 0) + { + if (min != 0) + { + os << "if (i < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + } + + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (a) << " ())"; + + } + else if (max != 1) + { + // We only need to count if max != unbounded || min != 0. + // + if (max != 0 || min != 0) + { + os << "{" + << "size_t i = 0;" + << "for (; "; + + if (max != 0) + os << "i < " << max << "UL && "; + + os << "this->" << enext (a) << " (); ++i)"; + } + else + os << "while (this->" << enext (a) << " ())"; + } + + os << "{"; + + if (stl) + { + os << "::std::string ns, name;" + << "this->" << ename (a) << " (ns, name);" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if ("; + + any_test_.dispatch (a); + + os << ")" + << "{"; + + os << "if (ns.empty ())" + << "{"; + + if (exceptions) + os << "this->_start_element (name.c_str ());"; + else + os << "if (!this->_start_element (name.c_str ()))" << endl + << "return;"; + + os << "}" + << "else" + << "{"; + + if (exceptions) + os << "this->_start_element (ns.c_str (), name.c_str ());"; + else + os << "if (!this->_start_element (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;"; + + os << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_element ();"; + else + os << "if (!this->_end_element ())" << endl + << "return;"; + + os << "}" // test + << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::unexpected_element);" + << "return;" + << "}"; + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;" + << "this->" << ename (a) << " (ns, name, free);" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + else + os << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}"; + + os << "if ("; + + any_test_.dispatch (a); + + os << ")" + << "{"; + + if (exceptions) + os << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_element (name);" + << "else" << endl + << "this->_start_element (ns, name);" + << endl; + else + os << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_element (name);" + << "else" << endl + << "r = this->_start_element (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl; + + os << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (exceptions) + os << "this->_end_element ();"; + else + os << "if (!this->_end_element ())" << endl + << "return;"; + + os << "}" // test + << "else" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::unexpected_element);" + << "return;" + << "}"; + } + + os << "}"; + + if (min == 0 && max == 1) + { + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + else if (max != 1) + { + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (max != 0 || min != 0) + { + if (min != 0) + { + os << "if (i < " << min << "UL)" + << "{" + << "this->_schema_error (" << + "::xsde::cxx::schema_error::expected_element);" + << "return;" + << "}"; + } + + os << "}"; + } + } + } + + private: + AnyTest any_test_; + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_ (c), + particle_ (c) + { + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + } + + virtual Void + traverse (Type& c) + { + if (!has (c) && + !has_particle (c)) + return; + + // Don't use restriction_p here since we don't want special + // treatment of anyType. + // + Boolean restriction ( + c.inherits_p () && + c.inherits ().is_a ()); + + String const& name (ename (c)); + + os <<"// Element validation and serialization for " << + name << "." << endl + <<"//" << endl; + + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{" + << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (c.inherits_p () && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_content ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + + contains_compositor (c, contains_compositor_); + + os << "}"; + } + + private: + Compositor compositor_; + Particle particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + }; + } + + Void + generate_element_validation_source (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Complex complex (ctx); + + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/element-validation-source.hxx b/xsde/cxx/serializer/element-validation-source.hxx new file mode 100644 index 0000000..5649457 --- /dev/null +++ b/xsde/cxx/serializer/element-validation-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/element-validation-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX +#define CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_element_validation_source (Context&); + } +} + +#endif // CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX diff --git a/xsde/cxx/serializer/elements.cxx b/xsde/cxx/serializer/elements.cxx new file mode 100644 index 0000000..f130254 --- /dev/null +++ b/xsde/cxx/serializer/elements.cxx @@ -0,0 +1,278 @@ +// file : xsde/cxx/serializer/elements.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace CXX +{ + namespace Serializer + { + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + CLI::Options const& ops, + Regex const* he, + Regex const* ie, + Regex const* hie) + : CXX::Context (o, + root, + "s:name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + options (ops), + xml_serializer (xml_serializer_), + serializer_base (serializer_base_), + simple_base (simple_base_), + complex_base (complex_base_), + serializer_map (serializer_map_), + validation (!ops.value ()), + exceptions (!ops.value ()), + stl (!ops.value ()), + poly_code (ops.value ()), + poly_runtime (poly_code || ops.value ()), + reset (!ops.value ()), + mixin (ops.value ()), + tiein (!mixin && !ops.value ()), + hxx_expr (he), + ixx_expr (ie), + hxx_impl_expr (hie), + xml_serializer_ ("genx") + { + String xs_ns (xs_ns_name ()); + + string_type = L"::xsde::cxx::ro_string"; + + serializer_base_ = xs_ns + L"::serializer_base"; + + simple_base_ = L"::xsde::cxx::serializer::"; + simple_base_ += (validation ? L"validating" : L"non_validating"); + simple_base_ += L"::simple_content"; + + complex_base_ = L"::xsde::cxx::serializer::"; + complex_base_ += (validation ? L"validating" : L"non_validating"); + complex_base_ += L"::complex_content"; + + if (poly_code) + serializer_map_ = xs_ns + L"::serializer_map"; + } + + String Context:: + real_fq_name (SemanticGraph::Nameable& n) + { + SemanticGraph::Context& c (n.context ()); + + if (c.count ("s:real-name")) + return c.get ("s:real-name"); + else + return fq_name (n); + } + + Content::Value Context:: + content (SemanticGraph::Complex& c) + { + using namespace SemanticGraph; + + if (c.mixed ()) + return Content::mixed; + + if (c.inherits_p ()) + { + Type& base (c.inherits ().base ()); + + if (Complex* cb = dynamic_cast (&base)) + return content (*cb); + + if (base.is_a ()) + return Content::complex; + + // Everyhting else (built-in type and AnySimpleType) is simple + // content. + // + return Content::simple; + } + else + return Content::complex; + } + + String const& Context:: + ret_type (SemanticGraph::Type& t) + { + return t.context ().get ("s:ret-type"); + } + + String const& Context:: + arg_type (SemanticGraph::Type& t) + { + return t.context ().get ("s:arg-type"); + } + + // + // + String const& Context:: + epresent (SemanticGraph::Particle& p) + { + return p.context ().get ("s:present"); + } + + String const& Context:: + epresent (SemanticGraph::Attribute& a) + { + return a.context ().get ("s:present"); + } + + String const& Context:: + enext (SemanticGraph::Particle& p) + { + return p.context ().get ("s:next"); + } + + String const& Context:: + enext (SemanticGraph::AnyAttribute& a) + { + return a.context ().get ("s:next"); + } + + String const& Context:: + etag (SemanticGraph::Particle& p) + { + return p.context ().get ("s:tag"); + } + + String const& Context:: + earm (SemanticGraph::Choice& c) + { + return c.context ().get ("s:arm"); + } + + String const& Context:: + earm_tag (SemanticGraph::Choice& c) + { + return c.context ().get ("s:arm-tag"); + } + + // + // + String const& Context:: + eserializer (SemanticGraph::Member& m) + { + return m.context ().get ("s:serializer"); + } + + String const& Context:: + emember (SemanticGraph::Member& m) + { + return m.context ().get ("s:member"); + } + + String const& Context:: + emember_map (SemanticGraph::Member& m) + { + return m.context ().get ("s:member-map"); + } + + String const& Context:: + etiein (SemanticGraph::Type& t) + { + return t.context ().get ("s:tiein"); + } + + // + // + String const& Context:: + eserialize (SemanticGraph::Any& a) + { + return a.context ().get ("s:serialize"); + } + + String const& Context:: + eserialize (SemanticGraph::AnyAttribute& a) + { + return a.context ().get ("s:serialize"); + } + + // + // + String const& Context:: + eimpl (SemanticGraph::Type& t) + { + return t.context ().get ("s:impl"); + } + + // Includes + // + Void TypeForward:: + traverse (SemanticGraph::Type& t) + { + os << "class " << t.context ().get (name_key_) << ";"; + } + + Void Includes:: + traverse_ (SemanticGraph::Uses& u) + { + // Support for weak (forward) inclusion used in the file-per-type + // compilation model. + // + Boolean weak (u.context ().count ("weak")); + + if (weak && (type_ == header || type_ == impl_header)) + { + // Generate forward declarations. We don't really need them + // in the impl files. + // + if (type_ == header) + schema_.dispatch (u.schema ()); + + return; + } + + if (type_ == source && !weak) + return; + + SemanticGraph::Path path (u.path ()); + + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.native_file_string (); + } + + String inc_path; + + switch (type_) + { + case header: + case source: + { + inc_path = ctx_.hxx_expr->merge (path_str); + break; + } + case impl_header: + { + inc_path = ctx_.hxx_impl_expr->merge (path_str); + break; + } + } + + ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl + << endl; + } + } +} diff --git a/xsde/cxx/serializer/elements.hxx b/xsde/cxx/serializer/elements.hxx new file mode 100644 index 0000000..c80ab5b --- /dev/null +++ b/xsde/cxx/serializer/elements.hxx @@ -0,0 +1,443 @@ +// file : xsde/cxx/serializer/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_ELEMENTS_HXX +#define CXX_SERIALIZER_ELEMENTS_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + struct Content + { + enum Value + { + simple, + complex, + mixed + }; + }; + + // + // + class Context: public CXX::Context + { + public: + typedef BackendElements::Regex::Expression Regex; + + public: + Context (std::wostream&, + SemanticGraph::Schema&, + CLI::Options const&, + Regex const* hxx_expr, + Regex const* ixx_expr, + Regex const* hxx_impl_expr); + + protected: + Context (Context& c) + : CXX::Context (c), + options (c.options), + xml_serializer (c.xml_serializer), + serializer_base (c.serializer_base), + simple_base (c.simple_base), + complex_base (c.complex_base), + serializer_map (c.serializer_map), + validation (c.validation), + exceptions (c.exceptions), + stl (c.stl), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + hxx_impl_expr (c.hxx_impl_expr) + { + } + + Context (Context& c, std::wostream& o) + : CXX::Context (c, o), + options (c.options), + xml_serializer (c.xml_serializer), + serializer_base (c.serializer_base), + simple_base (c.simple_base), + complex_base (c.complex_base), + serializer_map (c.serializer_map), + validation (c.validation), + exceptions (c.exceptions), + stl (c.stl), + poly_code (c.poly_code), + poly_runtime (c.poly_runtime), + reset (c.reset), + mixin (c.mixin), + tiein (c.tiein), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + hxx_impl_expr (c.hxx_impl_expr) + { + } + + public: + Boolean + restriction_p (SemanticGraph::Complex& c) const + { + if (c.inherits_p () && + c.inherits ().is_a ()) + { + // Restriction of anyType is a special case. + // + return !c.inherits ().base ().is_a (); + } + + return false; + } + + // Real (e.g., non-typedef) fq-name. + // + String + real_fq_name (SemanticGraph::Nameable& n); + + public: + static Content::Value + content (SemanticGraph::Complex&); + + public: + static String const& + ret_type (SemanticGraph::Type&); + + static String const& + arg_type (SemanticGraph::Type&); + + public: + // Optional. + // + static String const& + epresent (SemanticGraph::Particle&); + + static String const& + epresent (SemanticGraph::Attribute&); + + // Sequence. + // + static String const& + enext (SemanticGraph::Particle&); + + static String const& + enext (SemanticGraph::AnyAttribute&); + + // Choice. + // + static String const& + etag (SemanticGraph::Particle&); + + static String const& + earm (SemanticGraph::Choice&); + + static String const& + earm_tag (SemanticGraph::Choice&); + + public: + static String const& + eserializer (SemanticGraph::Member&); + + static String const& + emember (SemanticGraph::Member&); + + static String const& + emember_map (SemanticGraph::Member&); + + static String const& + etiein (SemanticGraph::Type&); + + // serialize_* + // + public: + static String const& + eserialize (SemanticGraph::Any&); + + static String const& + eserialize (SemanticGraph::AnyAttribute&); + + public: + static String const& + eimpl (SemanticGraph::Type&); + + public: + CLI::Options const& options; + String& xml_serializer; + String& serializer_base; + String& simple_base; + String& complex_base; + String& serializer_map; + + Boolean validation; + Boolean exceptions; + Boolean stl; + Boolean poly_code; + Boolean poly_runtime; + Boolean reset; + Boolean mixin; + Boolean tiein; + + Regex const* hxx_expr; + Regex const* ixx_expr; + Regex const* hxx_impl_expr; + + private: + String xml_serializer_; + String serializer_base_; + String simple_base_; + String complex_base_; + String serializer_map_; + }; + + // + // + struct RequiredAttributeTest: Traversal::Attribute + { + RequiredAttributeTest (Boolean& result) + : result_ (result) + { + } + + virtual Void + traverse (Type& a) + { + if (!result_ && !a.optional ()) + result_ = true; + } + + private: + Boolean& result_; + }; + + + // + // + struct ParticleParamDecl: Traversal::Element, Context + { + ParticleParamDecl (Context& c, Boolean& first, Boolean name_arg) + : Context (c), first_ (first), name_arg_ (name_arg) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (e.type ()) << "&"; + + if (name_arg_) + os << " " << ename (e); + else + os << " /* " << comment (e.name ()) << " */"; + } + + private: + Boolean& first_; + Boolean name_arg_; + }; + + struct AttributeParamDecl: Traversal::Attribute, Context + { + AttributeParamDecl (Context& c, Boolean& first, Boolean name_arg) + : Context (c), first_ (first), name_arg_ (name_arg) + { + } + + virtual Void + traverse (Type& a) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (a.type ()) << "&"; + + if (name_arg_) + os << " " << ename (a); + else + os << " /* " << comment (a.name ()) << " */"; + } + + private: + Boolean& first_; + Boolean name_arg_; + }; + + struct SerializerParamDecl : Traversal::Complex, + Traversal::List, + Context + { + SerializerParamDecl (Context& c, Boolean name_arg) + : Context (c), + particle_ (c, first_, name_arg), + attribute_ (c, first_, name_arg), + first_ (true), + name_arg_ (name_arg) + { + inherits_ >> *this; + + contains_compositor_ >> compositor_ >> contains_particle_; + contains_particle_ >> particle_; + contains_particle_ >> compositor_; + + names_ >> attribute_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c, names_); + contains_compositor (c, contains_compositor_); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + if (!first_) + os << "," << endl; + else + first_ = false; + + os << fq_name (l.argumented ().type ()) << "&"; + + if (name_arg_) + os << " " << ename (l) << "_item"; + else + os << " /* " << comment (l.name ()) << " item */"; + } + + private: + Traversal::Inherits inherits_; + + Traversal::Compositor compositor_; + ParticleParamDecl particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + AttributeParamDecl attribute_; + Traversal::Names names_; + + Boolean first_; + Boolean name_arg_; + }; + + // + // + struct TypeForward: Traversal::Type, Context + { + TypeForward (Context& c, Char const* name_key) + : Context (c), name_key_ (name_key) + { + } + + virtual Void + traverse (SemanticGraph::Type& t); + + private: + Char const* name_key_; + }; + + struct Includes : Traversal::Imports, + Traversal::Includes + { + enum Type + { + header, + source, + impl_header + }; + + Includes (Context& c, Type t) + : ctx_ (c), + type_ (t), + namespace_ (c), + type_forward_ (c, t == header ? "s:name" : "s:impl") + { + schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + traverse_ (i); + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + traverse_ (i); + } + + private: + Void + traverse_ (SemanticGraph::Uses&); + + private: + Context& ctx_; + Type type_; + + Traversal::Schema schema_; + Traversal::Names schema_names_; + Namespace namespace_; + Traversal::Names names_; + TypeForward type_forward_; + }; + + // Find root element for the test driver. + // + struct RootElement: Traversal::Element + { + RootElement (CLI::Options const& options, + SemanticGraph::Element*& element) + : options_ (options), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (options_.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (String name = options_.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + element_ = &e; // Cover root-element-last and no option. + } + + private: + CLI::Options const& options_; + SemanticGraph::Element*& element_; + }; + } +} + +#endif // CXX_SERIALIZER_ELEMENTS_HXX diff --git a/xsde/cxx/serializer/generator.cxx b/xsde/cxx/serializer/generator.cxx new file mode 100644 index 0000000..c27ef09 --- /dev/null +++ b/xsde/cxx/serializer/generator.cxx @@ -0,0 +1,1600 @@ +// file : xsde/cxx/serializer/generator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include "../../../libxsde/xsde/cxx/version.hxx" + +using std::endl; +using std::wcerr; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef +boost::filesystem::wifstream +WideInputFileStream; + +typedef +boost::filesystem::wofstream +WideOutputFileStream; + +typedef +boost::filesystem::ifstream +NarrowInputFileStream; + +namespace CXX +{ + namespace + { + Char const copyright_gpl[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n" + "// to C++ data binding compiler for embedded systems.\n" + "//\n" + "// This program is free software; you can redistribute it and/or modify\n" + "// it under the terms of the GNU General Public License version 2 as\n" + "// published by the Free Software Foundation.\n" + "//\n" + "// This program is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU General Public License\n" + "// along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" + "//\n" + "//\n\n"; + + Char const copyright_proprietary[] = + "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n" + "// C++ data binding compiler for embedded systems, in the Proprietary\n" + "// License mode. You should have received a proprietary license from\n" + "// Code Synthesis Tools CC prior to generating this code. See the\n" + "// license text for conditions.\n" + "//\n\n"; + + Char const copyright_impl[] = + "// Not copyrighted - public domain.\n" + "//\n" + "// This sample serializer implementation was generated by CodeSynthesis XSD/e,\n" + "// an XML Schema to C++ data binding compiler for embedded systems. You may\n" + "// use it in your programs without any restrictions.\n" + "//\n\n"; + } + + namespace Serializer + { + namespace CLI + { + extern Key type_map = "type-map"; + extern Key no_stl = "no-stl"; + extern Key no_iostream = "no-iostream"; + extern Key no_exceptions = "no-exceptions"; + extern Key no_long_long = "no-long-long"; + extern Key reuse_style_mixin = "reuse-style-mixin"; + extern Key reuse_style_none = "reuse-style-none"; + extern Key generate_inline = "generate-inline"; + extern Key suppress_validation = "suppress-validation"; + extern Key generate_polymorphic = "generate-polymorphic"; + extern Key runtime_polymorphic = "runtime-polymorphic"; + extern Key suppress_reset = "suppress-reset"; + extern Key generate_empty_impl = "generate-empty-impl"; + extern Key generate_test_driver = "generate-test-driver"; + extern Key force_overwrite = "force-overwrite"; + extern Key root_element_first = "root-element-first"; + extern Key root_element_last = "root-element-last"; + extern Key root_element = "root-element"; + extern Key generate_xml_schema = "generate-xml-schema"; + extern Key extern_xml_schema = "extern-xml-schema"; + extern Key output_dir = "output-dir"; + extern Key skel_type_suffix = "skel-type-suffix"; + extern Key skel_file_suffix = "skel-file-suffix"; + extern Key impl_type_suffix = "impl-type-suffix"; + extern Key impl_file_suffix = "impl-file-suffix"; + extern Key namespace_map = "namespace-map"; + extern Key namespace_regex = "namespace-regex"; + extern Key namespace_regex_trace = "namespace-regex-trace"; + extern Key reserved_name = "reserved-name"; + extern Key include_with_brackets = "include-with-brackets"; + extern Key include_prefix = "include-prefix"; + extern Key include_regex = "include-regex"; + extern Key include_regex_trace = "include-regex-trace"; + extern Key guard_prefix = "guard-prefix"; + extern Key hxx_suffix = "hxx-suffix"; + extern Key ixx_suffix = "ixx-suffix"; + extern Key cxx_suffix = "cxx-suffix"; + extern Key hxx_regex = "hxx-regex"; + extern Key ixx_regex = "ixx-regex"; + extern Key cxx_regex = "cxx-regex"; + extern Key hxx_prologue = "hxx-prologue"; + extern Key ixx_prologue = "ixx-prologue"; + extern Key cxx_prologue = "cxx-prologue"; + extern Key prologue = "prologue"; + extern Key hxx_epilogue = "hxx-epilogue"; + extern Key ixx_epilogue = "ixx-epilogue"; + extern Key cxx_epilogue = "cxx-epilogue"; + extern Key epilogue = "epilogue"; + extern Key hxx_prologue_file = "hxx-prologue-file"; + extern Key ixx_prologue_file = "ixx-prologue-file"; + extern Key cxx_prologue_file = "cxx-prologue-file"; + extern Key prologue_file = "prologue-file"; + extern Key hxx_epilogue_file = "hxx-epilogue-file"; + extern Key ixx_epilogue_file = "ixx-epilogue-file"; + extern Key cxx_epilogue_file = "cxx-epilogue-file"; + extern Key epilogue_file = "epilogue-file"; + extern Key show_anonymous = "show-anonymous"; + extern Key show_sloc = "show-sloc"; + extern Key proprietary_license = "proprietary-license"; + } + } + + Void Serializer::Generator:: + usage () + { + std::wostream& e (wcerr); + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + e << "--type-map " << endl + << " Read XML Schema to C++ type mapping information\n" + << " from . Repeat this option to specify\n" + << " several type maps. Type maps are considered in\n" + << " order of appearance and the first match is used." + << endl; + + e << "--no-stl" << endl + << " Generate code that does not use STL." + << endl; + + e << "--no-iostream" << endl + << " Generate code that does not use the iostream\n" + << " library." + << endl; + + e << "--no-exceptions" << endl + << " Generate code that does not use C++ exceptions." + << endl; + + e << "--no-long-long" << endl + << " Generate code that does not use the long long\n" + << " and unsigned long long types." + << endl; + + e << "--reuse-style-mixin" << endl + << " Generate code that supports the mixin base\n" + << " serializer implementation reuse style." + << endl; + + e << "--reuse-style-none" << endl + << " Do not generate any support for base serializer\n" + << " implementation reuse." + << endl; + + e << "--generate-inline" << endl + << " Generate certain functions inline." + << endl; + + e << "--suppress-validation" << endl + << " Suppress the generation of validation code." + << endl; + + e << "--generate-polymorphic" << endl + << " Generate polymorphism-aware code. Specify this\n" + << " option if you use substitution groups or xsi:type." + << endl; + + e << "--runtime-polymorphic" << endl + << " Generate non-polymorphic code that uses the\n" + << " runtime library configured with polymorphism\n" + << " support." + << endl; + + e << "--suppress-reset" << endl + << " Suppress the generation of serializer reset code." + << endl; + + e << "--generate-empty-impl" << endl + << " Generate a sample serializer implementation with\n" + << " empty function bodies." + << endl; + + e << "--generate-test-driver" << endl + << " Generate a test driver for the sample serializer\n" + << " implementation." + << endl; + + e << "--force-overwrite" << endl + << " Force overwriting of the existing implementation\n" + << " and test driver files." + << endl; + + e << "--root-element-first" << endl + << " Indicate that the first global element is the\n" + << " document root." + << endl; + + e << "--root-element-last" << endl + << " Indicate that the last global element is the\n" + << " document root." + << endl; + + e << "--root-element " << endl + << " Indicate that is the document root." + << endl; + + e << "--generate-xml-schema" << endl + << " Generate a C++ header file as if the schema being\n" + << " compiled defines the XML Schema namespace." + << endl; + + e << "--extern-xml-schema " << endl + << " Generate code as if the XML Schema namespace was\n" + << " defined in and xsd:included in the schema\n" + << " being compiled." + << endl; + + e << "--output-dir " << endl + << " Write generated files to instead of the\n" + << " current directory." + << endl; + + e << "--skel-type-suffix " << endl + << " Use instead of the default '_sskel' to\n" + << " construct the names of generated serializer\n" + << " skeletons." + << endl; + + e << "--skel-file-suffix " << endl + << " Use instead of the default '-sskel' to\n" + << " construct the names of generated serializer\n" + << " skeleton files." + << endl; + + e << "--impl-type-suffix " << endl + << " Use instead of the default '_simpl' to\n" + << " construct the names of serializer implementations\n" + << " for the built-in XML Schema types and sample\n" + << " serializer implementations." + << endl; + + e << "--impl-file-suffix " << endl + << " Use instead of the default '-simpl' to\n" + << " construct the names of generated sample\n" + << " serializer implementation files." + << endl; + + e << "--namespace-map =" << endl + << " Map XML Schema namespace to C++ namespace\n" + << " . Repeat this option to specify mapping for\n" + << " more than one XML Schema namespace." + << endl; + + e << "--namespace-regex " << endl + << " Add to the list of regular expressions\n" + << " used to translate XML Schema namespace names to\n" + << " C++ namespace names." + << endl; + + e << "--namespace-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --namespace-regex option." + << endl; + + e << "--reserved-name " << endl + << " Add to the list of names that should not\n" + << " be used as identifiers. The name can optionally\n" + << " be followed by '=' and the replacement name that\n" + << " should be used instead." + << endl; + + e << "--include-with-brackets" << endl + << " Use angle brackets (<>) instead of quotes (\"\") in\n" + << " generated #include directives." + << endl; + + e << "--include-prefix " << endl + << " Add to generated #include directive\n" + << " paths." + << endl; + + e << "--include-regex " << endl + << " Add to the list of regular expressions\n" + << " used to transform #include directive paths." + << endl; + + e << "--include-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --include-regex option." + << endl; + + e << "--guard-prefix " << endl + << " Add to generated header inclusion guards." + << endl; + + e << "--hxx-suffix " << endl + << " Use instead of the default '.hxx' to\n" + << " construct the name of the header file." + << endl; + + e << "--ixx-suffix " << endl + << " Use instead of the default '.ixx' to\n" + << " construct the name of the inline file." + << endl; + + e << "--cxx-suffix " << endl + << " Use instead of the default '.cxx' to\n" + << " construct the name of the source file." + << endl; + + e << "--hxx-regex " << endl + << " Use to construct the name of the header\n" + << " file." + << endl; + + e << "--ixx-regex " << endl + << " Use to construct the name of the inline\n" + << " file." + << endl; + + e << "--cxx-regex " << endl + << " Use to construct the name of the source\n" + << " file." + << endl; + + + // Prologues. + // + e << "--hxx-prologue " << endl + << " Insert at the beginning of the header file." + << endl; + + e << "--ixx-prologue " << endl + << " Insert at the beginning of the inline file." + << endl; + + e << "--cxx-prologue " << endl + << " Insert at the beginning of the source file." + << endl; + + e << "--prologue " << endl + << " Insert at the beginning of each generated\n" + << " file for which there is no file-specific prologue." + << endl; + + + // Epilogues. + // + e << "--hxx-epilogue " << endl + << " Insert at the end of the header file." + << endl; + + e << "--ixx-epilogue " << endl + << " Insert at the end of the inline file." + << endl; + + e << "--cxx-epilogue " << endl + << " Insert at the end of the source file." + << endl; + + e << "--epilogue " << endl + << " Insert at the end of each generated file\n" + << " for which there is no file-specific epilogue." + << endl; + + + // Prologue files. + // + e << "--hxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the header file." + << endl; + + e << "--ixx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the inline file." + << endl; + + e << "--cxx-prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of the source file." + << endl; + + e << "--prologue-file " << endl + << " Insert the content of the at the beginning\n" + << " of each generated file for which there is no file-\n" + << " specific prologue file." + << endl; + + + // Epilogue files. + // + e << "--hxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the header file." + << endl; + + e << "--ixx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the inline file." + << endl; + + e << "--cxx-epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " the source file." + << endl; + + e << "--epilogue-file " << endl + << " Insert the content of the at the end of\n" + << " each generated file for which there is no file-\n" + << " specific epilogue file." + << endl; + + + // Misc. + // + e << "--show-anonymous" << endl + << " Show elements and attributes that are of anonymous\n" + << " types." + << endl; + + e << "--show-sloc" << endl + << " Show the number of generated physical source lines\n" + << " of code (SLOC)." + << endl; + + e << "--sloc-limit " << endl + << " Check that the number of generated physical source\n" + << " lines of code (SLOC) does not exceed ." + << endl; + + e << "--options-file " << endl + << " Read additional options from . Each option\n" + << " should appear on a separate line optionally\n" + << " followed by space and an argument." + << endl; + + e << "--proprietary-license" << endl + << " Indicate that the generated code is licensed under\n" + << " a proprietary license instead of the GPL." + << endl; + } + + Serializer::CLI::OptionsSpec Serializer::Generator:: + options_spec () + { + CLI::OptionsSpec spec; + + spec.option ().default_value ("-sskel"); + spec.option ().default_value ("_sskel"); + spec.option ().default_value ("-simpl"); + spec.option ().default_value ("_simpl"); + + spec.option ().default_value (".hxx"); + spec.option ().default_value (".ixx"); + spec.option ().default_value (".cxx"); + + return spec; + } + + + namespace + { + template + Void + open (S& ifs, NarrowString const& path) + { + try + { + Path fs_path (path, boost::filesystem::native); + ifs.open (fs_path, std::ios_base::in | std::ios_base::binary); + + if (!ifs.is_open ()) + { + wcerr << path.c_str () << ": error: unable to open in read mode" + << endl; + + throw Serializer::Generator::Failed (); + } + } + catch (InvalidPath const&) + { + wcerr << "error: '" << path.c_str () << "' is not a valid " + << "filesystem path" << endl; + + throw Serializer::Generator::Failed (); + } + } + + Void + append (WideOutputFileStream& os, + NarrowString const& path, + WideInputFileStream& default_is) + { + using std::ios_base; + + if (path) + { + WideInputFileStream is; + open (is, path); + os << is.rdbuf (); + } + else if (default_is.is_open ()) + { + os << default_is.rdbuf (); + default_is.seekg (0, ios_base::beg); + } + } + + Void + append (WideOutputFileStream& os, + Cult::Containers::Vector const& primary, + Cult::Containers::Vector const& def) + { + Cult::Containers::Vector const& v ( + primary.empty () ? def : primary); + + for (Containers::Vector::ConstIterator + i (v.begin ()), e (v.end ()); i != e; ++i) + { + os << i->c_str () << endl; + } + } + } + + + UnsignedLong Serializer::Generator:: + generate (Serializer::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + TypeMap::Namespaces& type_map, + Boolean gen_driver, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression Regex; + + try + { + Boolean generate_xml_schema (ops.value ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (generate_xml_schema) + { + if (NarrowString name = ops.value ()) + { + if (file_path.native_file_string () != name) + generate_xml_schema = false; + } + } + + Boolean impl (!generate_xml_schema && + ops.value ()); + + Boolean driver (gen_driver && !generate_xml_schema && + ops.value ()); + + // Evaluate the graph for possibility of generating something useful. + // + { + Validator validator; + if (!validator.validate ( + ops, schema, file_path, driver, disabled_warnings)) + throw Failed (); + } + + // Process names. + // + { + NameProcessor proc; + proc.process (ops, schema, file_path); + } + + // + // + Boolean validation (!ops.value ()); + + // Read-in type maps. + // + { + using namespace TypeMap; + typedef Containers::Vector Files; + + Files const& files (ops.value ()); + + for (Files::ConstIterator f (files.begin ()); f != files.end (); ++f ) + { + NarrowInputFileStream ifs; + open (ifs, *f); + + Lexer l (ifs, *f); + TypeMap::Parser p (l, *f); + + if (!p.parse (type_map)) + throw Failed (); + } + + // Add the built-in mappings at the end. + // + String xns; + { + Context ctx (std::wcerr, schema, ops, 0, 0, 0); + xns = ctx.xs_ns_name (); + } + + if (ops.value ()) + { + TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema"); + + String qname (L"const " + xns + L"::qname*"); + String string_seq (L"const " + xns + L"::string_sequence*"); + + xsd_std.types_push_back ("string", "const char*", "const char*"); + xsd_std.types_push_back ("normalizedString", "const char*", "const char*"); + xsd_std.types_push_back ("token", "const char*", "const char*"); + xsd_std.types_push_back ("Name", "const char*", "const char*"); + xsd_std.types_push_back ("NMTOKEN", "const char*", "const char*"); + xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq); + xsd_std.types_push_back ("NCName", "const char*", "const char*"); + + xsd_std.types_push_back ("ID", "const char*", "const char*"); + xsd_std.types_push_back ("IDREF", "const char*", "const char*"); + xsd_std.types_push_back ("IDREFS", string_seq, string_seq); + + xsd_std.types_push_back ("language", "const char*", "const char*"); + xsd_std.types_push_back ("anyURI", "const char*", "const char*"); + xsd_std.types_push_back ("QName", qname, qname); + + type_map.push_back (xsd_std); + } + else + { + TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema"); + + String qname (xns + L"::qname"); + String string_seq (L"const " + xns + L"::string_sequence*"); + + xsd_std.types_push_back ("string", "::std::string"); + xsd_std.types_push_back ("normalizedString", "::std::string"); + xsd_std.types_push_back ("token", "::std::string"); + xsd_std.types_push_back ("Name", "::std::string"); + xsd_std.types_push_back ("NMTOKEN", "::std::string"); + xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq); + xsd_std.types_push_back ("NCName", "::std::string"); + + xsd_std.types_push_back ("ID", "::std::string"); + xsd_std.types_push_back ("IDREF", "::std::string"); + xsd_std.types_push_back ("IDREFS", string_seq, string_seq); + + xsd_std.types_push_back ("language", "::std::string"); + xsd_std.types_push_back ("anyURI", "::std::string"); + xsd_std.types_push_back ("QName", qname); + + type_map.push_back (xsd_std); + } + + String buffer (L"const " + xns + L"::buffer*"); + + TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema"); + + xsd.types_push_back ("boolean", "bool", "bool"); + + xsd.types_push_back ("byte", "signed char", "signed char"); + xsd.types_push_back ("unsignedByte", "unsigned char", "unsigned char"); + + xsd.types_push_back ("short", "short", "short"); + xsd.types_push_back ("unsignedShort", "unsigned short", "unsigned short"); + + xsd.types_push_back ("int", "int", "int"); + xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int"); + + if (ops.value ()) + { + xsd.types_push_back ("long", "long", "long"); + xsd.types_push_back ("unsignedLong", "unsigned long", "unsigned long"); + } + else + { + xsd.types_push_back ("long", "long long", "long long"); + xsd.types_push_back ("unsignedLong", "unsigned long long", "unsigned long long"); + } + + xsd.types_push_back ("integer", "long", "long"); + + xsd.types_push_back ("negativeInteger", "long", "long"); + xsd.types_push_back ("nonPositiveInteger", "long", "long"); + + xsd.types_push_back ("positiveInteger", "unsigned long", "unsigned long"); + xsd.types_push_back ("nonNegativeInteger", "unsigned long", "unsigned long"); + + xsd.types_push_back ("float", "float", "float"); + xsd.types_push_back ("double", "double", "double"); + xsd.types_push_back ("decimal", "double", "double"); + + xsd.types_push_back ("base64Binary", buffer, buffer); + xsd.types_push_back ("hexBinary", buffer, buffer); + + xsd.types_push_back ("gDay", xns + L"::gday"); + xsd.types_push_back ("gMonth", xns + L"::gmonth"); + xsd.types_push_back ("gYear", xns + L"::gyear"); + xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day"); + xsd.types_push_back ("gYearMonth", xns + L"::gyear_month"); + xsd.types_push_back ("date", xns + L"::date"); + xsd.types_push_back ("time", xns + L"::time"); + xsd.types_push_back ("dateTime", xns + L"::date_time"); + xsd.types_push_back ("duration", xns + L"::duration"); + + type_map.push_back (xsd); + + // Everyhting else maps to void. + // + TypeMap::Namespace rest (".*"); + rest.types_push_back (".*", "void", "void"); + type_map.push_back (rest); + } + + // Process types. + // + { + TypeProcessor proc; + proc.process (ops, schema, type_map); + } + + // Generate code. + // + Boolean inline_ (ops.value () && + !generate_xml_schema); + + Boolean source (!generate_xml_schema); + + NarrowString name (file_path.leaf ()); + NarrowString skel_suffix (ops.value ()); + NarrowString impl_suffix (ops.value ()); + + NarrowString hxx_suffix (ops.value ()); + NarrowString ixx_suffix (ops.value ()); + NarrowString cxx_suffix (ops.value ()); + + + Regex hxx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#" + : ops.value ()); + + Regex ixx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#" + : ops.value ()); + + Regex cxx_expr ( + ops.value ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#" + : ops.value ()); + + Regex hxx_impl_expr; + Regex cxx_impl_expr; + Regex cxx_driver_expr; + + if (impl || driver) + { + hxx_impl_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"; + + cxx_impl_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"; + + cxx_driver_expr = + "#^(.+?)(\\.[^./\\\\]+)?$#$1-sdriver" + cxx_suffix + "#"; + } + + if (!hxx_expr.match (name)) + { + wcerr << "error: header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (inline_ && !ixx_expr.match (name)) + { + wcerr << "error: inline expression '" << + ixx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (source && !cxx_expr.match (name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (impl || driver) + { + if (!hxx_impl_expr.match (name)) + { + wcerr << "error: implementation header expression '" << + hxx_impl_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_impl_expr.match (name)) + { + wcerr << "error: implementation source expression '" << + cxx_impl_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (!cxx_driver_expr.match (name)) + { + wcerr << "error: driver source expression '" << + cxx_driver_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + } + + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ()); + NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ()); + + NarrowString hxx_impl_name; + NarrowString cxx_impl_name; + NarrowString cxx_driver_name; + + if (impl || driver) + { + hxx_impl_name = hxx_impl_expr.merge (name); + cxx_impl_name = cxx_impl_expr.merge (name); + cxx_driver_name = cxx_driver_expr.merge (name); + } + + Path hxx_path (hxx_name, boost::filesystem::native); + Path ixx_path (ixx_name, boost::filesystem::native); + Path cxx_path (cxx_name, boost::filesystem::native); + + Path hxx_impl_path; + Path cxx_impl_path; + Path cxx_driver_path; + + if (impl || driver) + { + hxx_impl_path = Path (hxx_impl_name, boost::filesystem::native); + cxx_impl_path = Path (cxx_impl_name, boost::filesystem::native); + cxx_driver_path = Path (cxx_driver_name, boost::filesystem::native); + } + + if (NarrowString dir = ops.value ()) + { + try + { + Path path (dir, boost::filesystem::native); + + hxx_path = path / hxx_path; + ixx_path = path / ixx_path; + cxx_path = path / cxx_path; + + if (impl || driver) + { + hxx_impl_path = path / hxx_impl_path; + cxx_impl_path = path / cxx_impl_path; + cxx_driver_path = path /cxx_driver_path; + } + + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + // Open the impl files first so that if open fails, the skel files + // are not deleted. + // + WideOutputFileStream hxx_impl; + WideOutputFileStream cxx_impl; + WideOutputFileStream cxx_driver; + + if (impl) + { + if (!ops.value ()) + { + WideInputFileStream tmp (hxx_impl_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << hxx_impl_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + hxx_impl.open (hxx_impl_path, ios_base::out); + + if (!hxx_impl.is_open ()) + { + wcerr << hxx_impl_path << ": error: unable to open in write mode" + << endl; + throw Failed (); + } + + unlinks.add (hxx_impl_path); + file_list.push_back (hxx_impl_path.native_file_string ()); + + if (!ops.value ()) + { + WideInputFileStream tmp (cxx_impl_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << cxx_impl_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + cxx_impl.open (cxx_impl_path, ios_base::out); + + if (!cxx_impl.is_open ()) + { + wcerr << cxx_impl_path << ": error: unable to open in write mode" + << endl; + throw Failed (); + } + + unlinks.add (cxx_impl_path); + file_list.push_back (cxx_impl_path.native_file_string ()); + } + + if (driver) + { + if (!ops.value ()) + { + WideInputFileStream tmp (cxx_driver_path, ios_base::in); + + if (tmp.is_open ()) + { + wcerr << cxx_driver_path << ": error: cowardly refusing to " << + "overwrite an existing file" << endl; + throw Failed (); + } + + tmp.close (); + } + + cxx_driver.open (cxx_driver_path, ios_base::out); + + if (!cxx_driver.is_open ()) + { + wcerr << cxx_driver_path << ": error: unable to open in write " << + "mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_driver_path); + file_list.push_back (cxx_driver_path.native_file_string ()); + } + + // Open the skel files. + // + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream ixx; + WideOutputFileStream cxx; + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + file_list.push_back (hxx_path.native_file_string ()); + + if (inline_) + { + ixx.open (ixx_path, ios_base::out); + + if (!ixx.is_open ()) + { + wcerr << ixx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (ixx_path); + file_list.push_back (ixx_path.native_file_string ()); + } + + if (source) + { + cxx.open (cxx_path, ios_base::out); + + if (!cxx.is_open ()) + { + wcerr << cxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (cxx_path); + file_list.push_back (cxx_path.native_file_string ()); + } + + // Print copyright and license. + // + Char const* copyright ( + ops.value () + ? copyright_proprietary + : copyright_gpl); + + hxx << copyright; + + if (inline_) + ixx << copyright; + + if (source) + cxx << copyright; + + if (impl) + { + hxx_impl << copyright_impl; + cxx_impl << copyright_impl; + } + + if (driver) + cxx_driver << copyright_impl; + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name (ops.value ()); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name (ops.value ()); + + if (name) + open (epilogue, name); + } + + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value ()); + + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + + NarrowString guard_prefix (ops.value ()); + + if (!guard_prefix) + guard_prefix = file_path.branch_path ().native_directory_string (); + + if (guard_prefix) + guard_prefix += '_'; + + + // HXX + // + { + Context ctx (hxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip hxx_sloc (hxx); + + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append ( + hxx, ops.value (), ops.value ()); + append (hxx, ops.value (), prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Version check. + // + hxx << "#include " << endl + << endl + << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl + << "#error XSD/e runtime version mismatch" << endl + << "#endif" << endl + << endl; + + // Runtime/generated code compatibility checks. + // + + hxx << "#include " << endl + << endl; + + if (ops.value ()) + { + hxx << "#ifdef XSDE_STL" << endl + << "#error the XSD/e runtime uses STL while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-stl)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_STL" << endl + << "#error the generated code uses STL while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-stl)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_IOSTREAM" << endl + << "#error the XSD/e runtime uses iostream while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-iostream)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_IOSTREAM" << endl + << "#error the generated code uses iostream while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-iostream)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_EXCEPTIONS" << endl + << "#error the XSD/e runtime uses exceptions while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_EXCEPTIONS" << endl + << "#error the generated code uses exceptions while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-exceptions)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_LONGLONG" << endl + << "#error the XSD/e runtime uses long long while the " << + "generated code does not (reconfigure the runtime or " << + "remove --no-long-long)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_LONGLONG" << endl + << "#error the generated code uses long long while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --no-long-long)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifdef XSDE_SERIALIZER_VALIDATION" << endl + << "#error the XSD/e runtime uses validation while the " << + "generated code does not (reconfigure the runtime or " << + "remove --suppress-validation)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_SERIALIZER_VALIDATION" << endl + << "#error the generated code uses validation while the " << + "XSD/e runtime does not (reconfigure the runtime or " << + "add --suppress-validation)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value () || + ops.value ()) + { + hxx << "#ifndef XSDE_POLYMORPHIC" << endl + << "#error the generated code expects XSD/e runtime with " << + "polymorphism support (reconfigure the runtime or remove " << + "--generate-polymorphic/--runtime-polymorphic)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifdef XSDE_POLYMORPHIC" << endl + << "#error the generated code expects XSD/e runtime " << + "without polymorphism support (reconfigure the runtime or " << + "add --generate-polymorphic/--runtime-polymorphic)" << endl + << "#endif" << endl + << endl; + } + + if (ops.value ()) + { + hxx << "#ifndef XSDE_REUSE_STYLE_MIXIN" << endl + << "#error the generated code uses the mixin reuse style " << + "while the XSD/e runtime does not (reconfigure the runtime " << + "or remove --reuse-style-mixin)" << endl + << "#endif" << endl + << endl; + } + else if (ops.value ()) + { + hxx << "#ifndef XSDE_REUSE_STYLE_NONE" << endl + << "#error the generated code does not provide support " << + "for serializer reuse while the XSD/e runtime does (" << + "reconfigure the runtime or remove --reuse-style-none)" << endl + << "#endif" << endl + << endl; + } + else + { + hxx << "#ifndef XSDE_REUSE_STYLE_TIEIN" << endl + << "#error the generated code uses the tiein reuse style " << + "while the XSD/e runtime does not (reconfigure the runtime " << + "or add --reuse-style-mixin or --reuse-style-none)" << endl + << "#endif" << endl + << endl; + } + + // + // + + hxx << "#include " << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip hxx_clip (hxx); + + // Generate. + // + if (!generate_xml_schema) + generate_serializer_forward (ctx); + + generate_serializer_header (ctx, generate_xml_schema); + + + if (inline_) + hxx << "#include " << ctx.process_include_path (ixx_name) << endl + << endl; + + hxx << "#include " << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, ops.value (), epilogue); + append ( + hxx, ops.value (), ops.value ()); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + + // IXX + // + if (inline_) + { + Context ctx (ixx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip ixx_sloc (ixx); + + + // Copy prologue. + // + ixx << "// Begin prologue." << endl + << "//" << endl; + + append ( + ixx, ops.value (), ops.value ()); + append (ixx, ops.value (), prologue); + + ixx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip ixx_clip (ixx); + + + // Generate. + // + generate_serializer_inline (ctx); + } + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, ops.value (), epilogue); + append ( + ixx, ops.value (), ops.value ()); + + ixx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << ixx_path << ": " + << ixx_sloc.buffer ().count () << endl; + + sloc += ixx_sloc.buffer ().count (); + } + } + + + // CXX + // + if (source) + { + Context ctx (cxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + Indentation::Clip cxx_sloc (cxx); + + // Copy prologue. + // + cxx << "// Begin prologue." << endl + << "//" << endl; + + append ( + cxx, ops.value (), ops.value ()); + append (cxx, ops.value (), prologue); + + cxx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip cxx_clip (cxx); + + cxx << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + if (!inline_) + generate_serializer_inline (ctx); + + generate_serializer_source (ctx); + + if (validation) + { + generate_element_validation_source (ctx); + generate_attribute_validation_source (ctx); + } + } + + // Copy epilogue. + // + cxx << "// Begin epilogue." << endl + << "//" << endl; + + append (cxx, ops.value (), epilogue); + append ( + cxx, ops.value (), ops.value ()); + + cxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_path << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + + // HXX impl + // + if (impl) + { + Context ctx (hxx_impl, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr); + + String guard (guard_expr.merge (guard_prefix + hxx_impl_name)); + guard = ctx.escape (guard); // Make it a C++ id. + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx_impl << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip clip (hxx_impl); + + hxx_impl << "#include " << ctx.process_include_path (hxx_name) + << endl << endl; + + generate_impl_header (ctx); + } + + hxx_impl << "#endif // " << guard << endl; + } + + // CXX impl + // + if (impl) + { + Context ctx (cxx_impl, schema, ops, + &hxx_expr, &ixx_expr, &hxx_impl_expr); + + // Set auto-indentation. + // + Indentation::Clip clip (cxx_impl); + + cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name) + << endl << endl; + + generate_impl_source (ctx); + } + + // CXX driver + // + if (driver) + { + Context ctx (cxx_driver, schema, ops, + &hxx_expr, &ixx_expr, &hxx_impl_expr); + + // Set auto-indentation. + // + Indentation::Clip clip (cxx_driver); + + cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name) + << endl << endl; + + generate_driver_source (ctx); + } + + return sloc; + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } +} diff --git a/xsde/cxx/serializer/generator.hxx b/xsde/cxx/serializer/generator.hxx new file mode 100644 index 0000000..a5b8558 --- /dev/null +++ b/xsde/cxx/serializer/generator.hxx @@ -0,0 +1,56 @@ +// file : xsde/cxx/serializer/generator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_GENERATOR_HXX +#define CXX_SERIALIZER_GENERATOR_HXX + +#include + +#include + +#include +#include + +#include // Path +#include + +#include +#include +#include + +namespace CXX +{ + namespace Serializer + { + using namespace Cult::Types; + + class Generator + { + public: + static Void + usage (); + + static CLI::OptionsSpec + options_spec (); + + struct Failed {}; + + static UnsignedLong + generate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + TypeMap::Namespaces& type_map, + Boolean gen_driver, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + private: + Generator (); + }; + } +} + +#endif // CXX_SERIALIZER_GENERATOR_HXX diff --git a/xsde/cxx/serializer/impl-header.cxx b/xsde/cxx/serializer/impl-header.cxx new file mode 100644 index 0000000..d98b6af --- /dev/null +++ b/xsde/cxx/serializer/impl-header.cxx @@ -0,0 +1,488 @@ +// file : xsde/cxx/serializer/impl-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (eimpl (e)); + String const& arg (arg_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + + os << "class " << name << ": " << "public " << + (mixin ? "virtual " : "") << ename (e); + + if (mixin) + os << "," << endl + << " public " << fq_name (base, "s:impl"); + + os << "{" + << "public:" << endl; + + if (tiein) + os << name << " ();" + << endl; + + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ");"; + + os << endl + << "virtual void" << endl + << "post ();"; + + if (tiein) + os << endl + << "private:" << endl + << fq_name (base, "s:impl") << " base_impl_;"; + + os << "};"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (eimpl (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String const& arg (arg_type (l)); + String const& ret (ret_type (t)); + + String const& skel (ename (l)); + String item (unclash (skel, "item")); + String item_next (unclash (skel, "item_next")); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (l) + << "{" + << "public:" << endl + << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ");"; + + os << endl + << "virtual bool" << endl + << item_next << " ();" + << endl + << "virtual " << ret << endl + << item << " ();" + << endl + << "virtual void" << endl + << "post ();" + << "};"; + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (eimpl (u)); + String const& arg (arg_type (u)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (u) + << "{" + << "public:" << endl + << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ");"; + + os << endl + << "virtual void" << endl + << "_serialize_content ();" + << endl + << "virtual void" << endl + << "post ();" + << "};"; + } + }; + + + // + // + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (c) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (c) << " ();" + << endl; + } + + os << "virtual " << earm_tag (c) << endl + << earm (c) << " ();" + << endl; + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (s) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (s) << " ();" + << endl; + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallback: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (e) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (e) << " ();" + << endl; + } + + String const& ret (ret_type (e.type ())); + + os << "virtual " << ret << endl + << ename (e) << " ();" + << endl; + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (a) << " ();" + << endl; + } + + if (stl) + { + os << "virtual void" << endl + << ename (a) << " (::std::string& ns, ::std::string& name);" + << endl; + } + else + { + os << "virtual void" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free);" + << endl; + } + + os << "virtual void" << endl + << eserialize (a) << " ();" + << endl; + + } + }; + + struct AttributeCallback: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (a.optional ()) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + + String const& ret (ret_type (a.type ())); + + os << "virtual " << ret << endl + << ename (a) << " ();" + << endl; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << "virtual bool" << endl + << enext (a) << " ();" + << endl; + + if (stl) + { + os << "virtual void" << endl + << ename (a) << " (::std::string& ns, ::std::string& name);" + << endl; + } + else + { + os << "virtual void" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free);" + << endl; + } + + os << "virtual void" << endl + << eserialize (a) << " ();" + << endl; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + // In case of an inheritance-by-restriction, we don't need to + // generate serializer callbacks, etc. since they are the same + // as in the base. We only need the serialization/validation code. + // + Boolean restriction (restriction_p (c)); + + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + Boolean haa (has (c)); + + String const& name (eimpl (c)); + String const& arg (arg_type (c)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << ename (c); + + if (mixin && hb) + os << "," << endl + << " public " << fq_name (c.inherits ().base (), "s:impl"); + + os << "{" + << "public:" << endl; + + // c-tor + // + if (tiein && hb) + os << name << " ();" + << endl; + + // pre + // + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ");"; + + os << endl; + + + // Member callbacks. + // + if (!restriction && (ha || he || hae || haa)) + { + if (ha || haa) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + + if (he || hae) + { + os << "// Elements." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_callback_); + } + } + + // post + // + os << "virtual void" << endl + << "post ();"; + + if (tiein && hb) + os << endl + << "private:" << endl + << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;"; + + os << "};"; + } + + private: + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_impl_header (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::impl_header); + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/impl-header.hxx b/xsde/cxx/serializer/impl-header.hxx new file mode 100644 index 0000000..a483eaa --- /dev/null +++ b/xsde/cxx/serializer/impl-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/impl-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_IMPL_HEADER_HXX +#define CXX_SERIALIZER_IMPL_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_impl_header (Context&); + } +} + +#endif // CXX_SERIALIZER_IMPL_HEADER_HXX diff --git a/xsde/cxx/serializer/impl-source.cxx b/xsde/cxx/serializer/impl-source.cxx new file mode 100644 index 0000000..cc31ced --- /dev/null +++ b/xsde/cxx/serializer/impl-source.cxx @@ -0,0 +1,664 @@ +// file : xsde/cxx/serializer/impl-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (eimpl (e)); + String const& arg (arg_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein) + os << name << "::" << endl + << name << " ()" << endl + << ": " << ename (e) << " (&base_impl_)" + << "{" + << "}"; + + // pre + // + os << "void " << name << "::" << endl; + + if (arg == L"void") + os << "pre ()"; + else + os << "pre (" << arg << " v)"; + + os << "{"; + + if (arg == arg_type (base)) + { + if (tiein) + { + os << "base_impl_.pre (" << + (arg != L"void" ? "v" : "") << ");"; + } + else if (mixin) + { + os << eimpl (base) << "::pre (" << + (arg != L"void" ? "v" : "") << ");"; + } + } + else + { + if (tiein) + { + os << "// TODO: call base_impl_.pre ()." << endl + << "//" << endl; + } + else if (mixin) + { + os << "// TODO: call " << eimpl (base) << "::pre ()." << endl + << "//" << endl; + } + } + + os << "}"; + + // post + // + os << "void " << name << "::" << endl + << "post ()" + << "{" + << "}"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (eimpl (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String const& arg (arg_type (l)); + String const& ret (ret_type (t)); + + String const& skel (ename (l)); + String item (unclash (skel, "item")); + String item_next (unclash (skel, "item_next")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + os << "void " << name << "::" << endl; + + if (arg == L"void") + os << "pre ()" + << "{" + << "}"; + else + os << "pre (" << arg << " v)" + << "{" + << "// TODO" << endl + << "//" << endl + << "}"; + + // item + // + os << "bool " << name << "::" << endl + << item_next << " ()" + << "{" + << "// TODO: return true if there is another item to" << endl + << "// serialize." << endl + << "//" << endl + << "}"; + + + os << ret << " " << name << "::" << endl + << item << " ()" + << "{" + << "// TODO: return the next item." << endl + << "//" << endl + << "}"; + + // post + // + os << "void " << name << "::" << endl + << "post ()" + << "{" + << "}"; + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (eimpl (u)); + String const& arg (arg_type (u)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + os << "void " << name << "::" << endl; + + if (arg == L"void") + os << "pre ()" + << "{" + << "}"; + else + os << "pre (" << arg << " v)" + << "{" + << "// TODO" << endl + << "//" << endl + << "}"; + + // _serialize_content + // + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{" + << "// TODO: call the _characters() function to serialize" << endl + << "// text content." << endl + << "//" << endl + << "}"; + + // post + // + os << "void " << name << "::" << endl + << "post ()" + << "{" + << "}"; + } + }; + + // + // + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + String const& s (eimpl (scope (a))); + + os << "bool " << s << "::" << endl + << epresent (a) << " ()" + << "{" + << "// TODO: return true if the content corresponding" << endl + << "// to the all compositor is present." << endl + << "//" << endl + << "}"; + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + SemanticGraph::Complex& t (scope (c)); + String const& s (eimpl (t)); + + if (min == 0 && max == 1) + { + os << "bool " << s << "::" << endl + << epresent (c) << " ()" + << "{" + << "// TODO: return true if the content corresponding" << endl + << "// to the choice compositor is present." << endl + << "//" << endl + << "}"; + } + else if (max != 1) + { + os << "bool " << s << "::" << endl + << enext (c) << " ()" + << "{" + << "// TODO: return true if there is another choice" << endl + << "// item to serialize." << endl + << "//" << endl + << "}"; + } + + os << ename (t) << "::" << earm_tag (c) << " " << s << "::" << endl + << earm (c) << " ()" + << "{" + << "// TODO: return the choice arm that is being" << endl + << "// serialized." << endl + << "//" << endl + << "}"; + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + String const& sc (eimpl (scope (s))); + + if (min == 0 && max == 1) + { + os << "bool " << sc << "::" << endl + << epresent (s) << " ()" + << "{" + << "// TODO: return true if the content corresponding" << endl + << "// to the sequence compositor is present." << endl + << "//" << endl + << "}"; + + } + else if (max != 1) + { + os << "bool " << sc << "::" << endl + << enext (s) << " ()" + << "{" + << "// TODO: return true if there is another sequence" << endl + << "// item to serialize." << endl + << "//" << endl + << "}"; + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Complex& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + }; + + struct ParticleCallback: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& s ( + eimpl (dynamic_cast (e.scope ()))); + + if (min == 0 && max == 1) + { + os << "bool " << s << "::" << endl + << epresent (e) << " ()" + << "{" + << "// TODO: return true if the element is present." << endl + << "//" << endl + << "}"; + + } + else if (max != 1) + { + os << "bool " << s << "::" << endl + << enext (e) << " ()" + << "{" + << "// TODO: return true if there is another element" << endl + << "// to serialize." << endl + << "//" << endl + << "}"; + } + + String const& ret (ret_type (e.type ())); + + os << ret << " " << s << "::" << endl + << ename (e) << " ()" + << "{" + << "// TODO: return the element data." << endl + << "//" << endl + << "}"; + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + String const& s ( + eimpl (dynamic_cast (a.scope ()))); + + if (min == 0 && max == 1) + { + os << "bool " << s << "::" << endl + << epresent (a) << " ()" + << "{" + << "// TODO: return true if the wildcard content is" << endl + << "// present." << endl + << "//" << endl + << "}"; + } + else if (max != 1) + { + os << "bool " << s << "::" << endl + << enext (a) << " ()" + << "{" + << "// TODO: return true if there is another wildcard" << endl + << "// element to serialize." << endl + << "//" << endl + << "}"; + } + + if (stl) + { + os << "void " << s << "::" << endl + << ename (a) << " (::std::string& ns, ::std::string& name)"; + } + else + { + os << "void " << s << "::" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free)"; + } + + os << "{" + << "// TODO: return the name and namespace of the element" << endl + << "// corresponding to the wildcard." << endl + << "//" << endl + << "}"; + + os << "void " << s << "::" << endl + << eserialize (a) << " ()" + << "{" + << "// TODO: use the _start_element(), _end_element()," << endl + << "// _attribute(), and _characters() functions to" << endl + << "// serialize the wildcard content." << endl + << "//" << endl + << "}"; + + } + }; + + struct AttributeCallback: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& s ( + eimpl (dynamic_cast (a.scope ()))); + + if (a.optional ()) + { + os << "bool " << s << "::" << endl + << epresent (a) << " ()" + << "{" + << "// TODO: return true if the attribute is present." << endl + << "//" << endl + << "}"; + } + + String const& ret (ret_type (a.type ())); + + os << ret << " " << s << "::" << endl + << ename (a) << " ()" + << "{" + << "// TODO: return the attribute data." << endl + << "//" << endl + << "}"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& s ( + eimpl (dynamic_cast (a.scope ()))); + + os << "bool " << s << "::" << endl + << enext (a) << " ()" + << "{" + << "// TODO: return true if there is another wildcard" << endl + << "// attribute to serialize." << endl + << "//" << endl + << "}"; + + if (stl) + { + os << "void " << s << "::" << endl + << ename (a) << " (::std::string& ns, ::std::string& name)"; + } + else + { + os << "void " << s << "::" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free)"; + } + + os << "{" + << "// TODO: return the name and namespace of the attribute" << endl + << "// corresponding to the wildcard." << endl + << "//" << endl + << "}"; + + os << "void " << s << "::" << endl + << eserialize (a) << " ()" + << "{" + << "// TODO: use the _characters() function to serialize" << endl + << "// the wildcard content." << endl + << "//" << endl + << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + + String const& name (eimpl (c)); + String const& arg (arg_type (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor + // + if (tiein && hb) + os << name << "::" << endl + << name << " ()" << endl + << ": " << ename (c) << " (&base_impl_)" + << "{" + << "}"; + + // pre + // + os << "void " << name << "::" << endl; + + if (arg == L"void") + os << "pre ()"; + else + os << "pre (" << arg << " v)"; + + os << "{"; + + if (hb) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + if (arg == arg_type (base)) + { + if (tiein) + { + os << "base_impl_.pre (" << + (arg != L"void" ? "v" : "") << ");"; + } + else if (mixin) + { + os << eimpl (base) << "::pre (" << + (arg != L"void" ? "v" : "") << ");"; + } + } + else + { + if (tiein) + { + os << "// TODO: call " << eimpl (base) << "::pre ()." << endl + << "//" << endl; + } + else if (mixin) + { + os << "// TODO: call base_impl_.pre ()." << endl + << "//" << endl; + } + } + + } + else if (arg != L"void") + { + os << "// TODO" << endl + << "//" << endl; + } + + os << "}"; + + // Member callbacks. + // + if (!restriction_p (c)) + { + names (c, names_attribute_callback_); + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + os << "void " << name << "::" << endl + << "post ()" + << "{" + << "}"; + } + + private: + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + } + + Void + generate_impl_source (Context& ctx) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/impl-source.hxx b/xsde/cxx/serializer/impl-source.hxx new file mode 100644 index 0000000..f6303ba --- /dev/null +++ b/xsde/cxx/serializer/impl-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/impl-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_IMPL_SOURCE_HXX +#define CXX_SERIALIZER_IMPL_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_impl_source (Context&); + } +} + +#endif // CXX_SERIALIZER_IMPL_SOURCE_HXX diff --git a/xsde/cxx/serializer/name-processor.cxx b/xsde/cxx/serializer/name-processor.cxx new file mode 100644 index 0000000..d68b823 --- /dev/null +++ b/xsde/cxx/serializer/name-processor.cxx @@ -0,0 +1,1409 @@ +// file : xsde/cxx/serializer/name-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + // + // + typedef Cult::Containers::Set NameSet; + + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, + SemanticGraph::Schema& root, + SemanticGraph::Path const& file) + : CXX::Context (std::wcerr, + root, + "s:name", + "char", + ops.value (), + ops.value (), + "", // export symbol + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + schema_path_ (file), + skel_suffix_ (ops.value ()), + impl_suffix_ (ops.value ()), + schema (root), + schema_path (schema_path_), + impl (ops.value () || + ops.value ()), + tiein (!ops.value () && + !ops.value ()), + skel_suffix (skel_suffix_), + impl_suffix (impl_suffix_), + global_type_names (global_type_names_), + validation (!ops.value ()), + polymorphic (ops.value ()) + { + } + + protected: + Context (Context& c) + : CXX::Context (c), + schema (c.schema), + schema_path (c.schema_path), + impl (c.impl), + tiein (c.tiein), + skel_suffix (c.skel_suffix), + impl_suffix (c.impl_suffix), + global_type_names (c.global_type_names), + validation (c.validation), + polymorphic (c.polymorphic) + { + } + + public: + String + find_name (String const& n, String const& suffix, NameSet& set) + { + String name (escape (n + suffix)); + + for (UnsignedLong i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = escape (n + os.str () + suffix); + } + + set.insert (name); + return name; + } + + String + find_name (String const& n, NameSet& set) + { + return find_name (n, L"", set); + } + + private: + SemanticGraph::Path const schema_path_; + String const skel_suffix_; + String const impl_suffix_; + + Cult::Containers::Map global_type_names_; + + public: + SemanticGraph::Schema& schema; + SemanticGraph::Path const& schema_path; + Boolean const impl; + Boolean const tiein; + String const& skel_suffix; + String const& impl_suffix; + + Cult::Containers::Map& global_type_names; + + Boolean validation; + Boolean polymorphic; + }; + + // Primary names. + // + struct PrimaryParticle: Traversal::Element, + Traversal::Any, + Context + { + PrimaryParticle (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Element; + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + ec.set ("s:name", find_name (e.name (), set_)); + else + { + Element* prot = ec.get ( + "xsd-frontend-restriction-correspondence"); + + ec.set ("s:name", prot->context ().get ("s:name")); + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Any; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + ac.set ("s:name", find_name (L"any", set_)); + } + else + { + Any* prot = ac.get ( + "xsd-frontend-restriction-correspondence"); + + ac.set ("s:name", prot->context ().get ("s:name")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct PrimaryAttribute: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + PrimaryAttribute (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Attribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + ac.set ("s:name", find_name (a.name (), set_)); + } + else + { + Attribute* prot = ac.get ( + "xsd-frontend-restriction-correspondence"); + + ac.set ("s:name", prot->context ().get ("s:name")); + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + using SemanticGraph::AnyAttribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + ac.set ("s:name", find_name (L"any_attribute", set_)); + } + else + { + AnyAttribute* prot = ac.get ( + "xsd-frontend-restriction-correspondence"); + + ac.set ("s:name", prot->context ().get ("s:name")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + // Secondary names. + // + + struct ParticleTag: Traversal::Element, + Traversal::Any, + Traversal::Choice, + Traversal::Sequence, + Context + { + ParticleTag (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + using SemanticGraph::Element; + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + { + String const base (ec.get ("s:name")); + ec.set ("s:tag", find_name (base, L"_tag", set_)); + } + else + { + Element* prot = ec.get ( + "xsd-frontend-restriction-correspondence"); + + ec.set ("s:tag", prot->context ().get ("s:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Any; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + String const& base (ac.get ("s:name")); + ac.set ("s:tag", find_name (base, L"_tag", set_)); + } + else + { + Any* prot = ac.get ( + "xsd-frontend-restriction-correspondence"); + + ac.set ("s:tag", prot->context ().get ("s:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + using SemanticGraph::Compositor; + + SemanticGraph::Context& cc (c.context ()); + + if (!restriction_) + { + cc.set ("s:tag", find_name (L"choice", L"_tag", set_)); + } + else + { + Compositor* prot = cc.get ( + "xsd-frontend-restriction-correspondence"); + + cc.set ("s:tag", prot->context ().get ("s:tag")); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + using SemanticGraph::Compositor; + + SemanticGraph::Context& sc (s.context ()); + + if (!restriction_) + { + sc.set ("s:tag", find_name (L"sequence", L"_tag", set_)); + } + else + { + Compositor* prot = sc.get ( + "xsd-frontend-restriction-correspondence"); + + sc.set ("s:tag", prot->context ().get ("s:tag")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct SecondaryCompositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + SecondaryCompositor (Context& c, NameSet& set, Boolean restriction) + : Context (c), + set_ (set), + restriction_ (restriction), + particle_tag_ (c, set, restriction) + { + contain_particle_tag_ >> particle_tag_; + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1} + // and it cannot be used in restriction. + // + if (a.contained_compositor ().min () == 0) + { + a.context ().set ( + "s:present", find_name (L"all", L"_present", set_)); + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () == c.contains_end ()) + return; + + SemanticGraph::Context& cc (c.context ()); + + if (!restriction_) + { + if (c.max () != 1) + cc.set ("s:next", find_name (L"choice", L"_next", set_)); + else if (c.min () == 0) + cc.set ("s:present", find_name (L"choice", L"_present", set_)); + + // Tags. + // + cc.set ("s:arm-tag", find_name (L"choice", L"_arm_tag", set_)); + Traversal::Choice::contains (c, contain_particle_tag_); + cc.set ("s:arm", find_name (L"choice", L"_arm", set_)); + } + else + { + SemanticGraph::Compositor& b ( + *cc.get ( + "xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + + if (b.max () != 1) + { + cc.set ("s:next", bc.get ("s:next")); + + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (c.min () == 0) + cc.set ("s:present", + find_name (L"choice", L"_present", set_)); + } + else if (b.min () == 0) + cc.set ("s:present", bc.get ("s:present")); + + // Tags. + // + cc.set ("s:arm-tag", bc.get ("s:arm-tag")); + Traversal::Choice::contains (c, contain_particle_tag_); + cc.set ("s:arm", bc.get ("s:arm")); + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + SemanticGraph::Context& sc (s.context ()); + + if (!restriction_) + { + if (s.max () != 1) + sc.set ("s:next", find_name (L"sequence", L"_next", set_)); + else if (s.min () == 0) + sc.set ("s:present", find_name (L"sequence", L"_present", set_)); + } + else + { + // Root compositor that models inheritance by extension + // may not have an association. + // + if (sc.count ("xsd-frontend-restriction-correspondence")) + { + SemanticGraph::Compositor& b ( + *sc.get ( + "xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + + if (b.max () != 1) + { + sc.set ("s:next", bc.get ("s:next")); + + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (s.min () == 0) + sc.set ("s:present", + find_name (L"sequence", L"_present", set_)); + } + else if (b.min () == 0) + sc.set ("s:present", bc.get ("s:present")); + } + } + + Traversal::Sequence::traverse (s); + } + + private: + NameSet& set_; + Boolean restriction_; + + ParticleTag particle_tag_; + Traversal::ContainsParticle contain_particle_tag_; + }; + + struct SecondaryParticle: Traversal::Element, + Traversal::Any, + Context + { + SecondaryParticle (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + Boolean poly ( + polymorphic && !e.type ().context ().count ("anonymous")); + + SemanticGraph::Context& ec (e.context ()); + + if (!restriction_) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& base (ec.get ("s:name")); + + if (min == 0 && max == 1) + ec.set ("s:present", find_name (base + L"_present", set_)); + else if (max != 1) + ec.set ("s:next", find_name (base + L"_next", set_)); + + ec.set ("s:serializer", find_name (base + L"_serializer", set_)); + ec.set ("s:member", find_name (base + L"_serializer_", set_)); + + if (poly) + ec.set ("s:member-map", + find_name (base + L"_serializer_map_", set_)); + } + else + { + SemanticGraph::Element& b ( + *ec.get ( + "xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + UnsignedLong min (b.min ()), max (b.max ()); + + if (min == 0 && max == 1) + ec.set ("s:present", bc.get ("s:present")); + else if (max != 1) + { + ec.set ("s:next", bc.get ("s:next")); + + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (e.min () == 0) + { + String const& base (bc.get ("s:name")); + ec.set ("s:present", find_name (base + L"_present", set_)); + } + } + + ec.set ("s:serializer", bc.get ("s:serializer")); + ec.set ("s:member", bc.get ("s:member")); + + if (poly) + ec.set ("s:member-map", bc.get ("s:member-map")); + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Any; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + UnsignedLong min (a.min ()), max (a.max ()); + String const& base (ac.get ("s:name")); + + if (min == 0 && max == 1) + { + ac.set ("s:present", find_name (base + L"_present", set_)); + } + else if (max != 1) + { + ac.set ("s:next", find_name (base + L"_next", set_)); + } + + ac.set ("s:serialize", find_name (L"serialize_" + base, set_)); + } + else + { + Any& b ( + *ac.get ("xsd-frontend-restriction-correspondence")); + + SemanticGraph::Context& bc (b.context ()); + UnsignedLong min (b.min ()), max (b.max ()); + + if (min == 0 && max == 1) + { + ac.set ("s:present", bc.get ("s:present")); + } + else if (max != 1) + { + ac.set ("s:next", bc.get ("s:next")); + + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (a.min () == 0) + { + String const& base (bc.get ("s:name")); + ac.set ("s:present", find_name (base + L"_present", set_)); + } + } + + ac.set ("s:serialize", bc.get ("s:serialize")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + struct SecondaryAttribute: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + SecondaryAttribute (Context& c, NameSet& set, Boolean restriction) + : Context (c), set_ (set), restriction_ (restriction) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + using SemanticGraph::Attribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + String const& base (ac.get ("s:name")); + + if (a.optional ()) + ac.set ("s:present", find_name (base + L"_present", set_)); + + ac.set ("s:serializer", find_name (base + L"_serializer", set_)); + ac.set ("s:member", find_name (base + L"_serializer_", set_)); + } + else + { + Attribute& b ( + *ac.get ("xsd-frontend-restriction-correspondence")); + SemanticGraph::Context& bc (b.context ()); + + if (a.optional ()) + ac.set ("s:present", bc.get ("s:present")); + + ac.set ("s:serializer", bc.get ("s:serializer")); + ac.set ("s:member", bc.get ("s:member")); + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + using SemanticGraph::AnyAttribute; + + SemanticGraph::Context& ac (a.context ()); + + if (!restriction_) + { + String const& base (ac.get ("s:name")); + + ac.set ("s:next", find_name (base + L"_next", set_)); + ac.set ("s:serialize", find_name (L"serialize_" + base, set_)); + } + else + { + AnyAttribute& b ( + *ac.get ( + "xsd-frontend-restriction-correspondence")); + SemanticGraph::Context& bc (b.context ()); + + ac.set ("s:next", bc.get ("s:next")); + ac.set ("s:serialize", bc.get ("s:serialize")); + } + } + + private: + NameSet& set_; + Boolean restriction_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // Use processed name. + // + String const& name (cc.get ("s:name")); + + // We leave this set around to allow other mappings to use + // this information. + // + cc.set ("cxx-serializer-name-processor-member-set", NameSet ()); + NameSet& member_set ( + cc.get ("cxx-serializer-name-processor-member-set")); + + member_set.insert (name); + + // Add our base's members to the initial list unless we are + // inheriting by restriction in which case we need to have + // the same names as our base. + // + Boolean restriction (false); + + if (c.inherits_p ()) + { + // @@ What if this types name is the same as one of base's + // members? + // + SemanticGraph::Type& base (c.inherits ().base ()); + + if (base.is_a ()) + { + if (!base.context ().count ( + "cxx-serializer-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_set ( + base.context ().get ( + "cxx-serializer-name-processor-member-set")); + + member_set.insert (base_set.begin (), base_set.end ()); + + // Inheritance by restriction from anyType is a special case. + // + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + } + } + + // First assign the "primary" names. + // + { + if (c.contains_compositor_p ()) + { + PrimaryParticle particle (*this, member_set, restriction); + Traversal::Compositor compositor; + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + + // + // + PrimaryAttribute attribute (*this, member_set, restriction); + Traversal::Names names (attribute); + + Complex::names (c, names); + } + + // Assign "secondary" names. + // + { + if (c.contains_compositor_p ()) + { + SecondaryParticle particle (*this, member_set, restriction); + SecondaryCompositor compositor (*this, member_set, restriction); + Traversal::ContainsCompositor contains_compositor; + Traversal::ContainsParticle contains_particle; + + contains_compositor >> compositor >> contains_particle; + + contains_particle >> compositor; + contains_particle >> particle; + + Complex::contains_compositor (c, contains_compositor); + } + + // + // + SecondaryAttribute attribute (*this, member_set, restriction); + Traversal::Names names (attribute); + + Complex::names (c, names); + } + } + }; + + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + String const& n (t.name ()); + SemanticGraph::Context& tc (t.context ()); + + String name (find_name (n + skel_suffix, set_)); + tc.set ("s:name", name); + + if (tiein) + tc.set ("s:tiein", escape (n + L"_impl_")); + + // Note that we do not add this name to the set so that it + // does not influence other names. + // + if (impl) + tc.set ("s:impl", escape (n + impl_suffix)); + } + + private: + NameSet& set_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& ns) + { + SemanticGraph::Context& nsc (ns.context ()); + String const& name (ns.name ()); + + // Use a name set associated with this namespace if present. + // This will make sure that we don't get any conflicts in the + // multi-mapping translation case. Note that here we assume + // that all mappings traverse schemas in the same order which + // is currently the case. + // + if (global_type_names.find (name) == global_type_names.end ()) + { + if (!nsc.count ("name-set")) + nsc.set ("name-set", NameSet ()); + + NameSet& s (nsc.get ("name-set")); + global_type_names[name] = &s; + } + + NameSet& type_set (*global_type_names[name]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + } + }; + + struct FundType : Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + + { + FundType (Context& c) + : Context (c) + { + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + set_names (t, "any_type"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + set_names (t, "any_simple_type"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + set_names (t, "boolean"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + set_names (t, "byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + set_names (t, "unsigned_byte"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + set_names (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + set_names (t, "unsigned_short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + set_names (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + set_names (t, "unsigned_int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + set_names (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + set_names (t, "unsigned_long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + set_names (t, "integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + set_names (t, "non_positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + set_names (t, "non_negative_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + set_names (t, "positive_integer"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + set_names (t, "negative_integer"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + set_names (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + set_names (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + set_names (t, "decimal"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + set_names (t, "string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + set_names (t, "normalized_string"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + set_names (t, "token"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + set_names (t, "nmtoken"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + set_names (t, "nmtokens"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + set_names (t, "name"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + set_names (t, "ncname"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + set_names (t, "language"); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + set_names (t, "qname"); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + set_names (t, "id"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + set_names (t, "idref"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + set_names (t, "idrefs"); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + set_names (t, "uri"); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + set_names (t, "base64_binary"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + set_names (t, "hex_binary"); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + set_names (t, "date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + set_names (t, "date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + set_names (t, "duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + set_names (t, "gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + set_names (t, "gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + set_names (t, "gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + set_names (t, "gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + set_names (t, "gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + set_names (t, "time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + set_names (t, "entity"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + set_names (t, "entities"); + } + + private: + String + make_skel_name (String const& base) + { + return escape (base + skel_suffix); + } + + String + make_impl_name (String const& base) + { + return escape (base + impl_suffix); + } + + Void + set_names (SemanticGraph::Type& t, String const& name) + { + SemanticGraph::Context& c (t.context ()); + + WideChar const* ns = validation + ? L"::xsde::cxx::serializer::validating::" + : L"::xsde::cxx::serializer::non_validating::"; + + String skel (make_skel_name (name)); + c.set ("s:name", skel); + c.set ("s:real-name", ns + skel); + + String impl (make_impl_name (name)); + c.set ("s:impl", impl); + c.set ("s:real-impl", ns + impl); + + c.set ("s:post", L"post_" + name); + + if (tiein) + c.set ("s:tiein", name + L"_impl_"); + } + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count ("cxx-serializer-name-processor-seen")) + { + s.context ().set ("cxx-serializer-name-processor-seen", true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-serializer-name-processor-seen")) + { + s.context ().set ("cxx-serializer-name-processor-seen", true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-serializer-name-processor-seen")) + { + s.context ().set ("cxx-serializer-name-processor-seen", true); + Traversal::Imports::traverse (i); + } + } + }; + + // Go into implied schemas while making sure we don't process + // the same stuff more than once. + // + struct Implies: Traversal::Implies + { + virtual Void + traverse (SemanticGraph::Implies& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-serializer-name-processor-seen")) + { + s.context ().set ("cxx-serializer-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + Void + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + Context ctx (ops, tu, file); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // Pass one - assign names to fundamental types. + // + { + Traversal::Schema schema; + Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (ctx); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Pass two - assign names to global types. This pass cannot + // be combined with pass three because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count ("cxx-serializer-name-processor-seen")) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Namespace ns (ctx); + + schema >> schema_names >> ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-serializer-name-processor-seen", true); + + schema.dispatch (tu); + } + + // Pass three - assign names inside complex types. Here we don't + // need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + Complex complex (ctx); + + ns_names >> complex; + + schema.dispatch (tu); + } + } + } + } + + Void NameProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + process_impl (ops, tu, file); + } + } +} diff --git a/xsde/cxx/serializer/name-processor.hxx b/xsde/cxx/serializer/name-processor.hxx new file mode 100644 index 0000000..bf69ba6 --- /dev/null +++ b/xsde/cxx/serializer/name-processor.hxx @@ -0,0 +1,32 @@ +// file : xsde/cxx/serializer/name-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_NAME_PROCESSOR_HXX +#define CXX_SERIALIZER_NAME_PROCESSOR_HXX + +#include + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + using namespace Cult::Types; + + class NameProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // CXX_SERIALIZER_NAME_PROCESSOR_HXX diff --git a/xsde/cxx/serializer/serializer-forward.cxx b/xsde/cxx/serializer/serializer-forward.cxx new file mode 100644 index 0000000..60d5ce5 --- /dev/null +++ b/xsde/cxx/serializer/serializer-forward.cxx @@ -0,0 +1,112 @@ +// file : xsde/cxx/serializer/serializer-forward.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + os << "class " << ename (e) << ";"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + os << "class " << ename (l) << ";"; + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + os << "class " << ename (u) << ";"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + os << "class " << ename (c) << ";"; + } + }; + } + + Void + generate_serializer_forward (Context& ctx) + { + ctx.os << "// Forward declarations" << endl + << "//" << endl; + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + + ctx.os << endl; + } + } +} diff --git a/xsde/cxx/serializer/serializer-forward.hxx b/xsde/cxx/serializer/serializer-forward.hxx new file mode 100644 index 0000000..239d82f --- /dev/null +++ b/xsde/cxx/serializer/serializer-forward.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/serializer-forward.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_SERIALIZER_FORWARD_HXX +#define CXX_SERIALIZER_SERIALIZER_FORWARD_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_serializer_forward (Context&); + } +} + +#endif // CXX_SERIALIZER_SERIALIZER_FORWARD_HXX diff --git a/xsde/cxx/serializer/serializer-header.cxx b/xsde/cxx/serializer/serializer-header.cxx new file mode 100644 index 0000000..6ba57f1 --- /dev/null +++ b/xsde/cxx/serializer/serializer-header.cxx @@ -0,0 +1,2006 @@ +// file : xsde/cxx/serializer/serializer-header.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + // Override classes override pure virtual functions in the base. + // Should be in sync with declaration generators below. Used in + // tiein implementation. + // + + struct CompositorCallbackOverride: Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallbackOverride (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (max != 1 && min != 0) + { + os << "virtual bool" << endl + << enext (c) << " ();" + << endl; + } + + if (min != 0) + { + os << "virtual " << earm_tag (c) << endl + << earm (c) << " ();" + << endl; + } + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (max != 1 && min != 0) + { + os << "virtual bool" << endl + << enext (s) << " ();" + << endl; + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallbackOverride: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallbackOverride (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + if (max != 1 && min != 0) + { + os << "virtual bool" << endl + << enext (e) << " ();" + << endl; + } + + String const& ret (ret_type (e.type ())); + + if (ret != L"void") + { + os << "virtual " << ret << endl + << ename (e) << " ();" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min != 0 && + !a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()) + { + if (max != 1) + { + os << "virtual bool" << endl + << enext (a) << " ();" + << endl; + } + + if (stl) + { + os << "virtual void" << endl + << ename (a) << " (::std::string& ns, ::std::string& name);" + << endl; + } + else + { + os << "virtual void" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free);" + << endl; + } + + os << "virtual void" << endl + << eserialize (a) << " ();" + << endl; + } + } + }; + + struct AttributeCallbackOverride: Traversal::Attribute, Context + { + AttributeCallbackOverride (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& ret (ret_type (a.type ())); + + if (ret != L"void") + { + os << "virtual " << ret << endl + << ename (a) << " ();" + << endl; + } + } + }; + + struct BaseOverride: Traversal::Type, + Traversal::Enumeration, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Context + { + BaseOverride (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + // pre + // + String const& arg (arg_type (t)); + + if (arg != L"void") + { + os << "virtual void" << endl + << "pre (" << arg << ");" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + SemanticGraph::Type& t (e); + traverse (t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + SemanticGraph::Type& t (l); + traverse (t); + + // item + // + String const& ret (ret_type (l.argumented ().type ())); + + if (ret != L"void") + { + os << "virtual " << ret << endl + << unclash (ename (l), "item") << " ();" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Union& u) + { + SemanticGraph::Type& t (u); + traverse (t); + + // serialize_content + // + os << "virtual void" << endl + << "_serialize_content ();" + << endl; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Type& t (c); + traverse (t); + + // Member callbacks. + // + if (!restriction_p (c)) + { + Traversal::Complex::names (c, names_attribute_callback_); + Traversal::Complex::contains_compositor ( + c, contains_compositor_callback_); + } + } + + private: + CompositorCallbackOverride compositor_callback_; + ParticleCallbackOverride particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallbackOverride attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + + // + // + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + String fq_base (fq_name (base)); + + os << "class " << name << ": public " << + (mixin ? "virtual " : "") << fq_base + << "{" + << "public:" << endl + << "// Serializer callbacks. Override them in your " << + "implementation." << endl + << "//" << endl + << endl; + + // pre + // + String const& arg (arg_type (e)); + String const& base_arg (arg_type (base)); + + if (arg == base_arg) + { + os << "// virtual void" << endl; + + if (arg == L"void") + os << "// pre ();" << endl; + else + os << "// pre (" << arg << ") = 0;" << endl; + + os << endl; + } + else + { + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ") = 0;"; + + os << endl; + } + + // post + // + os << "// virtual void" << endl + << "// post ();" << endl; + + if (poly_code) + { + os << endl + << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;"; + } + + if (tiein) + { + os << endl + << "// Constructor." << endl + << "//" << endl + << name << " (" << fq_base << "* tiein);" + << endl; + + os << "// Implementation details." << endl + << "//" << endl; + + // If our base has pure virtual functions, override them here. + // + inherits (e); + + os << "protected:" << endl + << name << "* " << etiein (e) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + os << "};"; + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + String item_type (fq_name (t)); + + String item (unclash (name, "item")); + String item_next (unclash (name, "item_next")); + + os << "class " << name << ": public " << simple_base + << "{" + << "public:" << endl + << "// Serializer callbacks. Override them in your " << + "implementation." << endl + << "//" << endl + << endl; + + // pre + // + String const& arg (arg_type (l)); + + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ") = 0;"; + + os << endl; + + // item + // + os << "virtual bool" << endl + << item_next << " ();" + << endl; + + String const& ret (ret_type (t)); + + os << "virtual " << ret << endl + << item << " ()" << (ret != L"void" ? " = 0" : "") << ";" + << endl; + + // post + // + os << "// virtual void" << endl + << "// post ();" << endl + << endl; + + // + // + os << "// Serializer construction API." << endl + << "//" << endl; + + // item_serializer + // + os << "void" << endl + << unclash (name, "item_serializer") << " (" << item_type << "&);" + << endl; + + // serializers + // + os << "void" << endl + << "serializers (" << item_type << "& /* item */);" + << endl; + + if (reset) + os << "virtual void" << endl + << "_reset ();" + << endl; + + // c-tor + // + os << "// Constructor." << endl + << "//" << endl + << name << " ();" + << endl; + + if (poly_code) + { + os << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;" + << endl; + } + + // + // + os << "// Implementation." << endl + << "//" << endl + << "public:" << endl; + + os << "virtual void" << endl + << "_serialize_content ();" + << endl; + + os << "protected:" << endl; + + if (tiein) + { + os << name << "* " << etiein (l) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + os << item_type << "* _xsde_" << item << "_;" + << "};"; + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + + os << "class " << name << ": public " << simple_base + << "{" + << "public:" << endl + << "// Serializer callbacks. Override them in your " << + "implementation." << endl + << "//" << endl + << endl; + + // pre + // + String const& arg (arg_type (u)); + + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ") = 0;"; + + os << endl; + + // serialize_content + // + os << "virtual void" << endl + << "_serialize_content () = 0;" + << endl; + + // post + // + os << "// virtual void" << endl + << "// post ();" << endl; + + if (poly_code) + { + os << endl + << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;"; + } + + if (tiein) + { + // c-tor + // + os << endl + << "// Constructor." << endl + << "//" << endl + << name << " ();" + << endl; + + // + // + os << "// Implementation details." << endl + << "//" << endl + << "protected:" << endl + << name << "* " << etiein (u) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + os << "};"; + } + }; + + // + // + struct ParticleTag: Traversal::Particle, Context + { + ParticleTag (Context& c) + : Context (c), first_ (true) + { + } + + virtual Void + traverse (Type& p) + { + if (first_) + first_ = false; + else + os << "," << endl; + + os << etag (p); + } + + private: + Boolean first_; + }; + + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context ().count ("xsd-frontend-restriction-correspondence")) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + if (SemanticGraph::Compositor* b = correspondent (c)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + UnsignedLong cmin (c.min ()), bmax (b->max ()); + + if (bmax != 1 && cmin == 0) + { + os << "virtual bool" << endl + << epresent (c) << " ();" + << endl; + } + } + else + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (c) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (c) << " ()" << (min != 0 ? " = 0" : "") << ";" + << endl; + } + + // + // + os << "enum " << earm_tag (c) + << "{"; + + { + ParticleTag particle (*this); + Traversal::ContainsParticle contain_particle (particle); + Traversal::Choice::contains (c, contain_particle); + } + + os << "};"; + + os << "virtual " << earm_tag (c) << endl + << earm (c) << " ()" << (min != 0 ? " = 0" : "") << ";" + << endl; + } + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + // Root compositor that models inheritance by extension + // may not have an association so we may fall through + // in to the 'else' case even though this is a restriction. + // This is ok since such a compositor always has max == + // min == 1 and so nothing is generated. + // + if (SemanticGraph::Compositor* b = correspondent (s)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + UnsignedLong smin (s.min ()); + UnsignedLong bmax (b->max ()); + + if (bmax != 1 && smin == 0) + { + os << "virtual bool" << endl + << epresent (s) << " ();" + << endl; + } + } + else + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (s) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (s) << " ()" << (min != 0 ? " = 0" : "") << ";" + << endl; + } + } + + Traversal::Sequence::traverse (s); + } + }; + + struct ParticleCallback: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (SemanticGraph::Element* b = correspondent (e)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (b->max () != 1 && e.min () == 0) + { + os << "virtual bool" << endl + << epresent (e) << " ();" + << endl; + } + } + else + { + UnsignedLong min (e.min ()), max (e.max ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (e) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (e) << " ()" << (min != 0 ? " = 0" : "") << ";" + << endl; + } + + String const& ret (ret_type (e.type ())); + + // Make it non-pure-virtual only if the return type is void. + // + os << "virtual " << ret << endl + << ename (e) << " ()" << (ret != L"void" ? " = 0;" : ";") + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (SemanticGraph::Any* b = correspondent (a)) + { + // Add the *_present callback if this is a restriction + // of sequence to optional. + // + if (b->max () != 1 && a.min () == 0) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + } + else + { + UnsignedLong min (a.min ()), max (a.max ()); + + // Generate pure virtual callbacks unless we are optional + // or in choice. + // + Boolean pv ( + min != 0 && + !a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()); + + if (min == 0 && max == 1) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + else if (max != 1) + { + os << "virtual bool" << endl + << enext (a) << " ()" << (pv ? " = 0" : "") << ";" + << endl; + } + + if (stl) + { + os << "virtual void" << endl + << ename (a) << " (::std::string& ns, ::std::string& name)" << + (pv ? " = 0;" : ";") + << endl; + } + else + { + os << "virtual void" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free)" << (pv ? " = 0;" : ";") + << endl; + } + + os << "virtual void" << endl + << eserialize (a) << " ()" << (pv ? " = 0;" : ";") + << endl; + } + } + }; + + struct AttributeCallback: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (a.optional ()) + { + os << "virtual bool" << endl + << epresent (a) << " ();" + << endl; + } + + String const& ret (ret_type (a.type ())); + + // Make it non-pure-virtual only if the return type is void. + // + os << "virtual " << ret << endl + << ename (a) << " ()" << (ret != L"void" ? " = 0;" : ";") + << endl; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << "virtual bool" << endl + << enext (a) << " ();" + << endl; + + if (stl) + { + os << "virtual void" << endl + << ename (a) << " (::std::string& ns, ::std::string& name);" + << endl; + } + else + { + os << "virtual void" << endl + << ename (a) << " (const char*& ns, const char*& name, " << + "bool& free);" + << endl; + } + + os << "virtual void" << endl + << eserialize (a) << " ();" + << endl; + } + }; + + + // + // + struct ParticleAccessor: Traversal::Element, Context + { + ParticleAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& serializer (eserializer (e)); + + os << "void" << endl + << serializer << " (" << fq_name (e.type ()) << "&);" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + os << "void" << endl + << eserializer (e) << " (" << serializer_map << "&);" + << endl; + } + } + }; + + struct AttributeAccessor: Traversal::Attribute, Context + { + AttributeAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << "void" << endl + << eserializer (a) << " (" << fq_name (a.type ()) << "&);" + << endl; + } + }; + + + // + // + struct ParticleMember: Traversal::Element, Context + { + ParticleMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String type (fq_name (e.type ())); + + os << type << "* " << emember (e) << ";"; + + if (poly_code && !anonymous (e.type ())) + { + os << serializer_map << "* " << emember_map (e) << ";" + << endl; + } + } + }; + + struct AttributeMember: Traversal::Attribute, Context + { + AttributeMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << fq_name (a.type ()) << "* " << emember (a) << ";"; + } + }; + + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_accessor_ (c), + attribute_accessor_ (c), + particle_member_ (c), + attribute_member_ (c) + { + // Callback. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Accessor. + // + contains_compositor_accessor_ >> compositor_accessor_; + compositor_accessor_ >> contains_particle_accessor_; + contains_particle_accessor_ >> compositor_accessor_; + contains_particle_accessor_ >> particle_accessor_; + + names_attribute_accessor_ >> attribute_accessor_; + + // Member. + // + contains_compositor_member_ >> compositor_member_; + compositor_member_ >> contains_particle_member_; + contains_particle_member_ >> compositor_member_; + contains_particle_member_ >> particle_member_; + + names_attribute_member_ >> attribute_member_; + } + + virtual Void + traverse (Type& c) + { + String const& name (ename (c)); + + // In case of an inheritance-by-restriction, we don't need to + // generate serializer callbacks, etc. since they are the same + // as in the base. We only need the serialization/validation code. + // + Boolean restriction (restriction_p (c)); + + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + Boolean haa (has (c)); + + Boolean hra (false); // Has required attribute. + if (ha) + { + RequiredAttributeTest test (hra); + Traversal::Names names_test (test); + names (c, names_test); + } + + // + // + os << "class " << name << ": public "; + + if (hb) + os << (mixin ? "virtual " : "") << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << "{" + << "public:" << endl + << "// Serializer callbacks. Override them in your " << + "implementation." << endl + << "//" << endl + << endl; + + // pre + // + String const& arg (arg_type (c)); + Boolean same (hb && arg == arg_type (c.inherits ().base ())); + + if (same) + { + os << "// virtual void" << endl; + + if (arg == L"void") + os << "// pre ();" << endl; + else + os << "// pre (" << arg << ") = 0;" << endl; + + os << endl; + } + else + { + os << "virtual void" << endl; + + if (arg == L"void") + os << "pre ();"; + else + os << "pre (" << arg << ") = 0;"; + + os << endl; + } + + // Member callbacks. + // + if (!restriction) + { + if (ha || haa) + { + os << "// Attributes." << endl + << "//" << endl; + + names (c, names_attribute_callback_); + } + } + + if (he || hae) + { + if (!restriction) + { + os << "// Elements." << endl + << "//" << endl; + } + + contains_compositor (c, contains_compositor_callback_); + } + + // post + // + os << "// virtual void" << endl + << "// post ();" << endl + << endl; + + // + // + if (!restriction && (he || ha)) + { + os << "// Serializer construction API." << endl + << "//" << endl; + + os << "void" << endl + << "serializers ("; + + { + SerializerParamDecl decl (*this, false); + decl.traverse (c); + } + + os << ");" + << endl; + + if (ha) + { + os << "// Individual attribute serializers." << endl + << "//" << endl; + + names (c, names_attribute_accessor_); + } + + if (he) + { + os << "// Individual element serializers." << endl + << "//" << endl; + + contains_compositor (c, contains_compositor_accessor_); + } + } + + if (!restriction && (he || ha) && reset) + { + os << "virtual void" << endl + << "_reset ();" + << endl; + } + + // Default c-tor. + // + if (tiein || (!restriction && (he || ha))) + { + os << "// Constructor." << endl + << "//" << endl; + + if (hb && tiein) + os << name << " (" << fq_name (c.inherits ().base ()) << + "* tiein);" + << endl; + else + os << name << " ();" + << endl; + } + + if (poly_code) + { + os << "public:" << endl + << "static const char*" << endl + << "_static_type ();" + << endl + << "virtual const char*" << endl + << "_dynamic_type () const;" + << endl; + } + + // Implementation. + // + if (tiein || he || ha || hae || haa) + { + os << "// Implementation." << endl + << "//" << endl + << "public:" << endl; + + // If our base has pure virtual functions, override them here. + // + if (tiein && hb) + inherits (c); + + if (ha || haa) + { + os << "virtual void" << endl + << "_serialize_attributes ();" + << endl; + } + + if (he || hae) + { + os << "virtual void" << endl + << "_serialize_content ();" + << endl; + } + } + + if (tiein) + { + os << "protected:" << endl + << name << "* " << etiein (c) << ";" + << name << " (" << name << "*, void*);" + << endl; + } + + if (!restriction && (he || ha)) + { + os << "protected:" << endl; + + if (ha) + names (c, names_attribute_member_); + + if (he) + contains_compositor (c, contains_compositor_member_); + } + + os << "};"; + } + + private: + // + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_accessor_; + ParticleAccessor particle_accessor_; + Traversal::ContainsCompositor contains_compositor_accessor_; + Traversal::ContainsParticle contains_particle_accessor_; + + AttributeAccessor attribute_accessor_; + Traversal::Names names_attribute_accessor_; + + // + // + Traversal::Compositor compositor_member_; + ParticleMember particle_member_; + Traversal::ContainsCompositor contains_compositor_member_; + Traversal::ContainsParticle contains_particle_member_; + + AttributeMember attribute_member_; + Traversal::Names names_attribute_member_; + }; + + struct FundType : Context, + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + { + FundType (Context& c) + : Context (c), xs_ns_ (xs_ns_name ()) + { + impl_ns_ = "::xsde::cxx::serializer::"; + impl_ns_ += (validation ? L"validating" : L"non_validating"); + + if (options.value ()) + { + qname_type_ = L"const " + xs_ns_ + L"::qname*"; + string_type_ = L"const char*"; + } + else + { + qname_type_ = xs_ns_ + L"::qname"; + string_type_ = L"::std::string"; + } + + string_seq_type_ = L"const " + xs_ns_ + L"::string_sequence*"; + buffer_type_ = L"const " + xs_ns_ + L"::buffer*"; + + if (options.value ()) + { + long_type_ = L"long"; + unsigned_long_type_ = L"unsigned long"; + } + else + { + long_type_ = L"long long"; + unsigned_long_type_ = L"unsigned long long"; + } + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + gen_typedef (t, "void"); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + gen_typedef (t, "void"); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + gen_typedef (t, "bool"); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + gen_typedef (t, "signed char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + gen_typedef (t, "unsigned char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + gen_typedef (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + gen_typedef (t, "unsigned short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + gen_typedef (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + gen_typedef (t, "unsigned int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + gen_typedef (t, long_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + gen_typedef (t, unsigned_long_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + gen_typedef (t, "long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + gen_typedef (t, "unsigned long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + gen_typedef (t, "unsigned long"); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + gen_typedef (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + gen_typedef (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + gen_typedef (t, "double"); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + nmtoken_ = gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + // NMTOKENS uses NMTOKEN implementation to serialize individual + // items. As a result, we don't generate NMTOKENS if we didn't + // generate NMTOKEN. Here we assume NMTOKEN is handled before + // NMTOKENS. + // + if(nmtoken_) + gen_typedef (t, string_seq_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + gen_typedef (t, string_type_); + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + gen_typedef (t, qname_type_); + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + idref_ = gen_typedef (t, string_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + // IDREFS uses IDREF implementation to serialize individual items. + // As a result, we don't generate IDREFS if we didn't generate + // IDREF. Here we assume IDREF is handled before IDREFS. + // + if (idref_) + gen_typedef (t, string_seq_type_); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + gen_typedef (t, string_type_); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + gen_typedef (t, buffer_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + gen_typedef (t, buffer_type_); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + gen_typedef (t, xs_ns_ + L"::date"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + gen_typedef (t, xs_ns_ + L"::date_time"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + gen_typedef (t, xs_ns_ + L"::duration"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + gen_typedef (t, xs_ns_ + L"::gday"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + gen_typedef (t, xs_ns_ + L"::gmonth"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + gen_typedef (t, xs_ns_ + L"::gmonth_day"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + gen_typedef (t, xs_ns_ + L"::gyear"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + gen_typedef (t, xs_ns_ + L"::gyear_month"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + gen_typedef (t, xs_ns_ + L"::time"); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&) + { + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&) + { + } + + private: + Boolean + gen_typedef (SemanticGraph::Type& t, String const& type) + { + if (ret_type (t) == type) + { + SemanticGraph::Context& c (t.context ()); + + String const& real_name (c.get ("s:real-name")); + String const& name (c.get ("s:name")); + + os << "typedef " << real_name << " " << name << ";"; + + String const& real_impl (c.get ("s:real-impl")); + String const& impl (c.get ("s:impl")); + + os << "typedef " << real_impl << " " << impl << ";" + << endl; + + return true; + } + + return false; + } + + String xs_ns_; + String impl_ns_; + String qname_type_; + String string_type_; + String buffer_type_; + String string_seq_type_; + String long_type_; + String unsigned_long_type_; + + Boolean idref_; + Boolean nmtoken_; + }; + + struct FundNamespace : Namespace, Context + { + FundNamespace (Context& c) + : Namespace (c), Context (c) + { + } + + void + traverse (Type& ns) + { + pre (ns); + + String impl ("::xsde::cxx::serializer::"); + impl += (validation ? L"validating" : L"non_validating"); + + String const c (char_type); + + os << "// Built-in XML Schema types mapping." << endl + << "//" << endl + << "using ::xsde::cxx::string_sequence;" + << "using ::xsde::cxx::qname;" + << "using ::xsde::cxx::buffer;" + << "using ::xsde::cxx::time_zone;" + << "using ::xsde::cxx::gday;" + << "using ::xsde::cxx::gmonth;" + << "using ::xsde::cxx::gyear;" + << "using ::xsde::cxx::gmonth_day;" + << "using ::xsde::cxx::gyear_month;" + << "using ::xsde::cxx::date;" + << "using ::xsde::cxx::time;" + << "using ::xsde::cxx::date_time;" + << "using ::xsde::cxx::duration;" + << endl; + + os << "// Base serializer skeletons." << endl + << "//" << endl + << "using ::xsde::cxx::serializer::serializer_base;" + << "typedef " << impl << "::empty_content " << + "serializer_empty_content;" + << "typedef " << impl << "::simple_content " << + "serializer_simple_content;" + << "typedef " << impl << "::complex_content " << + "serializer_complex_content;" + << endl; + + if (poly_code) + { + os << "// Serializer map interface and default implementation." << endl + << "//" << endl + << "using ::xsde::cxx::serializer::serializer_map;" + << "using ::xsde::cxx::serializer::serializer_map_impl;" + << endl; + + os << "// Substitution and inheritance hashmaps load querying." << endl + << "//" << endl + << "using ::xsde::cxx::serializer::serializer_smap_buckets;" + << "using ::xsde::cxx::serializer::serializer_smap_elements;" + << "using ::xsde::cxx::serializer::serializer_smap_bucket_buckets;" + << "using ::xsde::cxx::serializer::serializer_smap_bucket_elements;"; + + if (validation) + os << "using ::xsde::cxx::serializer::validating::serializer_imap_buckets;" + << "using ::xsde::cxx::serializer::validating::serializer_imap_elements;"; + + os << endl; + } + + os << "// Serializer skeletons and implementations for the" << endl + << "// XML Schema built-in types." << endl + << "//" << endl; + + names (ns); + + os << "// Error codes." << endl + << "//" << endl; + + if (!exceptions) + os << "using xsde::cxx::sys_error;"; + + os << "typedef xsde::cxx::serializer::genx::xml_error " << + "serializer_xml_error;"; + + if (validation) + os << "typedef xsde::cxx::schema_error " << + "serializer_schema_error;"; + + os << endl; + + if (exceptions) + { + os << "// Exceptions." << endl + << "//" << endl + << "typedef xsde::cxx::serializer::exception " << + "serializer_exception;" + << "typedef xsde::cxx::serializer::xml serializer_xml;"; + + if (validation) + os << "typedef xsde::cxx::serializer::schema " << + "serializer_schema;"; + + os << endl; + } + else + os << "// Error object." << endl + << "//" << endl + << "typedef xsde::cxx::serializer::error serializer_error;" + << endl; + + os << "// Document serializer." << endl + << "//" << endl + << "using xsde::cxx::serializer::genx::writer;" + << "using xsde::cxx::serializer::genx::document_simpl;" + << endl; + + os << "// Serializer context." << endl + << "//" << endl + << "typedef xsde::cxx::serializer::context serializer_context;" + << endl; + + post (ns); + } + }; + } + + Void + generate_serializer_header (Context& ctx, Boolean generate_xml_schema) + { + NarrowString extern_xml_schema; + + if (!generate_xml_schema) + extern_xml_schema = ctx.options.value (); + + if (extern_xml_schema) + { + String name (ctx.hxx_expr->merge (extern_xml_schema)); + + ctx.os << "#include " << ctx.process_include_path (name) << endl + << endl; + + // Generate includes that came from the type map. + // + if (ctx.schema_root.context ().count ("s:includes")) + { + typedef Cult::Containers::Set Includes; + + Includes& is ( + ctx.schema_root.context ().get ("s:includes")); + + for (Includes::ConstReverseIterator i (is.rbegin ()); + i != is.rend (); ++i) + { + ctx.os << "#include " << *i << endl; + } + + ctx.os << endl; + } + } + else + { + ctx.os << "#include " << endl + << endl; + + // std::string or xsde::cxx::string is used in wildcard API. + // + if (ctx.stl) + { + ctx.os << "#include " << endl + << endl; + } + else + { + ctx.os << "#include " << endl + << endl; + } + + // Data types. + // + ctx.os << "#include " << endl + << endl; + + // Error handling. + // + if (ctx.exceptions) + ctx.os << "#include " << endl + << endl; + else + { + ctx.os << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl; + + ctx.os << "#include " << endl + << "#include " << endl; + + ctx.os << endl; + } + + // Polymorphism support. + // + if (ctx.poly_code) + { + ctx.os << "#include " << endl + << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl; + + ctx.os << endl; + } + + // Serializers. + // + if (ctx.validation) + ctx.os << "#include " << endl + << "#include " << endl + << "#include " << endl + << endl; + else + ctx.os << "#include " << endl + << "#include " << endl + << "#include " << endl + << endl; + + // Document. + // + ctx.os << "#include " << endl + << endl; + + // Generate includes that came from the type map. + // + if (ctx.schema_root.context ().count ("s:includes")) + { + typedef Cult::Containers::Set Includes; + + Includes& is ( + ctx.schema_root.context ().get ("s:includes")); + + for (Includes::ConstReverseIterator i (is.rbegin ()); + i != is.rend (); ++i) + { + ctx.os << "#include " << *i << endl; + } + + ctx.os << endl; + } + + // Generate fundamental types. + // + if (generate_xml_schema) + { + Traversal::Schema schema; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + } + else + { + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + FundNamespace ns (ctx); + + schema >> implies >> xsd >> names >> ns; + + Traversal::Names ns_names; + FundType type (ctx); + + ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + } + } + + // Generate user type mapping. + // + if (!generate_xml_schema) + { + Traversal::Schema schema; + + Traversal::Sources sources; + Includes includes (ctx, Includes::header); + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> includes; + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + BaseOverride base_override (ctx); + Traversal::Inherits inherits_override; + + complex >> inherits_override; + enumeration >> inherits_override; + inherits_override >> base_override; + + schema.dispatch (ctx.schema_root); + } + } + } +} diff --git a/xsde/cxx/serializer/serializer-header.hxx b/xsde/cxx/serializer/serializer-header.hxx new file mode 100644 index 0000000..64c63ab --- /dev/null +++ b/xsde/cxx/serializer/serializer-header.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/serializer-header.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_SERIALIZER_HEADER_HXX +#define CXX_SERIALIZER_SERIALIZER_HEADER_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_serializer_header (Context&, Boolean generate_xml_schema); + } +} + +#endif // CXX_SERIALIZER_SERIALIZER_HEADER_HXX diff --git a/xsde/cxx/serializer/serializer-inline.cxx b/xsde/cxx/serializer/serializer-inline.cxx new file mode 100644 index 0000000..8caa791 --- /dev/null +++ b/xsde/cxx/serializer/serializer-inline.cxx @@ -0,0 +1,631 @@ +// file : xsde/cxx/serializer/serializer-inline.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (tiein) + { + String const& name (ename (e)); + String const& impl (etiein (e)); + + // We have to use "real" (non-typedef) base name in base + // initializer because of some broken compilers (EVC 4.0). + // + SemanticGraph::Type& base (e.inherits ().base ()); + String fq_base (fq_name (base)); + String real_fq_base (real_fq_name (base)); + + os << "// " << name << endl + << "//" << endl + << endl; + + os << inl + << name << "::" << endl + << name << " (" << fq_base << "* tiein)" << endl + << ": " << real_fq_base << " (tiein, 0)," << endl + << " " << impl << " (0)" + << "{" + << "}"; + + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << real_fq_base << " (impl, 0)," << endl + << " " << impl << " (impl)" + << "{" + << "}"; + } + } + }; + + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + String item_type (fq_name (t)); + + String item (unclash (name, "item")); + + os << "// " << name << endl + << "//" << endl + << endl; + + // item_serializer + // + os << inl + << "void " << name << "::" << endl + << unclash (name, "item_serializer") << " (" << + item_type << "& " << item << ")" + << "{" + << "this->_xsde_" << item << "_ = &" << item << ";" + << "}"; + + // serializers + // + os << inl + << "void " << name << "::" << endl + << "serializers (" << item_type << "& " << item << ")" + << "{" + << "this->_xsde_" << item << "_ = &" << item << ";" + << "}"; + + // c-tor + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": "; + + if (tiein) + os << etiein (l) << " (0)," << endl + << " "; + + os << "_xsde_" << item << "_ (0)" + << "{" + << "}"; + + if (tiein) + { + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << simple_base << " (impl, 0)," << endl + << " " << etiein (l) << " (impl)," << endl + << " _xsde_" << item << "_ (0)" + << "{" + << "}"; + } + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + if (tiein) + { + String const& name (ename (u)); + String const& impl (etiein (u)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << impl << " (0)" + << "{" + << "}"; + + // + // + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": " << simple_base << " (impl, 0)," << endl + << " " << impl << " (impl)" + << "{" + << "}"; + } + } + }; + + // + // + struct ParticleAccessor: Traversal::Element, Context + { + ParticleAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& scope (ename (e.scope ())); + String const& serializer (eserializer (e)); + + os << inl + << "void " << scope << "::" << endl + << serializer << " (" << fq_name (e.type ()) << "& s)" + << "{" + << "this->" << emember (e) << " = &s;" + << "}"; + + if (poly_code && !anonymous (e.type ())) + { + os << inl + << "void " << scope << "::" << endl + << serializer << " (" << serializer_map << "& m)" + << "{" + << "this->" << emember_map (e) << " = &m;" + << "}"; + } + } + }; + + struct AttributeAccessor: Traversal::Attribute, Context + { + AttributeAccessor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& name (ename (a)); + + os << inl + << "void " << ename (a.scope ()) << "::" << endl + << eserializer (a) << " (" << fq_name (a.type ()) << "& " << + name << ")" + << "{" + << "this->" << emember (a) << " = &" << name << ";" + << "}"; + } + }; + + // + // + struct ParticleMemberSet: Traversal::Element, Context + { + ParticleMemberSet (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + os << "this->" << emember (e) << " = &" << ename (e) << ";"; + } + }; + + struct AttributeMemberSet: Traversal::Attribute, Context + { + AttributeMemberSet (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + os << "this->" << emember (a) << " = &" << ename (a) << ";"; + } + }; + + struct BaseMemberSet: Traversal::Complex, + Traversal::List, + Context + { + BaseMemberSet (Context& c) + : Context (c) + { + inherits_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!restriction_p (c)) + { + names (c); + contains_compositor (c); + } + } + + virtual Void + traverse (SemanticGraph::List& l) + { + String const& name (ename (l)); + String item (unclash (name, "item")); + + os << "this->_xsde_" << item << "_ = &" << name << "_item;"; + } + + private: + Traversal::Inherits inherits_; + }; + + // + // + struct ParticleMemberInit: Traversal::Element, Context + { + ParticleMemberInit (Context& c, Boolean comma) + : Context (c), first_ (!comma) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (first_) + first_ = false; + else + os << "," << endl << " "; + + os << emember (e) << " (0)"; + + if (poly_code && !anonymous (e.type ())) + { + os << "," << endl + << " " << emember_map (e) << " (0)"; + } + } + + private: + Boolean first_; + }; + + struct AttributeMemberInit: Traversal::Attribute, Context + { + AttributeMemberInit (Context& c, Boolean comma) + : Context (c), first_ (!comma) + { + } + + virtual Void + traverse (Type& a) + { + if (first_) + first_ = false; + else + os << "," << endl << " "; + + os << emember (a) << " (0)"; + } + + Boolean + comma () const + { + return !first_; + } + + private: + Boolean first_; + }; + + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + particle_accessor_ (c), + attribute_accessor_ (c), + base_set_ (c), + particle_set_ (c), + attribute_set_ (c) + { + // Accessor. + // + contains_compositor_accessor_ >> compositor_accessor_; + compositor_accessor_ >> contains_particle_accessor_; + contains_particle_accessor_ >> compositor_accessor_; + contains_particle_accessor_ >> particle_accessor_; + + names_attribute_accessor_ >> attribute_accessor_; + + // Member set. + // + inherits_base_set_ >> base_set_; + base_set_ >> contains_compositor_set_; + base_set_ >> names_attribute_set_; + + contains_compositor_set_ >> compositor_set_; + compositor_set_ >> contains_particle_set_; + contains_particle_set_ >> compositor_set_; + contains_particle_set_ >> particle_set_; + + names_attribute_set_ >> attribute_set_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + Boolean restriction (restriction_p (c)); + + if (!(tiein || (!restriction && (he || ha)))) + return; + + String const& name (ename (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!restriction && (he || ha)) + { + // _serializer () + // + if (ha) + names (c, names_attribute_accessor_); + + if (he) + contains_compositor (c, contains_compositor_accessor_); + + // serializer () + // + + os << inl + << "void " << name << "::" << endl + << "serializers ("; + + { + SerializerParamDecl decl (*this, true); + decl.traverse (c); + } + + os << ")" + << "{"; + + inherits (c, inherits_base_set_); + + if (ha) + names (c, names_attribute_set_); + + if (he) + contains_compositor (c, contains_compositor_set_); + + os << "}"; + } + + // We have to use "real" (non-typedef) base name in base + // initializer because of some broken compilers (EVC 4.0). + // + String real_fq_base; + + if (hb && tiein) + real_fq_base = real_fq_name (c.inherits ().base ()); + + // Default c-tor. + // + os << inl + << name << "::" << endl; + + if (hb && tiein) + os << name << " (" << fq_name (c.inherits ().base ()) << + "* tiein)" << endl; + else + os << name << " ()" << endl; + + os << ": "; + + Boolean comma (false); + + if (hb && tiein) + { + os << real_fq_base << " (tiein, 0)"; + comma = true; + } + + if (tiein) + { + if (comma) + os << "," << endl << " "; + + os << etiein (c) << " (0)"; + comma = true; + } + + if (!restriction && (he || ha)) + { + if (ha) + { + AttributeMemberInit attribute_init (*this, comma); + Traversal::Names names_attribute_init; + + names_attribute_init >> attribute_init; + + names (c, names_attribute_init); + + comma = attribute_init.comma (); + } + + if (he) + { + Traversal::Compositor compositor_init; + ParticleMemberInit particle_init (*this, comma); + Traversal::ContainsCompositor contains_compositor_init; + Traversal::ContainsParticle contains_particle_init; + + contains_compositor_init >> compositor_init; + compositor_init >> contains_particle_init; + contains_particle_init >> compositor_init; + contains_particle_init >> particle_init; + + contains_compositor (c, contains_compositor_init); + } + } + + os << "{" + << "}"; + + // Tiein c-tor. + // + if (tiein) + { + os << inl + << name << "::" << endl + << name << " (" << name << "* impl, void*)" << endl + << ": "; + + if (hb) + os << real_fq_base << " (impl, 0)," << endl; + else + os << complex_base << " (impl, 0)," << endl; + + os << " " << etiein (c) << " (impl)"; + + Boolean comma (true); + + if (!restriction && (he || ha)) + { + if (ha) + { + AttributeMemberInit attribute_init (*this, comma); + Traversal::Names names_attribute_init; + + names_attribute_init >> attribute_init; + + names (c, names_attribute_init); + + comma = attribute_init.comma (); + } + + if (he) + { + Traversal::Compositor compositor_init; + ParticleMemberInit particle_init (*this, comma); + Traversal::ContainsCompositor contains_compositor_init; + Traversal::ContainsParticle contains_particle_init; + + contains_compositor_init >> compositor_init; + compositor_init >> contains_particle_init; + contains_particle_init >> compositor_init; + contains_particle_init >> particle_init; + + contains_compositor (c, contains_compositor_init); + } + } + + os << "{" + << "}"; + } + } + + private: + // + // + Traversal::Compositor compositor_accessor_; + ParticleAccessor particle_accessor_; + Traversal::ContainsCompositor contains_compositor_accessor_; + Traversal::ContainsParticle contains_particle_accessor_; + + AttributeAccessor attribute_accessor_; + Traversal::Names names_attribute_accessor_; + + // + // + BaseMemberSet base_set_; + Traversal::Inherits inherits_base_set_; + + Traversal::Compositor compositor_set_; + ParticleMemberSet particle_set_; + Traversal::ContainsCompositor contains_compositor_set_; + Traversal::ContainsParticle contains_particle_set_; + + AttributeMemberSet attribute_set_; + Traversal::Names names_attribute_set_; + }; + } + + Void + generate_serializer_inline (Context& ctx) + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (!ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + Enumeration enumeration (ctx); + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + + names >> enumeration; + names >> list; + names >> union_; + names >> complex; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/serializer-inline.hxx b/xsde/cxx/serializer/serializer-inline.hxx new file mode 100644 index 0000000..8cde76d --- /dev/null +++ b/xsde/cxx/serializer/serializer-inline.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/serializer-inline.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_SERIALIZER_INLINE_HXX +#define CXX_SERIALIZER_SERIALIZER_INLINE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_serializer_inline (Context&); + } +} + +#endif // CXX_SERIALIZER_SERIALIZER_INLINE_HXX diff --git a/xsde/cxx/serializer/serializer-source.cxx b/xsde/cxx/serializer/serializer-source.cxx new file mode 100644 index 0000000..ec30add --- /dev/null +++ b/xsde/cxx/serializer/serializer-source.cxx @@ -0,0 +1,2703 @@ +// file : xsde/cxx/serializer/serializer-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + // Override classes override pure virtual functions in the base. + // Should be in sync with definition generators below. Used in + // tiein implementation. + // + + struct CompositorCallbackOverride: Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min != 0) + { + SemanticGraph::Type& t ( + dynamic_cast (scope (c))); + + String const& impl (etiein (t)); + + if (max != 1) + { + String const& next (enext (c)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& arm (earm (c)); + + os << fq_name (t) << "::" << earm_tag (c) << " " << + scope_ << "::" << endl + << arm << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << arm << " ();" + << "}"; + } + + Traversal::Choice::traverse (c); + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (max != 1 && min != 0) + { + String const& impl ( + etiein (dynamic_cast (scope (s)))); + + String const& next (enext (s)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + + private: + String const& scope_; + }; + + struct ParticleCallbackOverride: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& impl ( + etiein (dynamic_cast (e.scope ()))); + + if (max != 1 && min != 0) + { + String const& next (enext (e)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& ret (ret_type (e.type ())); + + if (ret != L"void") + { + String const& name (ename (e)); + + os << ret << " " << scope_ << "::" << endl + << name << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << name << " ();" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min != 0 && + !a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()) + { + String const& impl ( + etiein (dynamic_cast (a.scope ()))); + + if (max != 1) + { + String const& next (enext (a)); + + os << "bool " << scope_ << "::" << endl + << next << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << next << " ();" + << "}"; + } + + String const& name (ename (a)); + + if (stl) + { + os << "void " << scope_ << "::" << endl + << name << " (::std::string& ns, ::std::string& name)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << name << " (ns, name);" + << "}"; + } + else + { + os << "void " << scope_ << "::" << endl + << name << " (const char*& ns, const char*& name, " << + "bool& free)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << name << " (ns, name, free);" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << scope_ << "::" << endl + << serialize << " ()" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->" << serialize << " ();" + << "}"; + } + } + + private: + String const& scope_; + }; + + struct AttributeCallbackOverride: Traversal::Attribute, Context + { + AttributeCallbackOverride (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& ret (ret_type (a.type ())); + + if (ret != L"void") + { + String const& impl ( + etiein (dynamic_cast (a.scope ()))); + + String const& name (ename (a)); + + os << ret << " " << scope_ << "::" << endl + << name << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << name << " ();" + << "}"; + } + } + + private: + String const& scope_; + }; + + struct BaseOverride: Traversal::Type, + Traversal::Enumeration, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Context + { + BaseOverride (Context& c, String const& scope) + : Context (c), + scope_ (scope), + compositor_callback_ (c, scope), + particle_callback_ (c, scope), + attribute_callback_ (c, scope) + { + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + // pre + // + String const& arg (arg_type (t)); + + if (arg != L"void") + { + String const& impl (etiein (t)); + + os << "void " << scope_ << "::" << endl + << "pre (" << arg << " x)" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->pre (x);" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + SemanticGraph::Type& t (e); + traverse (t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + SemanticGraph::Type& t (l); + traverse (t); + + // item + // + String const& ret (ret_type (l.argumented ().type ())); + + if (ret != L"void") + { + String item (unclash (ename (l), "item")); + String const& impl (etiein (l)); + + os << ret << " " << scope_ << "::" << endl + << item << " ()" + << "{" + << "assert (this->" << impl << ");" + << "return this->" << impl << "->" << item << " ();" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Union& u) + { + SemanticGraph::Type& t (u); + traverse (t); + + // serialize_content + // + String const& impl (etiein (u)); + + os << "void " << scope_ << "::" << endl + << "_serialize_content ()" + << "{" + << "assert (this->" << impl << ");" + << "this->" << impl << "->_serialize_content ();" + << "}"; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Type& t (c); + traverse (t); + + // Member callbacks. + // + if (!restriction_p (c)) + { + Traversal::Complex::names (c, names_attribute_callback_); + Traversal::Complex::contains_compositor ( + c, contains_compositor_callback_); + } + } + + private: + String const& scope_; + + CompositorCallbackOverride compositor_callback_; + ParticleCallbackOverride particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallbackOverride attribute_callback_; + Traversal::Names names_attribute_callback_; + }; + + // + // + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + String const& arg (arg_type (e)); + SemanticGraph::Type& base (e.inherits ().base ()); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (arg != arg_type (base) && arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (e)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (e.name ()); + + if (String ns = xml_ns_name (e)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (validation) + { + Boolean gen (!anonymous (e)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + e.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein) + { + // If our base has pure virtual functions, override them here. + // + BaseOverride t (*this, name); + t.dispatch (base); + } + } + }; + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + SemanticGraph::Type& t (l.argumented ().type ()); + + String const& ret (ret_type (t)); + String const& arg (arg_type (t)); + + String item (unclash (name, "item")); + String item_next (unclash (name, "item_next")); + String inst (L"_xsde_" + item + L"_"); + + os << "// " << name << endl + << "//" << endl + << endl; + + String impl; + + if (tiein) + impl = etiein (l); + + // pre + // + if (arg_type (l) == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + + os << "}"; + } + + // item + // + os << "bool " << name << "::" << endl + << item_next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << "->" << + item_next << " () : false;"; + else + os << "return false;"; + + os << "}"; + + if (ret == L"void") + { + os << ret << " " << name << "::" << endl + << item << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "return this->" << impl << "->" << item << " ();"; + + os << "}"; + } + + // reset + // + if (reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{" + << simple_base << "::_reset ();" + << endl + << "if (this->" << inst << ")" << endl + << "this->" << inst << "->_reset ();" + << "}"; + } + + // serialize_content + // + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{"; + + os << "bool first = true;" + << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (exceptions && !validation) + { + os << "while (this->" << item_next << " ())" + << "{" + << "if (this->" << inst << ")" + << "{"; + + if (ret == L"void") + os << "this->" << item << " ();" + << "this->" << inst << "->pre ();"; + else + os << arg << " r = this->" << item << " ();" + << "this->" << inst << "->pre (r);"; + + os << endl + << "if (!first)" << endl + << "this->_characters (\" \", 1);" + << "else" << endl + << "first = false;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_serialize_content ();" + << "this->" << inst << "->_post_impl ();" + << "this->" << inst << "->post ();"; + + os << "}" + << "}"; + } + else + { + os << "while (this->" << item_next << " ())" + << "{" + << "if (this->" << inst << ")" + << "{"; + + if (ret == L"void") + os << "this->" << item << " ();"; + else + os << arg << " r = this->" << item << " ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + if (!exceptions) + { + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "break;"; + } + + if (!exceptions) + os << endl + << "if (!first)" + << "{" + << "if (!this->_characters (\" \", 1))" << endl + << "break;" + << "}"; + else + os << endl + << "if (!first)" << endl + << "this->_characters (\" \", 1);"; + + os << "else" << endl + << "first = false;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "break;" + << endl; + + os << "this->" << inst << "->post ();"; + + if (!exceptions) + { + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "break;"; + } + + os << "}" // No check for error here since we return anyway. + << "}"; + } + + os << "}"; // _serialize_content + + // + // + if (poly_code) + { + String id (l.name ()); + + if (String ns = xml_ns_name (l)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + String const& arg (arg_type (u)); + + if (arg == L"void" || poly_code) + { + os << "// " << name << endl + << "//" << endl + << endl; + } + + if (arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (u)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + if (poly_code) + { + String id (u.name ()); + + if (String ns = xml_ns_name (u)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + } + } + }; + + // + // + struct ParticleReset: Traversal::Element, Context + { + ParticleReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + String const& m (emember (e)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + + if (poly_code && !anonymous (e.type ())) + { + String const& map (emember_map (e)); + + os << "if (this->" << map << ")" << endl + << "this->" << map << "->reset ();" + << endl; + } + } + }; + + struct AttributeReset: Traversal::Attribute, Context + { + AttributeReset (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& m (emember (a)); + + os << "if (this->" << m << ")" << endl + << "this->" << m << "->_reset ();" + << endl; + } + }; + + // Complex serialization code. + // + struct Compositor: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + Compositor (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + UnsignedLong min (a.min ()); + + if (min == 0) + os << "if (this->" << epresent (a) << " ())" + << "{"; + + Traversal::All::traverse (a); + + if (min == 0) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (c.contains_begin () != c.contains_end ()) + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (c) << " ())" + << "{"; + } + else if (max != 1) + { + os << "while (this->" << enext (c) << " ())" + << "{"; + } + else if (!exceptions) + { + os << "{"; + } + + if (exceptions) + os << "switch (this->" << earm (c) << " ())"; + else + os << earm_tag (c) << " t = this->" << earm (c) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "switch (t)"; + + + os << "{"; + + for (SemanticGraph::Choice::ContainsIterator + i (c.contains_begin ()); i != c.contains_end (); ++i) + { + os << "case " << etag (i->particle ()) << ":" + << "{"; + + edge_traverser ().dispatch (*i); + + os << "break;" + << "}"; + } + + // In case of restriction we may not handle all enumerators + // in which case default will help avoid warnings. + // + os << "default:" + << "{" + << "break;" + << "}" + << "}"; // switch + + if (min == 0 || max != 1) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + else if (!exceptions) + { + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (s) << " ())" + << "{"; + } + else if (max != 1) + { + os << "while (this->" << enext (s) << " ())" + << "{"; + } + + Traversal::Sequence::traverse (s); + + + if (min == 0 || max != 1) + { + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + } + }; + + struct Particle: Traversal::Element, + Traversal::Any, + Context + { + Particle (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + UnsignedLong min (e.min ()), max (e.max ()); + + String const& name (ename (e)); + + os << "// " << name << endl + << "//" << endl; + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (e) << " ())"; + } + else if (max != 1) + { + os << "while (this->" << enext (e) << " ())"; + } + + os << "{"; + + String const& ret (ret_type (e.type ())); + String const& arg (arg_type (e.type ())); + String fq_type (fq_name (e.type ())); + + Boolean poly (poly_code && !anonymous (e.type ())); + String inst (poly ? String (L"s") : L"this->" + emember (e)); + + if (poly) + os << "ctx.type_id (0);"; + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (poly) + { + // In case of mixin we use virtual inheritance and only + // dynamic_cast can be used. + // + String cast (mixin ? L"dynamic_cast" : L"static_cast"); + + os << "const void* t = ctx.type_id ();" + << fq_type << "* " << inst << " = 0;" + << endl + << "if (t == 0 && this->" << emember (e) << " != 0)" << endl + << inst << " = this->" << emember (e) << ";" + << "else if (this->" << emember_map (e) << " != 0)" << endl + << inst << " = " << cast << "< " << fq_type << "* > (" << endl + << "this->" << emember_map (e) << "->find (t));" + << endl; + } + + os << "if (" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret == L"void") + os << inst << "->pre ();"; + else + os << inst << "->pre (r);"; + + if (poly) + { + os << endl + << "const char* dt = 0;" + << "if (t != 0)" + << "{" + << "dt = " << inst << "->_dynamic_type ();" + << "if (strcmp (dt, " << fq_type << + "::_static_type ()) == 0)" << endl + << "dt = 0;" + << "}"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (poly && e.global ()) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "const char* ns = " << + strlit (e.namespace_ ().name ()) << ";"; + else + os << "const char* ns = 0;"; + + os << "const char* n = " << strlit (e.name ()) << ";" + << endl; + + os << "if (dt != 0 && " << + "::xsde::cxx::serializer::substitution_map_instance ()" << + ".check (ns, n, dt))" << endl + << "dt = 0;" + << endl; + + os << "if (ns != 0)" << endl + << "this->_start_element (ns, n);" + << "else" << endl + << "this->_start_element (n);"; + } + else + { + if (e.qualified () && e.namespace_ ().name ()) + os << "this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << ");"; + else + os << "this->_start_element (" << strlit (e.name ()) << ");"; + } + + if (poly) + { + // Set xsi:type if necessary. + // + os << endl + << "if (dt != 0)" << endl + << "this->_set_type (dt);" + << endl; + } + + os << inst << "->_pre_impl (ctx);" + << inst << "->_serialize_attributes ();" + << inst << "->_serialize_content ();" + << inst << "->_post_impl ();" + << "this->_end_element ();" + << inst << "->post ();"; + } + else + { + if (ret == L"void") + os << inst << "->pre ();"; + else + os << inst << "->pre (r);"; + + // Note that after pre() we need to check both the serializer + // and context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (poly) + { + os << "const char* dt = 0;" + << "if (t != 0)" + << "{" + << "dt = " << inst << "->_dynamic_type ();" + << "if (strcmp (dt, " << fq_type << + "::_static_type ()) == 0)" << endl + << "dt = 0;" + << "}"; + } + + // Only a globally-defined element can be a subst-group root. + // + if (poly && e.global ()) + { + if (e.qualified () && e.namespace_ ().name ()) + os << "const char* ns = " << + strlit (e.namespace_ ().name ()) << ";"; + else + os << "const char* ns = 0;"; + + os << "const char* n = " << strlit (e.name ()) << ";" + << endl; + + os << "if (dt != 0 && " << + "::xsde::cxx::serializer::substitution_map_instance ()" << + ".check (ns, n, dt))" << endl + << "dt = 0;" + << endl; + + os << "if (ns != 0)" + << "{" + << "if (!this->_start_element (ns, n))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_element (n))" << endl + << "return;" + << "}"; + } + else + { + if (e.qualified () && e.namespace_ ().name ()) + os << "if (!this->_start_element (" << + strlit (e.namespace_ ().name ()) << ", " << + strlit (e.name ()) << "))" << endl + << "return;" + << endl; + else + os << "if (!this->_start_element (" << + strlit (e.name ()) << "))" << endl + << "return;" + << endl; + } + + if (poly) + { + // Set xsi:type if necessary. + // + os << "if (dt != 0)" + << "{" + << "if (!this->_set_type (dt))" << endl + << "return;" + << "}"; + } + + os << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_attributes ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (!this->_end_element ())" << endl + << "return;" + << endl; + + os << inst << "->post ();"; + + // Note that after post() we need to check both the serializer + // and context error states because of the recursive parsing. + // + os << endl + << "if (" << inst << "->_error_type ())" << endl + << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;"; + } + + os << "}" // if (inst) + << "}"; + + if ((min == 0 || max != 1) && !exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 && max == 1) + { + os << "if (this->" << epresent (a) << " ())"; + + } + else if (max != 1) + { + os << "while (this->" << enext (a) << " ())"; + } + + os << "{"; + + if (stl) + { + os << "::std::string ns, name;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ns.empty ())" << endl + << "this->_start_element (name.c_str ());" + << "else" << endl + << "this->_start_element (ns.c_str (), name.c_str ());" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_element ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (ns.empty ())" + << "{" + << "if (!this->_start_element (name.c_str ()))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_element (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;" + << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_element ())" << endl + << "return;"; + } + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}" + << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_element (name);" + << "else" << endl + << "this->_start_element (ns, name);" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_element ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_element (name);" + << "else" << endl + << "r = this->_start_element (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_element ())" << endl + << "return;"; + } + } + + os << "}"; + + if (!exceptions && (min == 0 || max != 1)) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + }; + + struct Attribute: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& name (ename (a)); + + os << "// " << name << endl + << "//" << endl; + + if (a.optional ()) + { + os << "if (this->" << epresent (a) << " ())"; + } + + os << "{"; + + String const& inst (emember (a)); + String const& ret (ret_type (a.type ())); + String const& arg (arg_type (a.type ())); + + if (ret == L"void") + os << "this->" << name << " ();" + << endl; + else + os << arg << " r = this->" << name << " ();" + << endl; + + if (!exceptions) + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (this->" << inst << ")" + << "{"; + + if (exceptions) + { + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + if (a.qualified () && a.namespace_ ().name ()) + os << "this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << ");"; + else + os << "this->_start_attribute (" << strlit (a.name ()) << ");"; + + os << "this->" << inst << "->_pre_impl (ctx);" + << "this->" << inst << "->_serialize_content ();" + << "this->" << inst << "->_post_impl ();" + << "this->_end_attribute ();" + << "this->" << inst << "->post ();"; + } + else + { + if (ret == L"void") + os << "this->" << inst << "->pre ();"; + else + os << "this->" << inst << "->pre (r);"; + + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + if (a.qualified () && a.namespace_ ().name ()) + os << "if (!this->_start_attribute (" << + strlit (a.namespace_ ().name ()) << ", " << + strlit (a.name ()) << "))" << endl + << "return;" + << endl; + else + os << "if (!this->_start_attribute (" << + strlit (a.name ()) << "))" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_pre_impl (ctx);"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_serialize_content ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->_post_impl ();"; + + os << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl; + + os << "if (!this->_end_attribute ())" << endl + << "return;" + << endl; + + os << "this->" << inst << "->post ();"; + + os << endl + << "if (this->" << inst << "->_error_type ())" << endl + << "this->" << inst << "->_copy_error (ctx);" + << endl; + + os << "if (ctx.error_type ())" << endl + << "return;"; + } + + os << "}" // if (inst) + << "}"; + + if (a.optional () && !exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << "while (this->" << enext (a) << " ())" + << "{"; + + if (stl) + { + os << "::std::string ns, name;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ns.empty ())" << endl + << "this->_start_attribute (name.c_str ());" + << "else" << endl + << "this->_start_attribute (ns.c_str (), name.c_str ());" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_attribute ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (ns.empty ())" + << "{" + << "if (!this->_start_attribute (name.c_str ()))" << endl + << "return;" + << "}" + << "else" + << "{" + << "if (!this->_start_attribute (ns.c_str (), " << + "name.c_str ()))" << endl + << "return;" + << "}" + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_attribute ())" << endl + << "return;"; + } + } + else + { + os << "const char* ns = 0;" + << "const char* name;" + << "bool free;"; + + if (exceptions) + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "::xsde::cxx::string auto_ns, auto_name;" + << "if (free)" + << "{" + << "auto_ns.attach (const_cast< char* > (ns));" + << "auto_name.attach (const_cast< char* > (name));" + << "}" + << "if (ns == 0 || *ns == '\\0')" << endl + << "this->_start_attribute (name);" + << "else" << endl + << "this->_start_attribute (ns, name);" + << endl + << "this->" << eserialize (a) << " ();" + << "this->_end_attribute ();"; + } + else + { + os << "this->" << ename (a) << " (ns, name, free);" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "bool r;" + << "if (ns == 0 || *ns == '\\0')" << endl + << "r = this->_start_attribute (name);" + << "else" << endl + << "r = this->_start_attribute (ns, name);" + << endl + << "if (free)" + << "{" + << "delete[] ns;" + << "delete[] name;" + << "}" + << "if (!r)" << endl + << "return;" + << endl + << "this->" << eserialize (a) << " ();" + << endl + << "if (ctx.error_type ())" << endl + << "return;" + << endl + << "if (!this->_end_attribute ())" << endl + << "return;"; + } + } + + os << "}"; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + }; + + // Callbacks. + // + struct CompositorCallback: Traversal::All, + Traversal::Choice, + Traversal::Sequence, + Context + { + CompositorCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::All& a) + { + if (!a.context ().count ("xsd-frontend-restriction-correspondence")) + { + // For the all compositor, maxOccurs=1 and minOccurs={0,1}. + // + if (a.min () == 0) + { + SemanticGraph::Scope& s (scope (a)); + String const& present (epresent (a)); + + os << "bool " << ename (s) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (s))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + } + else + os << "return false;"; + + os << "}"; + } + } + + Traversal::All::traverse (a); + } + + virtual Void + traverse (SemanticGraph::Choice& c) + { + if (SemanticGraph::Compositor* b = correspondent (c)) + { + UnsignedLong smin (c.min ()); + UnsignedLong bmax (b->max ()); + + if (bmax != 1 && smin == 0) + { + String const& next (enext (c)); + String const& present (epresent (c)); + + SemanticGraph::Scope& scope (this->scope (c)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (scope))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (c.min ()), max (c.max ()); + + if (min == 0) + { + SemanticGraph::Scope& scope (this->scope (c)); + String const& s (ename (scope)); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast (scope)); + + if (max == 1) + { + String const& present (epresent (c)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (c)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + String const& arm (earm (c)); + String const& tag (etag (c.contains_begin ()->particle ())); + + os << s << "::" << earm_tag (c) << " " << s << "::" << endl + << arm << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << arm << " () : " << tag << ";"; + else + os << "return " << tag << ";"; + + os << "}"; + } + } + + Traversal::Choice::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Sequence& s) + { + if (SemanticGraph::Compositor* b = correspondent (s)) + { + UnsignedLong smin (s.min ()); + UnsignedLong bmax (b->max ()); + + if (bmax != 1 && smin == 0) + { + String const& next (enext (s)); + String const& present (epresent (s)); + + SemanticGraph::Scope& scope (this->scope (s)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (scope))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (s.min ()), max (s.max ()); + + if (min == 0) + { + SemanticGraph::Scope& scope (this->scope (s)); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast (scope)); + + if (max == 1) + { + String const& present (epresent (s)); + + os << "bool " << ename (scope) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (s)); + + os << "bool " << ename (scope) << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + } + } + + Traversal::Sequence::traverse (s); + } + + private: + SemanticGraph::Scope& + scope (SemanticGraph::Compositor& c) + { + SemanticGraph::Compositor* root (&c); + + while (root->contained_particle_p ()) + root = &root->contained_particle ().compositor (); + + return dynamic_cast ( + root->contained_compositor ().container ()); + } + }; + + struct ParticleCallback: Traversal::Element, + Traversal::Any, + Context + { + ParticleCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (SemanticGraph::Element* b = correspondent (e)) + { + if (b->max () != 1 && e.min () == 0) + { + String const& next (enext (e)); + String const& present (epresent (e)); + + os << "bool " << ename (e.scope ()) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (e.scope ()))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (e.min ()), max (e.max ()); + String const& s (ename (e.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast (e.scope ())); + + if (min == 0) + { + if (max == 1) + { + String const& present (epresent (e)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else + { + String const& next (enext (e)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + } + + // The callback is non-pure-virtual only if the return type + // is void. + // + if (ret_type (e.type ()) == L"void") + { + String const& name (ename (e)); + + os << "void " << s << "::" << endl + << name << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " ();"; + + os << "}"; + } + } + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (SemanticGraph::Any* b = correspondent (a)) + { + if (b->max () != 1 && a.min () == 0) + { + String const& next (enext (a)); + String const& present (epresent (a)); + + os << "bool " << ename (a.scope ()) << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + { + String const& impl ( + etiein (dynamic_cast (a.scope ()))); + + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : this->" << next << " ();"; + } + else + os << "return this->" << next << " ();"; + + os << "}"; + } + } + else + { + UnsignedLong min (a.min ()), max (a.max ()); + + if (min == 0 || + a.contained_particle ().compositor ().is_a< + SemanticGraph::Choice> ()) + { + String const& s (ename (a.scope ())); + String impl; + + if (tiein) + impl = etiein (dynamic_cast (a.scope ())); + + if (min == 0 && max == 1) + { + String const& present (epresent (a)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + else if (max != 1) + { + String const& next (enext (a)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + String const& name (ename (a)); + + if (stl) + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (::std::string& ns, ::std::string& n)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n);" + << "}"; + + else + os << "void " << s << "::" << endl + << name << " (::std::string&, ::std::string&)" + << "{" + << "}"; + } + else + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (const char*& ns, const char*& n, bool& f)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n, f);" + << "}"; + else + os << "void " << s << "::" << endl + << name << " (const char*&, const char*&, bool&)" + << "{" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << s << "::" << endl + << serialize << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << serialize << " ();"; + + os << "}"; + } + } + + } + }; + + struct AttributeCallback: Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + AttributeCallback (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& s (ename (a.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast (a.scope ())); + + if (a.optional ()) + { + String const& present (epresent (a)); + + os << "bool " << s << "::" << endl + << present << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << present << " () : false;"; + else + os << "return false;"; + + os << "}"; + } + + // The callback is non-pure-virtual only if the return type + // is void. + // + if (ret_type (a.type ()) == L"void") + { + String const& name (ename (a)); + + os << "void " << s << "::" << endl + << name << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " ();"; + + os << "}"; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& s (ename (a.scope ())); + + String impl; + + if (tiein) + impl = etiein (dynamic_cast (a.scope ())); + + String const& next (enext (a)); + + os << "bool " << s << "::" << endl + << next << " ()" + << "{"; + + if (tiein) + os << "return this->" << impl << " ? this->" << impl << + "->" << next << " () : false;"; + else + os << "return false;"; + + os << "}"; + + String const& name (ename (a)); + + if (stl) + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (::std::string& ns, ::std::string& n)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n);" + << "}"; + + else + os << "void " << s << "::" << endl + << name << " (::std::string&, ::std::string&)" + << "{" + << "}"; + } + else + { + if (tiein) + os << "void " << s << "::" << endl + << name << " (const char*& ns, const char*& n, bool& f)" + << "{" + << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << name << " (ns, n, f);" + << "}"; + else + os << "void " << s << "::" << endl + << name << " (const char*&, const char*&, bool&)" + << "{" + << "}"; + } + + String const& serialize (eserialize (a)); + + os << "void " << s << "::" << endl + << serialize << " ()" + << "{"; + + if (tiein) + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->" << serialize << " ();"; + + os << "}"; + } + }; + + // + // + struct Complex : Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + compositor_callback_ (c), + particle_callback_ (c), + attribute_callback_ (c), + particle_reset_ (c), + attribute_reset_ (c), + compositor_ (c), + particle_ (c), + attribute_ (c) + { + // Callback. + // + contains_compositor_callback_ >> compositor_callback_; + compositor_callback_ >> contains_particle_callback_; + contains_particle_callback_ >> compositor_callback_; + contains_particle_callback_ >> particle_callback_; + + names_attribute_callback_ >> attribute_callback_; + + // Reset. + // + contains_compositor_reset_ >> compositor_reset_; + compositor_reset_ >> contains_particle_reset_; + contains_particle_reset_ >> compositor_reset_; + contains_particle_reset_ >> particle_reset_; + + names_attribute_reset_ >> attribute_reset_; + + // Serialization code. + // + contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> particle_; + + names_attribute_ >> attribute_; + } + + virtual Void + traverse (Type& c) + { + Boolean hb (c.inherits_p ()); + Boolean he (has (c)); + Boolean ha (has (c)); + + Boolean hae (has_particle (c)); + Boolean haa (has (c)); + + String const& arg (arg_type (c)); + Boolean same (hb && arg == arg_type (c.inherits ().base ())); + + String const& name (ename (c)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // pre + // + if (!same && arg == L"void") + { + os << "void " << name << "::" << endl + << "pre ()" + << "{"; + + if (tiein) + { + String const& impl (etiein (c)); + + os << "if (this->" << impl << ")" << endl + << "this->" << impl << "->pre ();"; + } + + os << "}"; + } + + // Member callbacks. + // + if (!restriction_p (c)) + { + if (ha || haa) + names (c, names_attribute_callback_); + } + + if (he || hae) + contains_compositor (c, contains_compositor_callback_); + + // reset + // + if (!restriction_p (c) && (he || ha) && reset) + { + os << "void " << name << "::" << endl + << "_reset ()" + << "{"; + + // Avoid recursion in case of recursive parsing. + // + if (he) + os << "if (this->resetting_)" << endl + << "return;" + << endl; + + // Reset the base. We cannot use the fully-qualified base name + // directly because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef "; + + if (hb) + os << fq_name (c.inherits ().base ()); + else + os << complex_base; + + os << " " << base << ";" + << base << "::_reset ();" + << endl; + + // Reset member serializer. + // + + if (ha) + names (c, names_attribute_reset_); + + if (he) + { + os << "this->resetting_ = true;" + << endl; + + contains_compositor (c, contains_compositor_reset_); + + os << "this->resetting_ = false;" + << endl; + } + + os << "}"; + } + + // + // + if (poly_code) + { + String id (c.name ()); + + if (String ns = xml_ns_name (c)) + { + id += L' '; + id += ns; + } + + os << "const char* " << name << "::" << endl + << "_static_type ()" + << "{" + << "return " << strlit (id) << ";" + << "}"; + + os << "const char* " << name << "::" << endl + << "_dynamic_type () const" + << "{" + << "return _static_type ();" + << "}"; + + if (hb && validation) + { + Boolean gen (!anonymous (c)); + + // We normally don't need to enter anonymous types into + // the inheritance map. The only exception is when an + // anonymous types is defined inside an element that + // is a member of a substitution group. + // + if (!gen) + { + // The first instance that this anonymous type classifies + // is the prototype for others if any. + // + SemanticGraph::Instance& i ( + c.classifies_begin ()->instance ()); + + if (SemanticGraph::Element* e = + dynamic_cast (&i)) + { + if (e->substitutes_p ()) + gen = true; + } + } + + if (gen) + { + SemanticGraph::Type& base (c.inherits ().base ()); + + os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_entry" << endl + << "_xsde_" << name << "_inheritance_map_entry_ (" << endl + << name << "::_static_type ()," << endl + << fq_name (base) << "::_static_type ());" + << endl; + } + } + } + + if (tiein && hb) + { + // If our base has pure virtual functions, override them here. + // + BaseOverride t (*this, name); + t.dispatch (c.inherits ().base ()); + } + + // If we are validating, the rest is generated elsewere. + // + if (validation) + return; + + // Don't use restriction_p here since we don't want special + // treatment of anyType. + // + Boolean restriction ( + hb && c.inherits ().is_a ()); + + // _serialize_attributes + // + if (ha || haa) + { + os << "void " << name << "::" << endl + << "_serialize_attributes ()" + << "{"; + + // We need context for wildcards only if we are using error + // codes. + // + if (ha || !exceptions) + os << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (hb && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_attributes ();" + << endl; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + names (c, names_attribute_); + + os << "}"; + } + + // _serialize_content + // + if (he || hae) + { + os << "void " << name << "::" << endl + << "_serialize_content ()" + << "{"; + + // We need context for wildcards only if we are using error + // codes. + // + if (he || !exceptions) + os << "::xsde::cxx::serializer::context& ctx = this->_context ();" + << endl; + + if (hb && !restriction) + { + // We cannot use the fully-qualified base name directly + // because of some broken compilers (EVC 4.0). + // + String base (unclash (name, "base")); + + os << "typedef " << fq_name (c.inherits ().base ()) << " " << + base << ";" + << base << "::_serialize_content ();" + << endl; + + if (!exceptions) + { + os << "if (ctx.error_type ())" << endl + << "return;" + << endl; + } + } + + contains_compositor (c, contains_compositor_); + + os << "}"; + } + } + + private: + // + // + CompositorCallback compositor_callback_; + ParticleCallback particle_callback_; + Traversal::ContainsCompositor contains_compositor_callback_; + Traversal::ContainsParticle contains_particle_callback_; + + AttributeCallback attribute_callback_; + Traversal::Names names_attribute_callback_; + + // + // + Traversal::Compositor compositor_reset_; + ParticleReset particle_reset_; + Traversal::ContainsCompositor contains_compositor_reset_; + Traversal::ContainsParticle contains_particle_reset_; + + AttributeReset attribute_reset_; + Traversal::Names names_attribute_reset_; + + // + // + Compositor compositor_; + Particle particle_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + Attribute attribute_; + Traversal::Names names_attribute_; + }; + + + // Generate substitution group map entries. + // + struct GlobalElement: Traversal::Element, Context + { + GlobalElement (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (e.substitutes_p ()) + { + String name (escape (e.name ())); + Type& r (e.substitutes ().root ()); + + SemanticGraph::Type& type (e.type ()); + + String r_id (r.name ()); + + if (String const& ns = r.namespace_ ().name ()) + { + r_id += L' '; + r_id += ns; + } + + os << "// Substitution map entry for " << comment (e.name ()) << + "." << endl + << "//" << endl + << "static" << endl + << "const ::xsde::cxx::serializer::substitution_map_entry" << endl + << "_xsde_" << name << "_substitution_map_entry_ (" << endl + << strlit (r_id) << "," << endl; + + if (String const& ns = e.namespace_ ().name ()) + os << strlit (ns) << "," << endl; + else + os << "0," << endl; + + os << strlit (e.name ()) << "," << endl + << fq_name (type) << "::_static_type ());" + << endl; + } + } + }; + } + + Void + generate_serializer_source (Context& ctx) + { + if (ctx.tiein) + ctx.os << "#include " << endl + << endl; + + if (ctx.poly_code) + { + ctx.os << "#include " << endl + << "#include " << endl; + + if (ctx.validation) + ctx.os << "#include " << endl + << endl; + else + ctx.os << endl; + + ctx.os << "static" << endl + << "const ::xsde::cxx::serializer::substitution_map_init" << endl + << "_xsde_substitution_map_init_;" + << endl; + + if (ctx.validation) + { + ctx.os << "static" << endl + << "const ::xsde::cxx::serializer::validating::" << + "inheritance_map_init" << endl + << "_xsde_inheritance_map_init_;" + << endl; + } + } + + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + if (ctx.options.value ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names schema_names; + + Namespace ns (ctx); + Traversal::Names names; + + schema >> sources >> schema; + schema >> schema_names >> ns >> names; + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement global_element (ctx); + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.poly_code) + names >> global_element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsde/cxx/serializer/serializer-source.hxx b/xsde/cxx/serializer/serializer-source.hxx new file mode 100644 index 0000000..6b1353e --- /dev/null +++ b/xsde/cxx/serializer/serializer-source.hxx @@ -0,0 +1,22 @@ +// file : xsde/cxx/serializer/serializer-source.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_SERIALIZER_SOURCE_HXX +#define CXX_SERIALIZER_SERIALIZER_SOURCE_HXX + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + Void + generate_serializer_source (Context&); + } +} + +#endif // CXX_SERIALIZER_SERIALIZER_SOURCE_HXX diff --git a/xsde/cxx/serializer/type-processor.cxx b/xsde/cxx/serializer/type-processor.cxx new file mode 100644 index 0000000..6854e2c --- /dev/null +++ b/xsde/cxx/serializer/type-processor.cxx @@ -0,0 +1,356 @@ +// file : xsde/cxx/serializer/type-processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include +#include + +namespace CXX +{ + namespace Serializer + { + namespace + { + // + // + struct Type: Traversal::Type + { + Type (SemanticGraph::Schema& schema, + TypeMap::Namespaces& type_map, + Boolean add_includes) + : schema_ (schema), + type_map_ (type_map), + add_includes_ (add_includes) + { + } + + virtual Void + traverse (SemanticGraph::Type& type) + { + using TypeMap::Namespace; + using TypeMap::Namespaces; + + SemanticGraph::Context& tc (type.context ()); + + // There are two situations where we may try to process the + // same type more than once. The first is when the type is + // used in several element declarations in the same schema. + // The second situation only occurs when we are in the file- + // per-type mode. In this case the type was processed as part + // of another root schema. In the second case, while the ret + // and arg types are assumed to be the same, we need to re- + // match the type in order to add include directives to the + // new root schema. + // + Boolean set (true); + + if (tc.count ("s:ret-type")) + { + SemanticGraph::Schema* s ( + tc.get ("s:root-schema")); + + if (&schema_ == s) + return; + + set = false; + } + + SemanticGraph::Namespace& ns ( + dynamic_cast (type.scope ())); + + String ns_name (ns.name ()); + String t_name (type.name ()); + + // std::wcerr << "traversing: " << ns_name << "#" << t_name << endl; + + for (Namespaces::ConstIterator n (type_map_.begin ()); + n != type_map_.end (); ++n) + { + // Check if the namespace matches. + // + //@@ Should probably store precompiled regex somewhere + // instead of doing it every time. + // + boost::basic_regex ns_expr; + + Boolean ns_match; + + if (!n->xsd_name ().empty ()) + { + ns_match = n->xsd_name ().match (ns_name); + } + else + ns_match = ns_name.empty (); + + // std::wcerr << "considering ns expr: " << n->xsd_name () << endl; + + if (ns_match) + { + // Namespace matched. See if there is a type that matches. + // + for (Namespace::TypesIterator t (n->types_begin ()); + t != n->types_end (); ++t) + { + if (t->xsd_name ().match (t_name)) + { + if (set) + { + // Got a match. See if the namespace has the C++ + // namespace mapping. + // + String cxx_ns; + + if (n->has_cxx_name ()) + { + if (!n->xsd_name ().empty ()) + { + cxx_ns = n->xsd_name ().merge ( + n->cxx_name (), ns_name, true); + } + else + cxx_ns = n->cxx_name (); + + cxx_ns += L"::"; + } + + // Figure out ret and arg type names. + // + String ret_type (cxx_ns); + + ret_type += t->xsd_name ().merge ( + t->cxx_ret_name (), t_name, true); + + String arg_type; + + if (t->cxx_arg_name ()) + { + arg_type = cxx_ns; + arg_type += t->xsd_name ().merge ( + t->cxx_arg_name (), t_name, true); + } + else + { + if (ret_type == L"void") + arg_type = ret_type; + else + { + WideChar last (ret_type[ret_type.size () - 1]); + + // If it is already a pointer or reference then use + // it as is. + // + if (last == L'*' || last == L'&') + arg_type = ret_type; + else + arg_type = L"const " + ret_type + L"&"; + } + } + + tc.set ("s:ret-type", ret_type); + tc.set ("s:arg-type", arg_type); + } + + tc.set ("s:root-schema", &schema_); + + //std::wcerr << t_name << " -> " << ret_type << endl; + + // See of we need to add any includes to the translations + // unit. + // + if (add_includes_) + { + if (n->includes_begin () != n->includes_end ()) + { + typedef Cult::Containers::Set Includes; + + SemanticGraph::Context& sc (schema_.context ()); + + if (!sc.count ("s:includes")) + sc.set ("s:includes", Includes ()); + + Includes& is (sc.get ("s:includes")); + + for (Namespace::IncludesIterator i (n->includes_begin ()); + i != n->includes_end (); ++i) + { + is.insert (*i); + } + } + } + + return; + } + } + } + } + } + + private: + SemanticGraph::Schema& schema_; + TypeMap::Namespaces& type_map_; + Boolean add_includes_; + }; + + // + // + struct BaseType: Traversal::Complex + { + virtual Void + traverse (SemanticGraph::Complex& c) + { + Complex::names (c); + } + }; + + // + // + struct GlobalType: Traversal::Type, + Traversal::List, + Traversal::Complex, + Traversal::Enumeration + { + GlobalType (SemanticGraph::Schema& schema, + TypeMap::Namespaces& type_map, + Boolean add_includes, + Boolean tiein) + : type_ (schema, type_map, add_includes) + { + inherits_ >> type_; + names_ >> instance_ >> belongs_ >> type_; + argumented_ >> type_; + + if (tiein) + { + // In case of a tiein support, we also need to process base's + // members to assign ret/arg types. + // + inherits_base_ >> base_type_ >> names_; + } + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + type_.traverse (t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + type_.traverse (l); + Traversal::List::argumented (l, argumented_); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + type_.traverse (c); + Complex::inherits (c, inherits_); + Complex::inherits (c, inherits_base_); + Complex::names (c, names_); + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + type_.traverse (e); + Complex::inherits (e, inherits_); + } + + private: + Serializer::Type type_; + BaseType base_type_; + Traversal::Names names_; + Traversal::Instance instance_; + Traversal::Inherits inherits_; + Traversal::Inherits inherits_base_; + Traversal::Belongs belongs_; + Traversal::Argumented argumented_; + }; + + Void + process_impl (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema& tu, + TypeMap::Namespaces& type_map) + { + Boolean tiein (!options.value () && + !options.value ()); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalType global_type (tu, type_map, true, tiein); + + schema >> schema_names >> ns >> ns_names >> global_type; + + schema.dispatch (tu); + } + else + { + // If --extern-xml-schema is specified, then we don't want + // includes from the XML Schema type map. + // + Boolean extern_xml_schema ( + options.value ()); + + // Besides types defined in this schema, also process those + // referenced by global elements in case we are generating + // something for them. + // + Traversal::Schema schema; + Traversal::Schema xs_schema; + Traversal::Sources sources; + Traversal::Implies implies; + + schema >> sources >> schema; + schema >> implies >> xs_schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Traversal::Element global_element; + GlobalType global_type (tu, type_map, true, tiein); + + schema >> schema_names >> ns >> ns_names; + + ns_names >> global_element; + ns_names >> global_type; + + Traversal::Belongs element_belongs; + global_element >> element_belongs >> global_type; + + Traversal::Names xs_schema_names; + Traversal::Namespace xs_ns; + Traversal::Names xs_ns_names; + GlobalType xs_global_type (tu, type_map, !extern_xml_schema, tiein); + + xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >> + xs_global_type; + + schema.dispatch (tu); + } + } + } + + Void TypeProcessor:: + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema& s, + TypeMap::Namespaces& tm) + { + process_impl (options, s, tm); + } + } +} diff --git a/xsde/cxx/serializer/type-processor.hxx b/xsde/cxx/serializer/type-processor.hxx new file mode 100644 index 0000000..8408a4e --- /dev/null +++ b/xsde/cxx/serializer/type-processor.hxx @@ -0,0 +1,34 @@ +// file : xsde/cxx/serializer/type-processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_TYPE_PROCESSOR_HXX +#define CXX_SERIALIZER_TYPE_PROCESSOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + using namespace Cult::Types; + + class TypeProcessor + { + public: + Void + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + TypeMap::Namespaces&); + }; + } +} + +#endif // CXX_SERIALIZER_TYPE_PROCESSOR_HXX diff --git a/xsde/cxx/serializer/validator.cxx b/xsde/cxx/serializer/validator.cxx new file mode 100644 index 0000000..d9cc724 --- /dev/null +++ b/xsde/cxx/serializer/validator.cxx @@ -0,0 +1,501 @@ +// file : xsde/cxx/serializer/validator.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +#include + +#include + +using std::wcerr; + +namespace CXX +{ + namespace Serializer + { + namespace + { + class ValidationContext: public Context + { + public: + ValidationContext (SemanticGraph::Schema& root, + CLI::Options const& options, + const WarningSet& disabled_warnings, + Boolean& valid_) + : Context (std::wcerr, root, options, 0, 0, 0), + disabled_warnings_ (disabled_warnings), + disabled_warnings_all_ (false), + valid (valid_), + subst_group_warning_issued (subst_group_warning_issued_), + subst_group_warning_issued_ (false) + { + } + + public: + Boolean + is_disabled (Char const* w) + { + return disabled_warnings_all_ || + disabled_warnings_.find (w) != disabled_warnings_.end (); + } + + public: + String + xpath (SemanticGraph::Nameable& n) + { + if (n.is_a ()) + return L""; // There is a bug if you see this. + + assert (n.named ()); + + SemanticGraph::Scope& scope (n.scope ()); + + if (scope.is_a ()) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + + protected: + ValidationContext (ValidationContext& c) + : Context (c), + disabled_warnings_ (c.disabled_warnings_), + disabled_warnings_all_ (c.disabled_warnings_all_), + valid (c.valid), + subst_group_warning_issued (c.subst_group_warning_issued) + { + } + + protected: + const WarningSet& disabled_warnings_; + Boolean disabled_warnings_all_; + Boolean& valid; + Boolean& subst_group_warning_issued; + Boolean subst_group_warning_issued_; + }; + + // + // + struct Traverser : Traversal::Schema, + Traversal::Complex, + Traversal::Type, + Traversal::Element, + ValidationContext + { + Traverser (ValidationContext& c) + : ValidationContext (c) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Schema; + + traverse (static_cast (c)); + + if (c.inherits_p ()) + { + SemanticGraph::Type& t (c.inherits ().base ()); + + if (t.named () && + types_.find ( + t.scope ().name () + L"#" + t.name ()) == types_.end ()) + { + // Don't worry about types that are in included/imported + // schemas. + // + Schema& s (dynamic_cast (t.scope ().scope ())); + + if (&s == &schema_root || sources_p (schema_root, s)) + { + valid = false; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": error: type '" << xpath (c) << "' inherits from " + << "yet undefined type '" << xpath (t) << "'" << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": info: '" << xpath (t) << "' is defined here" + << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: inheritance from a yet-undefined type is " + << "not supported" << endl; + + wcerr << c.file () << ":" << c.line () << ":" << c.column () + << ": info: re-arrange your schema and try again" + << endl; + } + } + } + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (t.named ()) + { + types_.insert (t.scope ().name () + L"#" + t.name ()); + } + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (is_disabled ("S001")) + return; + + if (e.substitutes_p () && + !options.value () && + !subst_group_warning_issued) + { + subst_group_warning_issued = true; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": warning S001: substitution groups are used but " + << "--generate-polymorphic was not specified" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: generated code may not be able to serialize " + << "some conforming instances" << endl; + } + } + + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + }; + + // + // + struct AnonymousMember: protected ValidationContext + { + AnonymousMember (ValidationContext& c, Boolean& error_issued) + : ValidationContext (c), error_issued_ (error_issued) + { + } + + Boolean + traverse_common (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named () + && !t.is_a () + && !t.is_a ()) + { + if (!error_issued_) + { + valid = false; + error_issued_ = true; + + wcerr << t.file () + << ": error: anonymous types detected" + << endl; + + wcerr << t.file () + << ": info: " + << "anonymous types are not supported in this mapping" + << endl; + + wcerr << t.file () + << ": info: consider explicitly naming these types or " + << "remove the --preserve-anonymous option to " + << "automatically name them" + << endl; + + if (!options.value ()) + wcerr << t.file () + << ": info: use --show-anonymous option to see these " + << "types" << endl; + } + + return true; + } + + return false; + } + + private: + Boolean& error_issued_; + }; + + struct AnonymousElement: Traversal::Element, + AnonymousMember + { + AnonymousElement (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (traverse_common (e)) + { + if (options.value ()) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: element '" << xpath (e) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Element::traverse (e); + } + }; + + struct AnonymousAttribute: Traversal::Attribute, + AnonymousMember + { + AnonymousAttribute (ValidationContext& c, Boolean& error_issued) + : AnonymousMember (c, error_issued) + { + } + + virtual Void + traverse (Type& a) + { + if (traverse_common (a)) + { + if (options.value ()) + { + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: attribute '" << xpath (a) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Attribute::traverse (a); + } + }; + + struct AnonymousType : Traversal::Schema, + Traversal::Complex, + ValidationContext + { + AnonymousType (ValidationContext& c) + : ValidationContext (c), + error_issued_ (false), + element_ (c, error_issued_), + attribute_ (c, error_issued_) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + + *this >> contains_compositor_ >> compositor_; + compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> element_; + + *this >> names_attribute_ >> attribute_; + } + + private: + Boolean error_issued_; + + Containers::Set types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + Traversal::Names names_; + + Traversal::Compositor compositor_; + AnonymousElement element_; + Traversal::ContainsCompositor contains_compositor_; + Traversal::ContainsParticle contains_particle_; + + AnonymousAttribute attribute_; + Traversal::Names names_attribute_; + }; + + struct GlobalElement: Traversal::Element, ValidationContext + { + GlobalElement (ValidationContext& c, SemanticGraph::Element*& element) + : ValidationContext (c), element_ (element) + { + } + + virtual Void + traverse (Type& e) + { + if (!valid) + return; + + if (options.value ()) + { + if (element_ == 0) + element_ = &e; + } + else if (options.value ()) + { + element_ = &e; + } + else if (String name = options.value ()) + { + if (e.name () == name) + element_ = &e; + } + else + { + if (element_ == 0) + element_ = &e; + else + { + wcerr << schema_root.file () << ": error: unable to generate " + << "the test driver without a unique document root" + << endl; + + wcerr << schema_root.file () << ": info: use --root-element-* " + << "options to specify the document root" << endl; + + valid = false; + } + } + } + + private: + SemanticGraph::Element*& element_; + }; + } + + Boolean Validator:: + validate (CLI::Options const& options, + SemanticGraph::Schema& root, + SemanticGraph::Path const&, + Boolean gen_driver, + const WarningSet& disabled_warnings) + { + Boolean valid (true); + ValidationContext ctx (root, options, disabled_warnings, valid); + + // + // + { + Boolean ref (options.value ()); + Boolean rel (options.value ()); + Boolean re (options.value ()); + + if ((ref && rel) || (ref && re) || (rel && re)) + { + wcerr << "error: mutually exclusive options specified: " + << "--root-element-last, --root-element-first, and " + << "--root-element" + << endl; + + return false; + } + } + + // + // + if (options.value () && + options.value ()) + { + wcerr << "error: mutually exclusive options specified: " + << "--reuse-style-mixin and --reuse-style-none" + << endl; + + return false; + } + + // + // + if (options.value () && + options.value () && + !ctx.is_disabled ("S002")) + { + wcerr << "warning S002: generating sample implementation without " + << "serializer reuse support: the resulting code may not " + << "compile" + << endl; + + return false; + } + + // Test for anonymout types. + // + { + AnonymousType traverser (ctx); + traverser.dispatch (root); + } + + // Test the rest. + // + if (valid) + { + Traverser traverser (ctx); + traverser.dispatch (root); + } + + // Test that the document root is unique. + // + if (valid && gen_driver) + { + SemanticGraph::Element* element (0); + + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalElement global_element (ctx, element); + + schema >> schema_names >> ns >> ns_names >> global_element; + + schema.dispatch (root); + + if (valid && element == 0) + { + wcerr << root.file () << ": error: unable to generate the " + << "test driver without a global element (document root)" + << endl; + + valid = false; + } + } + + return valid; + } + } +} diff --git a/xsde/cxx/serializer/validator.hxx b/xsde/cxx/serializer/validator.hxx new file mode 100644 index 0000000..03d1349 --- /dev/null +++ b/xsde/cxx/serializer/validator.hxx @@ -0,0 +1,36 @@ +// file : xsde/cxx/serializer/validator.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_SERIALIZER_VALIDATOR_HXX +#define CXX_SERIALIZER_VALIDATOR_HXX + +#include + +#include + +#include + +#include + +namespace CXX +{ + namespace Serializer + { + using namespace Cult::Types; + + class Validator + { + public: + Boolean + validate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& tu, + Boolean gen_driver, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // CXX_SERIALIZER_VALIDATOR_HXX diff --git a/xsde/elements.hxx b/xsde/elements.hxx new file mode 100644 index 0000000..68de198 --- /dev/null +++ b/xsde/elements.hxx @@ -0,0 +1,135 @@ +// file : xsde/elements.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef ELEMENTS_HXX +#define ELEMENTS_HXX + +#include + +#include +#include + +using namespace Cult; +typedef WideString String; + +namespace SemanticGraph = XSDFrontend::SemanticGraph; +namespace Traversal = XSDFrontend::Traversal; + + +// Anonymous feedback via belongs edge. +// +struct AnonymousBase : Traversal::Element, + Traversal::Attribute +{ + AnonymousBase (Traversal::NodeDispatcherBase& d1) + : complex_ (&d1, 0) + { + edge_traverser (belongs_); + belongs_.node_traverser (complex_); + } + + AnonymousBase (Traversal::NodeDispatcherBase& d1, + Traversal::NodeDispatcherBase& d2) + : complex_ (&d1, &d2) + { + edge_traverser (belongs_); + belongs_.node_traverser (complex_); + } + + // Hooks. + // +public: + virtual void + member_pre (SemanticGraph::Member&) + { + } + + virtual void + member_post (SemanticGraph::Member&) + { + } + + /* + virtual void + type_pre (SemanticGraph::Type& t) + { + } + + virtual void + type_post (SemanticGraph::Type& t) + { + } + */ + +public: + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Type& t (e.type ()); + + if (!t.named () && !t.context ().count ("seen")) + { + t.context ().set ("seen", true); + + member_pre (e); + + Element::belongs (e, belongs_); + + member_post (e); + + t.context ().remove ("seen"); + } + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + SemanticGraph::Type& t (a.type ()); + + if (!t.named () && !t.context ().count ("seen")) + { + t.context ().set ("seen", true); + + member_pre (a); + + Attribute::belongs (a, belongs_); + + member_post (a); + + t.context ().remove ("seen"); + } + } + +private: + struct Complex : Traversal::Complex + { + Complex (Traversal::NodeDispatcherBase* d1, + Traversal::NodeDispatcherBase* d2) + : d1_ (d1), d2_ (d2) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + if (d1_) + d1_->dispatch (c); + + if (d2_) + d2_->dispatch (c); + } + + private: + Traversal::NodeDispatcherBase* d1_; + Traversal::NodeDispatcherBase* d2_; + + } complex_; + + Traversal::Belongs belongs_; +}; + +#endif // ELEMENTS_HXX + diff --git a/xsde/makefile b/xsde/makefile new file mode 100644 index 0000000..2272811 --- /dev/null +++ b/xsde/makefile @@ -0,0 +1,162 @@ +# file : xsde/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 + +cxx_tun := xsde.cxx + + +# C++ +# +cxx_tun += cxx/elements.cxx + +# C++/Parser +# +cxx_tun += cxx/parser/elements.cxx \ + cxx/parser/validator.cxx \ + cxx/parser/name-processor.cxx \ + cxx/parser/state-processor.cxx \ + cxx/parser/type-processor.cxx \ + cxx/parser/generator.cxx \ + cxx/parser/parser-forward.cxx \ + cxx/parser/parser-header.cxx \ + cxx/parser/parser-inline.cxx \ + cxx/parser/parser-source.cxx \ + cxx/parser/impl-header.cxx \ + cxx/parser/impl-source.cxx \ + cxx/parser/driver-source.cxx \ + cxx/parser/element-validation-source.cxx \ + cxx/parser/attribute-validation-source.cxx \ + cxx/parser/characters-validation-source.cxx + +# C++/Serializer +# +cxx_tun += cxx/serializer/elements.cxx \ + cxx/serializer/validator.cxx \ + cxx/serializer/name-processor.cxx \ + cxx/serializer/type-processor.cxx \ + cxx/serializer/generator.cxx \ + cxx/serializer/serializer-forward.cxx \ + cxx/serializer/serializer-header.cxx \ + cxx/serializer/serializer-inline.cxx \ + cxx/serializer/serializer-source.cxx \ + cxx/serializer/impl-header.cxx \ + cxx/serializer/impl-source.cxx \ + cxx/serializer/driver-source.cxx \ + cxx/serializer/element-validation-source.cxx \ + cxx/serializer/attribute-validation-source.cxx + +# C++/Hybrid +# +cxx_tun += cxx/hybrid/elements.cxx \ + cxx/hybrid/validator.cxx \ + cxx/hybrid/generator.cxx \ + cxx/hybrid/tree-size-processor.cxx \ + cxx/hybrid/tree-name-processor.cxx \ + cxx/hybrid/tree-forward.cxx \ + cxx/hybrid/tree-header.cxx \ + cxx/hybrid/tree-inline.cxx \ + cxx/hybrid/tree-source.cxx \ + cxx/hybrid/tree-type-map.cxx \ + cxx/hybrid/parser-name-processor.cxx \ + cxx/hybrid/parser-header.cxx \ + cxx/hybrid/parser-source.cxx \ + cxx/hybrid/parser-aggregate-header.cxx \ + cxx/hybrid/parser-aggregate-source.cxx \ + cxx/hybrid/serializer-name-processor.cxx \ + cxx/hybrid/serializer-header.cxx \ + cxx/hybrid/serializer-source.cxx \ + cxx/hybrid/serializer-aggregate-header.cxx \ + cxx/hybrid/serializer-aggregate-source.cxx + + +# Type map +# +cxx_tun += type-map/lexer.cxx \ + type-map/parser.cxx + + +# Processing +# +cxx_tun += processing/inheritance/processor.cxx + + +# +# +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +xsde := $(out_base)/xsde +clean := $(out_base)/.clean +install := $(out_base)/.install + +# Import. +# +$(call import,\ + $(scf_root)/import/libcult/stub.make,\ + l: cult.l,cpp-options: cult.l.cpp-options) + +$(call import,\ + $(scf_root)/import/libbackend-elements/stub.make,\ + l: be.l,cpp-options: be.l.cpp-options) + +# This is needed because libbe does not link properly to regex. +# +$(call import,\ + $(scf_root)/import/libboost/regex/stub.make,\ + l: re.l,cpp-options: re.l.cpp-options) + +$(call import,\ + $(scf_root)/import/libboost/filesystem/stub.make,\ + l: fs.l,cpp-options: fs.l.cpp-options) + +$(call import,\ + $(scf_root)/import/libxsd-frontend/stub.make,\ + l: xsd_fe.l,cpp-options: xsd_fe.l.cpp-options) + + +# Build. +# +$(xsde): $(cxx_obj) $(xsd_fe.l) $(be.l) $(cult.l) $(fs.l) $(re.l) + +$(cxx_obj) $(cxx_od): cpp_options := -I$(src_base) +$(cxx_obj) $(cxx_od): \ + $(xsd_fe.l.cpp-options) \ + $(be.l.cpp-options) \ + $(cult.l.cpp-options) \ + $(fs.l.cpp-options) \ + $(re.l.cpp-options) + + +$(call include-dep,$(cxx_od)) + +# Alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(xsde) + +# install +# +.PHONY: $(install) + +$(install): $(xsde) + $(call install-exec,$<,$(install_bin_dir)/xsde) + +# clean +# +.PHONY: $(clean) + +$(clean): \ + $(xsde).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# how to +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) diff --git a/xsde/processing/inheritance/processor.cxx b/xsde/processing/inheritance/processor.cxx new file mode 100644 index 0000000..ab1888f --- /dev/null +++ b/xsde/processing/inheritance/processor.cxx @@ -0,0 +1,517 @@ +// file : processing/inheritance/processor.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include +#include + +#include + +#include +using std::wcerr; +using std::endl; + +namespace Processing +{ + using namespace Cult; + + namespace SemanticGraph = XSDFrontend::SemanticGraph; + namespace Traversal = XSDFrontend::Traversal; + + typedef WideString String; + + namespace Inheritance + { + namespace + { + struct Dep + { + Dep (SemanticGraph::Type& t, + SemanticGraph::Member* m = 0, + String const& xpath = L"") + : type (t), member (m), member_xpath (xpath) + { + } + + SemanticGraph::Type& type; + SemanticGraph::Member* member; // Member if type is anonymous. + String member_xpath; + }; + + inline Boolean + operator< (Dep const& a, Dep const& b) + { + return &a.type < &b.type; + } + + typedef Containers::Set DepSet; + typedef Containers::Set TypeSet; + + + String + xpath (SemanticGraph::Nameable& n) + { + if (dynamic_cast (&n) != 0) + return L""; // There is a bug if you see this. + + if (n.named ()) + { + SemanticGraph::Scope& scope (n.scope ()); + + if (dynamic_cast (&scope) != 0) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + else + { + return L"(anonymous type for " + + n.context ().get ("instance-name") + L")"; + } + } + + + // Calculate the list of dependencies for this type. + // + struct Type: Traversal::List, + Traversal::Complex, + Traversal::Member + { + Type (DepSet& dep_set, Char const* by_value_key) + : by_value_key_ (by_value_key), dep_set_ (dep_set), last_ (0) + { + *this >> names_ >> *this; + } + + virtual Void + traverse (SemanticGraph::List& l) + { + SemanticGraph::Type& t (l.argumented ().type ()); + + if (by_value_key_ != 0 && + t.context ().count (by_value_key_) && + t.context ().get (by_value_key_)) + { + dep_set_.insert (Dep (t)); + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Complex; + + if (c.inherits_p ()) + dep_set_.insert (Dep (c.inherits ().base (), last_, last_xpath_)); + + types_seen_.insert (&c); + + // Go after anonymous types. + // + names (c); + } + + virtual Void + traverse (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named ()) + { + if (types_seen_.find (&t) == types_seen_.end ()) + { + FrontendElements::Context& ctx (t.context ()); + + last_xpath_ = xpath (m); + + String prev_xpath; + + if (ctx.count ("instance-name")) + prev_xpath = ctx.get ("instance-name"); + + ctx.set ("instance-name", last_xpath_); + + last_ = &m; + dispatch (t); + + if (prev_xpath) + ctx.set ("instance-name", prev_xpath); + else + ctx.remove ("instance-name"); + } + } + else + { + if (by_value_key_ != 0 && + t.context ().count (by_value_key_) && + t.context ().get (by_value_key_)) + { + dep_set_.insert (Dep (t)); + } + } + } + + private: + Char const* by_value_key_; + DepSet& dep_set_; + TypeSet types_seen_; + + SemanticGraph::Member* last_; + String last_xpath_; + + Traversal::Names names_; + }; + + + // + // + template + struct NodeArgs + { + NodeArgs (N& node, A arg) + : node_ (node), arg_ (arg) + { + } + + operator N& () const + { + return node_; + } + + template + Void + add_edge_left (E& e) + { + node_.add_edge_left (e, arg_); + } + + template + Void + add_edge_right (E& e) + { + node_.add_edge_right (e, arg_); + } + + private: + N& node_; + A arg_; + }; + + + // + // + struct Global: Traversal::Type, + Traversal::List, + Traversal::Complex, + Traversal::Element + { + Global (SemanticGraph::Schema& root, + SemanticGraph::Schema& schema, + Char const* by_value_key, + Boolean& failed) + : root_ (root), + schema_ (schema), + by_value_key_ (by_value_key), + failed_ (failed) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + if (t.named ()) + types_seen_.insert (&t); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + check_dep (l, l); + types_seen_.insert (&l); + }; + + virtual Void + traverse (SemanticGraph::Complex& c) + { + check_dep (c, c); + types_seen_.insert (&c); + }; + + virtual Void + traverse (SemanticGraph::Element& e) + { + SemanticGraph::Type& t (e.type ()); + + if (!t.named ()) + { + t.context ().set ("instance-name", xpath (e)); + check_dep (e, t); + t.context ().remove ("instance-name"); + } + }; + + private: + Void + check_dep (SemanticGraph::Nameable& global, + SemanticGraph::Type& type) + { + using SemanticGraph::Scope; + using SemanticGraph::Names; + using SemanticGraph::Schema; + + DepSet prereqs; + + // Calculate our prerequisistes. + // + { + Inheritance::Type t (prereqs, by_value_key_); + t.dispatch (type); + } + + for (DepSet::ConstIterator i (prereqs.begin ()); + i != prereqs.end (); ++i) + { + Dep const& dep (*i); + SemanticGraph::Type& t (dep.type); + + // We won't be able to generate compilable code in case of a + // dependency on ourselves (e.g., a member element with + // anonymous type that inherits from us). + // + if (&t == &type) + { + assert (dep.member != 0); + + SemanticGraph::Member& m (*dep.member); + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << " error: nested anonymous type for '" + << dep.member_xpath << "' cyclicly inherits from '" + << t.name () << "'" << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << " error: unable to generate valid code for such " + << "cyclic inheritance" << endl; + + wcerr << m.file () << ":" << m.line () << ":" << m.column () + << " info: '" << m.name () << "' element is declared here" + << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": info: consider explicitly naming this type " + << "or remove the --preserve-anonymous option" + << endl; + + failed_ = true; + continue; + } + + if (types_seen_.find (&t) == types_seen_.end ()) + { + Scope& scope (t.scope ()); + Schema& schema (dynamic_cast (scope.scope ())); + + // Don't worry about types that are in included/imported + // schemas. + // + if (&schema != &schema_ && !sources_p (schema_, schema)) + continue; + + if (t.context ().count ("seen")) + { + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << " error: nested anonymous type in '" << t.name () + << "' or '" << type.name () << "' inherits from one of " + << "these types and makes them mutually dependant" + << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << " error: unable to generate valid code for such " + << "cyclic dependency" << endl; + + wcerr << type.file () << ":" << type.line () << ":" + << type.column () << " info: '" << type.name () + << "' type is defined here" + << endl; + + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": info: consider explicitly naming the anonymous " + << "type or remove the --preserve-anonymous option" + << endl; + + failed_ = true; + continue; + } + + + //wcerr << "type '" << t.name () << "' needs to be moved " << + // "before " << (global.is_a () ? "type" : "element") + // << " '" << global.name () << "'" << endl; + + + // Delete current Names edge. + // + String name (t.name ()); + { + Names& n (t.named_ ()); + root_.delete_edge (scope, t, n); + } + + // Insert a new Names edge before global. + // + { + // Convert to the insert-after call. + // + Scope::NamesIterator i (scope.find (global.named_ ())); + + if (i == scope.names_begin ()) + i = scope.names_end (); + else + --i; + + NodeArgs na (scope, i); + root_.new_edge (na, t, name); + } + + // Recursively process the moved type. + // + global.context ().set ("seen", true); + dispatch (t); + global.context ().remove ("seen"); + } + } + } + + private: + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + SemanticGraph::Schema& root_; + SemanticGraph::Schema& schema_; + Char const* by_value_key_; + TypeSet types_seen_; + Boolean& failed_; + }; + + + // Go into included/imported schemas while making sure we don't + // process the same stuff more than once. + // + struct Uses: Traversal::Includes, Traversal::Imports + { + Uses (SemanticGraph::Schema& root, + Char const* by_value_key, + Boolean& failed) + : root_ (root), by_value_key_ (by_value_key), failed_ (failed) + { + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + traverse (i.schema ()); + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + traverse (i.schema ()); + } + + private: + Void + traverse (SemanticGraph::Schema& s) + { + if (!s.context ().count ("processing-inheritance-seen")) + { + Traversal::Schema schema; + Traversal::Sources sources; + + schema >> sources >> schema; + schema >> *this; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + Global global (root_, s, by_value_key_, failed_); + + ns_names >> global; + + s.context ().set ("processing-inheritance-seen", true); + schema.dispatch (s); + } + } + + private: + SemanticGraph::Schema& root_; + Char const* by_value_key_; + Boolean& failed_; + }; + } + + Void Processor:: + process (SemanticGraph::Schema& tu, + SemanticGraph::Path const&, + Char const* by_value_key) + { + Boolean failed (false); + + // We need to process include/imported schemas since other + // parts of the process, for example, name processors can + // rely on the order of types in the schema. + // + Traversal::Schema schema; + Traversal::Sources sources; + Uses uses (tu, by_value_key, failed); + + schema >> sources >> schema; + schema >> uses; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + Global global (tu, tu, by_value_key, failed); + + ns_names >> global; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("processing-inheritance-seen", true); + + schema.dispatch (tu); + + if (failed) + throw Failed (); + } + } +} diff --git a/xsde/processing/inheritance/processor.hxx b/xsde/processing/inheritance/processor.hxx new file mode 100644 index 0000000..602bd92 --- /dev/null +++ b/xsde/processing/inheritance/processor.hxx @@ -0,0 +1,38 @@ +// file : processing/inheritance/processor.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef PROCESSING_INHERITANCE_PROCESSOR_HXX +#define PROCESSING_INHERITANCE_PROCESSOR_HXX + +#include + +#include // Path +#include + +namespace Processing +{ + namespace Inheritance + { + using namespace Cult::Types; + + class Processor + { + public: + struct Failed {}; + + // If a type of an element or attribute has a context entry + // with the by_value_key key and it is true, then this type + // is rearranged to appear before the type containing this + // element/attribute. + // + Void + process (XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + Char const* by_value_key = 0); + }; + } +} + +#endif // PROCESSING_INHERITANCE_PROCESSOR_HXX diff --git a/xsde/type-map/lexer.cxx b/xsde/type-map/lexer.cxx new file mode 100644 index 0000000..81ac2d3 --- /dev/null +++ b/xsde/type-map/lexer.cxx @@ -0,0 +1,133 @@ +// file : xsde/type-map/lexer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +using std::wcerr; +using std::endl; + +namespace TypeMap +{ + Lexer::Lexer (std::istream& is, String const& path) + : locale_ ("C"), is_ (is), path_ (path), line_ (1), comment_ (false) + { + is_.exceptions (std::ios_base::badbit); + } + + Lexer::Token Lexer:: + next () + { + if (held_lexeme_) + { + Token t (Token::punct, held_lexeme_, line_); + held_lexeme_.clear (); + return t; + } + + typedef std::char_traits Traits; + typedef Traits::char_type CharType; + typedef Traits::int_type IntType; + + IntType i; + CharType c ('\0'); + NarrowString lexeme; + + // Skip all whitespaces including comments. + // + while (!is_.eof ()) + { + i = is_.get (); + + if (i == Traits::eof ()) + break; + + c = Traits::to_char_type (i); + + if (comment_) + { + if (c == '\n') + comment_ = false; + } + else + { + if (!(std::isspace (c, locale_) || c == '#')) + break; + + if (c == '#') + comment_ = true; + } + + if (c == '\n') + ++line_; + } + + if (is_.eof ()) + return Token (Token::eos, L"", line_); + + Boolean quote (c == '"'); + + if (!quote) + lexeme += c; + + if (c != ';' && c != '{' && c != '}') + { + // Accumulate non-whitespace character sequence. + // + + while (!is_.eof ()) + { + i = is_.get (); + + if (i == Traits::eof ()) + break; + + c = Traits::to_char_type (i); + + if (!quote && c == '#') + { + comment_ = true; + break; + } + + if (std::isspace (c, locale_)) + { + if (c == '\n') + ++line_; + + if (!quote) + break; + } + + if (!quote && (c == ';' || c == '{' || c == '}')) + { + held_lexeme_ += c; + break; + } + + if (quote && c == '"') + break; + + lexeme += c; + } + + if (quote && c != '"') + { + wcerr << path_ << ":" << line_ << ": error: closing '\"' expected" + << endl; + + throw Failed (); + } + } + + if (!quote && (lexeme == ";" || lexeme == "{" || lexeme == "}")) + { + return Token (Token::punct, lexeme, line_); + } + else + return Token (Token::token, lexeme, line_); + } +} diff --git a/xsde/type-map/lexer.hxx b/xsde/type-map/lexer.hxx new file mode 100644 index 0000000..1d710bc --- /dev/null +++ b/xsde/type-map/lexer.hxx @@ -0,0 +1,80 @@ +// file : xsde/type-map/lexer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_TYPE_MAP_LEXER_HXX +#define XSDE_TYPE_MAP_LEXER_HXX + +#include +#include + +#include + +namespace TypeMap +{ + using namespace Cult::Types; + typedef WideString String; + + class Lexer + { + public: + class Token + { + public: + enum Type + { + token, + punct, + eos + }; + + Token (Type type, String const& lexeme, UnsignedLong line) + : type_ (type), lexeme_ (lexeme), line_ (line) + { + } + + Type + type () const + { + return type_; + } + + String const& + lexeme () const + { + return lexeme_; + } + + UnsignedLong + line () const + { + return line_; + } + + private: + Type type_; + String lexeme_; + UnsignedLong line_; + }; + + Lexer (std::istream&, String const& path); + + struct Failed {}; + + Token + next (); + + private: + std::locale locale_; + std::istream& is_; + String path_; + UnsignedLong line_; + String held_lexeme_; + Boolean comment_; + }; + +} + +#endif // XSDE_TYPE_MAP_LEXER_HXX + diff --git a/xsde/type-map/parser.cxx b/xsde/type-map/parser.cxx new file mode 100644 index 0000000..14a6c26 --- /dev/null +++ b/xsde/type-map/parser.cxx @@ -0,0 +1,281 @@ +// file : xsde/type-map/parser.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +#include + +using std::endl; + +namespace TypeMap +{ + typedef Lexer::Token Token; + typedef BackendElements::Regex::Format Format; + + Parser::Parser (Lexer& lex, String const& path) + : lex_ (lex), path_ (path), e (std::wcerr) + { + } + + Boolean Parser:: + parse (Namespaces& ns) + { + try + { + Namespace* global = 0; + + for (Token t (lex_.next ()); t.type () != Token::eos; t = lex_.next ()) + { + String l (t.lexeme ()); + + if (l == L"namespace") + { + global = 0; + + if (!namespace_ (ns)) + return false; + } + else if (l == L"include") + { + if (global == 0) + { + ns.push_back (Namespace (Pattern ())); + global = &(*ns.rbegin ()); + } + + if (!include (*global)) + return false; + } + else if (l == L"type" || t.type () == Token::token) + { + // Type mapping can have 'type' specifier omitted. + // + if (l == L"type") + t = lex_.next (); + + if (global == 0) + { + ns.push_back (Namespace (Pattern ())); + global = &(*ns.rbegin ()); + } + + if (!type (t, *global)) + return false; + } + else + { + e << path_ << ":" << t.line () << ": unexpected '" << l << "'" + << endl; + + return false; + } + } + } + catch (Lexer::Failed const&) + { + return false; + } + + return true; + } + + Boolean Parser:: + namespace_ (Namespaces& ns) + { + // First get XML namespace. + // + Token t (lex_.next ()); + + Pattern xsd_name; + + try + { + xsd_name = t.lexeme (); + } + catch (Format const& ex) + { + e << path_ << ":" << t.line () << ": invalid namespace pattern: " + << ex.description () << endl; + return false; + } + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected XML namespace " + << "instead of '" << xsd_name << "'" << endl; + return false; + } + + + // See if we've got optional C++ mapping. + // + t = lex_.next (); + + Boolean has_cxx_name (false); + String cxx_name; + + if (t.type () != Token::token) + { + if (t.lexeme () != L"{") + { + e << path_ << ":" << t.line () << ": expected C++ namespace or '{' " + << "instead of '" << t.lexeme () << "'" << endl; + return false; + } + } + else + { + has_cxx_name = true; + cxx_name = t.lexeme (); + } + + // Swallow '{' if needed. + // + if (has_cxx_name) + { + t = lex_.next (); + + if (t.type () != Token::punct || t.lexeme () != L"{") + { + e << path_ << ":" << t.line () << ": expected '{' instead of '" + << t.lexeme () << "'" << endl; + return false; + } + } + + Namespace n (xsd_name, has_cxx_name, cxx_name); + + // Parse namespace body. + // + for (t = lex_.next ();; t = lex_.next ()) + { + String l (t.lexeme ()); + + if (l == L"include") + { + if (!include (n)) + return false; + } + else if (l == L"type" || t.type () == Token::token) + { + // Type mapping can have 'type' specifier omitted. + // + if (l == L"type") + t = lex_.next (); + + if (!type (t, n)) + return false; + } + else if (t.type () == Token::punct && l == L"}") + { + break; + } + else + { + e << path_ << ":" << t.line () << ": unexpected '" << l << "'" + << endl; + return false; + } + } + + if (cxx_name || n.types_begin () != n.types_end () || + n.includes_begin () != n.includes_end ()) + { + ns.push_back (n); + } + + return true; + } + + Boolean Parser:: + include (Namespace& n) + { + Token t (lex_.next ()); + + String path (t.lexeme ()); + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected include path " + << "instead of '" << path << "'" << endl; + return false; + } + + if (path && path[0] == L'<') + n.includes_push_back (path); + else + n.includes_push_back (L'"' + path + L'"'); + + t = lex_.next (); + + if (t.type () != Token::punct || t.lexeme () != L";") + { + e << path_ << ":" << t.line () << ": expected ';' after '" + << path << "'" << endl; + return false; + } + + return true; + } + + Boolean Parser:: + type (Token t, Namespace& n) + { + Pattern xsd_name; + + try + { + xsd_name = t.lexeme (); + } + catch (Format const& ex) + { + e << path_ << ":" << t.line () << ": invalid namespace pattern: " + << ex.description () << endl; + return false; + } + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected XML Schema type name " + << "instead of '" << xsd_name << "'" << endl; + return false; + } + + t = lex_.next (); + String cxx_ret_name (t.lexeme ()); + + if (t.type () != Token::token) + { + e << path_ << ":" << t.line () << ": expected C++ type name " + << "instead of '" << cxx_ret_name << "'" << endl; + return false; + } + + t = lex_.next (); + + String cxx_arg_name; + + // See if we've got optional argument type. + // + if (t.type () == Token::token) + { + cxx_arg_name = t.lexeme (); + t = lex_.next (); + } + + if (t.type () != Token::punct || t.lexeme () != L";") + { + e << path_ << ":" << t.line () << ": expected ';' after '" + << cxx_arg_name << "'" << endl; + return false; + } + + n.types_push_back (xsd_name, cxx_ret_name, cxx_arg_name); + + return true; + } +} diff --git a/xsde/type-map/parser.hxx b/xsde/type-map/parser.hxx new file mode 100644 index 0000000..592e1f6 --- /dev/null +++ b/xsde/type-map/parser.hxx @@ -0,0 +1,46 @@ +// file : xsde/type-map/parser.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_TYPE_MAP_PARSER_HXX +#define XSDE_TYPE_MAP_PARSER_HXX + +#include + +#include +#include + +namespace TypeMap +{ + using namespace Cult::Types; + typedef WideString String; + + class Parser + { + public: + Parser (Lexer&, String const& path); + + // Merge parsed namespaces. + // + Boolean + parse (Namespaces&); + + private: + Boolean + namespace_ (Namespaces&); + + Boolean + include (Namespace&); + + Boolean + type (Lexer::Token, Namespace&); + + private: + Lexer& lex_; + String path_; + std::wostream& e; + }; +} + +#endif // XSDE_TYPE_MAP_PARSER_HXX diff --git a/xsde/type-map/type-map.hxx b/xsde/type-map/type-map.hxx new file mode 100644 index 0000000..aa6a2ee --- /dev/null +++ b/xsde/type-map/type-map.hxx @@ -0,0 +1,160 @@ +// file : xsde/type-map/type-map.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_TYPE_MAP_TYPE_MAP_HXX +#define XSDE_TYPE_MAP_TYPE_MAP_HXX + +#include +#include + +#include + +namespace TypeMap +{ + using namespace Cult::Types; + typedef WideString String; + typedef BackendElements::Regex::Pattern Pattern; + + class Type + { + public: + Type (Pattern const& xsd_name, + String const& cxx_ret_name, + String const& cxx_arg_name) + : xsd_name_ (xsd_name), + cxx_ret_name_ (cxx_ret_name), + cxx_arg_name_ (cxx_arg_name) + { + } + + Pattern const& + xsd_name () const + { + return xsd_name_; + } + + String const& + cxx_ret_name () const + { + return cxx_ret_name_; + } + + String const& + cxx_arg_name () const + { + return cxx_arg_name_; + } + + private: + Pattern xsd_name_; + String cxx_ret_name_; + String cxx_arg_name_; + }; + + class Namespace + { + public: + Namespace (Pattern const& xsd_name) + : xsd_name_ (xsd_name), has_cxx_name_ (false) + { + } + + Namespace (Pattern const& xsd_name, String const& cxx_name) + : xsd_name_ (xsd_name), has_cxx_name_ (true), cxx_name_ (cxx_name) + { + } + + Namespace (Pattern const& xsd_name, + Boolean has_cxx_name, + String const& cxx_name) + : xsd_name_ (xsd_name), + has_cxx_name_ (has_cxx_name), + cxx_name_ (cxx_name) + { + } + + // + // + typedef Cult::Containers::Vector Includes; + typedef Includes::ConstIterator IncludesIterator; + + IncludesIterator + includes_begin () const + { + return includes_.begin (); + } + + IncludesIterator + includes_end () const + { + return includes_.end (); + } + + Void + includes_push_back (String const& i) + { + includes_.push_back (i); + } + + // + // + typedef Cult::Containers::Vector Types; + typedef Types::ConstIterator TypesIterator; + + TypesIterator + types_begin () const + { + return types_.begin (); + } + + TypesIterator + types_end () const + { + return types_.end (); + } + + Void + types_push_back (Pattern const& xsd_type, + String const& cxx_ret_type, + String const& cxx_arg_type = L"") + { + types_.push_back (Type (xsd_type, cxx_ret_type, cxx_arg_type)); + } + + // + // + Pattern const& + xsd_name () const + { + return xsd_name_; + } + + // + // + Boolean + has_cxx_name () const + { + return has_cxx_name_; + } + + String const& + cxx_name () const + { + return cxx_name_; + } + + private: + Includes includes_; + Types types_; + Pattern xsd_name_; + Boolean has_cxx_name_; + String cxx_name_; + }; + + typedef Cult::Containers::Vector Namespaces; +} + +#endif // XSDE_TYPE_MAP_TYPE_MAP_HXX + diff --git a/xsde/usage.hxx b/xsde/usage.hxx new file mode 100644 index 0000000..517f9c7 --- /dev/null +++ b/xsde/usage.hxx @@ -0,0 +1,226 @@ +// file : xsde/usage.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef USAGE_HXX +#define USAGE_HXX + +#include + +#include +#include + +namespace CLI +{ + using namespace Cult::Types; + + template + class OptionsUsage: public BackendElements::Indentation::Buffer + { + typedef BackendElements::Indentation::Buffer Buffer; + + public: + typedef + typename Buffer::Traits + Traits; + + typedef + typename Buffer::AsChar + AsChar; + + typedef + typename Buffer::AsInt + AsInt; + + typedef + typename Buffer::Write + Write; + + public: + OptionsUsage (Buffer& out) + : out_ (out), + option_length_ (0), + construct_ (Construct::newline) + { + } + + public: + virtual AsInt + put (AsChar c) + { + AsInt result (Traits::to_int_type (c)); + + try + { + switch (c) + { + case '\n': + { + switch (construct_) + { + case Construct::newline: + { + result = out_.put (c); + break; + } + case Construct::option: + { + construct_ = Construct::newline; + break; + } + case Construct::description: + { + result = out_.put (c); + construct_ = Construct::newline; + break; + } + default: + { + abort (); + } + } + + break; + } + case '-': + { + switch (construct_) + { + case Construct::newline: + { + construct_ = Construct::option; + + option_length_ = 0; + + output_indentation (); + result = out_.put (c); + + ++option_length_; + + break; + } + case Construct::option: + { + ++option_length_; + //fall through + } + case Construct::description: + { + result = out_.put (c); + break; + } + default: + { + abort (); + } + } + + break; + } + default: + { + switch (construct_) + { + case Construct::newline: + { + construct_ = Construct::description; + + output_indentation (); + + result = out_.put (c); + break; + } + case Construct::option: + { + ++option_length_; + //fall through + } + default: + { + result = out_.put (c); + break; + } + } + + break; + } + } + } + catch (Write const&) + { + result = Traits::eof (); + } + + return result; + } + + virtual Void + unbuffer () + { + } + + private: + Void + output_indentation () + { + UnsignedLong spaces; + + switch (construct_) + { + case Construct::option: + { + spaces = 2; + option_length_ += 2; + break; + } + case Construct::description: + { + spaces = 29; + + if (option_length_) + { + if (option_length_ > spaces) + spaces = 1; + else + spaces -= option_length_; + + option_length_ = 0; + } + + break; + } + default: + { + abort (); + } + } + + while (spaces--) + out_.put (' '); + } + + private: + Buffer& out_; + UnsignedLong option_length_; + + struct Construct + { + enum Value + { + newline, + option, + description + }; + }; + + typename Construct::Value construct_; + }; + + //@@ rename Indentation to Indent in be? + // + namespace Indent = BackendElements::Indentation; +} + +#endif // USAGE_HXX + diff --git a/xsde/xsde.cxx b/xsde/xsde.cxx new file mode 100644 index 0000000..acbc5db --- /dev/null +++ b/xsde/xsde.cxx @@ -0,0 +1,1422 @@ +// file : xsde/xsde.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include "../libxsde/xsde/cxx/version.hxx" + +using namespace Cult::Types; + +typedef Cult::Containers::Vector NarrowStrings; + +namespace SemanticGraph = XSDFrontend::SemanticGraph; +namespace Transformations = XSDFrontend::Transformations; + +using std::wcerr; +using std::endl; + +namespace CLI +{ + using namespace Cult::CLI; + + typedef Char const Key[]; + + extern Key help = "help"; + extern Key version = "version"; + extern Key proprietary_license = "proprietary-license"; + + typedef Cult::CLI::Options + < + help, Boolean, + version, Boolean, + proprietary_license, Boolean + > + HelpOptions; + + struct HelpOptionsSpec: Cult::CLI::OptionsSpec {}; + + + extern Key disable_warning = "disable-warning"; + extern Key sloc_limit = "sloc-limit"; + extern Key preserve_anonymous = "preserve-anonymous"; + extern Key anonymous_regex = "anonymous-regex"; + extern Key anonymous_regex_trace = "anonymous-regex-trace"; + extern Key location_map = "location-map"; + extern Key location_regex = "location-regex"; + extern Key location_regex_trace = "location-regex-trace"; + extern Key file_per_type = "file-per-type"; + extern Key type_file_regex = "type-file-regex"; + extern Key type_file_regex_trace = "type-file-regex-trace"; + extern Key file_list = "file-list"; + extern Key file_list_prologue = "file-list-prologue"; + extern Key file_list_epilogue = "file-list-epilogue"; + extern Key file_list_delim = "file-list-delim"; + extern Key disable_full_check = "disable-full-check"; // Undocumented. + + typedef Cult::CLI::Options + < + disable_warning, Cult::Containers::Vector, + sloc_limit, UnsignedLong, + preserve_anonymous, Boolean, + anonymous_regex, NarrowStrings, + anonymous_regex_trace, Boolean, + location_map, NarrowStrings, + location_regex, NarrowStrings, + location_regex_trace, Boolean, + file_per_type, Boolean, + type_file_regex, NarrowStrings, + type_file_regex_trace, Boolean, + file_list, NarrowString, + file_list_prologue, NarrowString, + file_list_epilogue, NarrowString, + file_list_delim, NarrowString, + disable_full_check, Boolean + > + CommonOptions; + + struct CommonOptionsSpec: Cult::CLI::OptionsSpec {}; +} + +// +// +struct LocationTranslator: XSDFrontend::LocationTranslator +{ + struct Failed {}; + + LocationTranslator (NarrowStrings const& map, + NarrowStrings const& regex, + Boolean trace); + + virtual NarrowString + translate (NarrowString const&); + +private: + typedef Cult::Containers::Map Map; + + typedef BackendElements::Regex::Expression Regex; + typedef BackendElements::Regex::Format RegexFormat; + typedef Cult::Containers::Vector RegexVector; + + typedef Cult::Containers::Map Cache; + + Map map_; + RegexVector regex_; + Cache cache_; + Boolean trace_; +}; + +// +// +struct AnonymousNameTranslator: Transformations::AnonymousNameTranslator +{ + struct Failed {}; + + AnonymousNameTranslator (NarrowStrings const& regex, Boolean trace); + + virtual WideString + translate (WideString const& file, + WideString const& ns, + WideString const& name, + WideString const& xpath); + +private: + typedef BackendElements::Regex::Expression Regex; + typedef BackendElements::Regex::Format RegexFormat; + typedef Cult::Containers::Vector RegexVector; + + RegexVector regex_; + Boolean trace_; + +}; + +// +// +struct TypeSchemaTranslator: Transformations::TypeSchemaTranslator +{ + struct Failed {}; + + TypeSchemaTranslator (NarrowStrings const& regex, Boolean trace); + + virtual WideString + translate (WideString const& ns, WideString const& name); + +private: + typedef BackendElements::Regex::Expression Regex; + typedef BackendElements::Regex::Format RegexFormat; + typedef Cult::Containers::Vector RegexVector; + + RegexVector regex_; + Boolean trace_; +}; + +// Expand the \n escape sequence. +// +Void +expand_nl (NarrowString& s); + +Int +main (Int argc, Char* argv[]) +{ + std::wostream& e (wcerr); + + Cult::Trace::Log::instance ().level (0); + + try + { + CLI::FileArguments args (argc, argv, "--options-file"); + + CLI::HelpOptions help_ops ( + CLI::parse (CLI::HelpOptionsSpec (), args, CLI::UnknownMode::stop)); + + NarrowString cmd; + + if (args.size () > 1) + { + cmd = args[1]; + args.erase (1); + } + + if (help_ops.value () || cmd == "version") + { + e << "CodeSynthesis XSD/e XML Schema to C++ compiler " << + "for embedded systems " << XSDE_STR_VERSION << endl + << "Copyright (C) 2005-2009 Code Synthesis Tools CC" << endl; + + if (!help_ops.value () && + cmd == "version") + { + // Parse the options after the command to detect trailing + // --proprietary-license. + // + help_ops = CLI::parse ( + CLI::HelpOptionsSpec (), args, CLI::UnknownMode::stop); + } + + if (help_ops.value ()) + { + e << "The compiler was invoked in the Proprietary License mode. You " + << "should have\nreceived a proprietary license from Code Synthesis " + << "Tools CC that entitles\nyou to use it in this mode." << endl; + } + else + { + e << "This is free software; see the source for copying conditions. " + << "There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS " + << "FOR A PARTICULAR PURPOSE." << endl; + } + + return 0; + } + + if (help_ops.value () || cmd == "help") + { + if (cmd == "help" && args.size () > 1) + { + NarrowString arg (args[1]); + + if (arg == "cxx-parser") + { + e << "Usage: " << args[0] << " cxx-parser [options] file [file ...]" + << endl + << "Options:" << endl; + + CXX::Parser::Generator::usage (); + } + else if (arg == "cxx-serializer") + { + e << "Usage: " << args[0] << " cxx-serializer [options] file " << + "[file ...]" << endl + << "Options:" << endl; + + CXX::Serializer::Generator::usage (); + } + else if (arg == "cxx-hybrid") + { + e << "Usage: " << args[0] << " cxx-hybrid [options] file " << + "[file ...]" << endl + << "Options:" << endl; + + CXX::Hybrid::Generator::usage (); + } + else + { + e << "error: unknown command '" << arg.c_str () << "'" << endl + << "info: try '" << args[0] << " help' for the list of commands" + << endl; + + return 1; + } + + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + // Disable warning option. + // + e << "--disable-warning " << endl + << " Disable printing warning with id . If 'all'\n" + << " is specified for the warning id then all warnings\n" + << " are disabled." + << endl; + + // Anonymous morphing options. + // + e << "--preserve-anonymous" << endl + << " Preserve anonymous types. By default anonymous\n" + << " types are automatically named with names derived\n" + << " from the enclosing elements/attributes." + << endl; + + e << "--anonymous-regex " << endl + << " Add the provided regular expression to the list of\n" + << " regular expressions used to derive names for\n" + << " anonymous types from the names of the enclosing\n" + << " attributes/elements." + << endl; + + e << "--anonymous-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --anonymous-regex option." + << endl; + + // Location mapping options. + // + e << "--location-map
    =" << endl + << " Map the original schema location
      that is\n" + << " specified in the XML Schema include or import\n" + << " elements to new schema location . Repeat\n" + << " this option to map more than one schema location." + << endl; + + e << "--location-regex " << endl + << " Add to the list of regular expressions\n" + << " used to map schema locations that are specified\n" + << " in the XML Schema include or import elements." + << endl; + + e << "--location-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --location-regex option." + << endl; + + // File-per-type compilation mode options. + // + e << "--file-per-type" << endl + << " Generate a separate set of C++ files for each\n" + << " type defined in XML Schema." + << endl; + + e << "--type-file-regex " << endl + << " Add the provided regular expression to the list of\n" + << " regular expressions used to translate type names\n" + << " to file names when the --type-per-file option is\n" + << " specified." + << endl; + + e << "--type-file-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --type-file-regex option." + << endl; + + // File list options. + // + e << "--file-list " << endl + << " Write a list of generated C++ files to ." + << endl; + + e << "--file-list-prologue

      " << endl + << " Insert

      at the beginning of the file list. All\n" + << " occurrences of the \\n character sequence in

      \n" + << " are replaced with new lines." + << endl; + + e << "--file-list-prologue " << endl + << " Insert at the end of the file list. All\n" + << " occurrences of the \\n character sequence in \n" + << " are replaced with new lines." + << endl; + + e << "--file-list-delim " << endl + << " Delimit file names written to the file list with\n" + << " instead of new lines. All occurrences of the\n" + << " \\n character sequence in are replaced with\n" + << " new lines." + << endl; + } + else + { + e << "Usage: " << args[0] << " ..." << endl + << "Commands:" << endl; + + e << " help Print usage information and exit. Use\n" + << " 'help ' for command-specific options." + << endl; + + e << " version Print version and exit." + << endl; + + e << " cxx-parser Generate Embedded C++/Parser mapping." + << endl; + + e << " cxx-serializer Generate Embedded C++/Serializer mapping." + << endl; + + e << " cxx-hybrid Generate Embedded C++/Hybrid mapping." + << endl; + } + + return 0; + } + + if (cmd.empty ()) + { + e << "error: no command specified" << endl + << "info: try '" << args[0] << " help' for usage information" << endl; + + return 1; + } + + if (cmd != "cxx-parser" && cmd != "cxx-serializer" && cmd != "cxx-hybrid") + { + e << "error: unknown command '" << cmd.c_str () << "'" << endl + << "info: try '" << args[0] << " help' for the list of commands" + << endl; + + return 1; + } + + // We need to parse command line options before we can get to + // the arguments. + // + CLI::CommonOptionsSpec common_spec; + common_spec.option ().default_value ("\n"); + + CLI::CommonOptions common_ops ( + CLI::parse ( + common_spec, + args, + CLI::UnknownMode::skip, + CLI::UnknownMode::skip)); + + WarningSet disabled_w; + { + typedef Cult::Containers::Vector Warnings; + Warnings const& w (common_ops.value ()); + + for (Warnings::ConstIterator i (w.begin ()); i != w.end (); ++i) + disabled_w.insert (*i); + } + + Boolean disabled_w_all (disabled_w.find ("all") != disabled_w.end ()); + + Evptr p_ops; + Evptr s_ops; + Evptr h_ops; + + Boolean show_sloc (false); + + if (cmd == "cxx-parser") + { + p_ops = new CXX::Parser::CLI::Options ( + CLI::parse (CXX::Parser::Generator::options_spec (), args)); + + show_sloc = p_ops->value (); + } + else if (cmd == "cxx-serializer") + { + s_ops = new CXX::Serializer::CLI::Options ( + CLI::parse (CXX::Serializer::Generator::options_spec (), args)); + + show_sloc = s_ops->value (); + } + else if (cmd == "cxx-hybrid") + { + h_ops = new CXX::Hybrid::CLI::Options ( + CLI::parse (CXX::Hybrid::Generator::options_spec (), args)); + + if (h_ops->value ()) + p_ops = CXX::Hybrid::Generator::parser_options (*h_ops); + + if (h_ops->value ()) + s_ops = CXX::Hybrid::Generator::serializer_options (*h_ops); + + show_sloc = h_ops->value (); + } + + if (args.size () < 2) + { + e << "error: no input file specified" << endl; + return 1; + } + + Boolean fpt (common_ops.value ()); + + // Generate/extern XML Schema checks. + // + if (cmd == "cxx-parser" || cmd == "cxx-serializer" || cmd == "cxx-hybrid") + { + Boolean gen (false), use (false); + + if (cmd == "cxx-parser") + { + gen = p_ops->value (); + use = p_ops->value (); + } + else if (cmd == "cxx-serializer") + { + gen = s_ops->value (); + use = s_ops->value (); + } + else if (cmd == "cxx-hybrid") + { + gen = h_ops->value (); + use = h_ops->value (); + } + + // Things get complicated when we are compiling several schemas at + // once (non-file-per-type mode) and use the --generate-xml-schema/ + // --extern-xml-schema options. The only way we can figure out which + // file corresponds to XML Schema is if the --extern-xml-schema option + // is also present. So we are going to require it for this case, + // especially since it generally makes sense. + // + if (!fpt) + { + if (args.size () > 2 && gen && !use) + { + e << "error: --extern-xml-schema is required when compiling more " + << "than one schema and --generate-xml-schema is specified" + << endl; + + return 1; + } + + if (args.size () == 2 && gen && use) + { + e << "error: --generate-xml-schema and --extern-xml-schema are " + << "mutually exclusive when compiling a single schema" << endl; + + return 1; + } + } + else + { + // The --file-per-type and --generate-xml-schema options are + // incompatible. It also makes sense to use --file-per-type + // and --extern-xml-schema. + // + if (gen) + { + e << "error: --file-per-type and --generate-xml-schema are " + << "incompatible" << endl + << "info: use --generate-xml-schema in a separate invocation " + << "of the compiler" << endl; + + return 1; + } + + if (!use && + !disabled_w_all && disabled_w.find ("D001") == disabled_w.end ()) + { + e << "warning D001: --extern-xml-schema is recommended when " + << "--file-per-type is specified to reduce generated code size" + << endl; + } + } + } + + // + // + FileList file_list; + AutoUnlinks unlinks; + UnsignedLong sloc (0); + + LocationTranslator loc_translator ( + common_ops.value (), + common_ops.value (), + common_ops.value ()); + + AnonymousNameTranslator anon_translator ( + common_ops.value (), + common_ops.value ()); + + Boolean gen_hybrid (cmd == "cxx-hybrid"); + + Boolean gen_parser ( + cmd == "cxx-parser" || + (gen_hybrid && h_ops->value ())); + + Boolean gen_serializer ( + cmd == "cxx-serializer" || + (gen_hybrid && h_ops->value ())); + + if (!fpt) + { + // File-per-schema compilation mode. + // + for (Size i (1); i < args.size (); ++i) + { + // Parse schema. + // + SemanticGraph::Path tu; + + try + { + tu = SemanticGraph::Path (args[i], boost::filesystem::native); + } + catch (SemanticGraph::InvalidPath const&) + { + e << "error: '" << args[i] << "' is not a valid " + << "filesystem path" << endl; + + return 1; + } + + XSDFrontend::Parser parser ( + true, + !common_ops.value (), + loc_translator, + disabled_w); + + Evptr schema; + + if (cmd == "cxx-parser" || + cmd == "cxx-serializer" || + cmd == "cxx-hybrid") + { + // See if we are generating code for the XML Schema namespace. + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + Boolean gen_xml_schema (false); + + if (cmd == "cxx-parser") + { + gen_xml_schema = + p_ops->value (); + + if (gen_xml_schema) + { + if (NarrowString name = + p_ops->value ()) + { + if (tu.native_file_string () != name) + gen_xml_schema = false; + } + } + } + else if (cmd == "cxx-serializer") + { + gen_xml_schema = + s_ops->value (); + + if (gen_xml_schema) + { + if (NarrowString name = + s_ops->value ()) + { + if (tu.native_file_string () != name) + gen_xml_schema = false; + } + } + } + else if (cmd == "cxx-hybrid") + { + gen_xml_schema = + h_ops->value (); + + if (gen_xml_schema) + { + if (NarrowString name = + h_ops->value ()) + { + if (tu.native_file_string () != name) + gen_xml_schema = false; + } + } + } + + if (gen_xml_schema) + schema = parser.xml_schema (tu); + else + schema = parser.parse (tu); + } + else + schema = parser.parse (tu); + + // Morph anonymous types. + // + if (!common_ops.value ()) + { + try + { + Transformations::Anonymous trans (anon_translator); + trans.transform (*schema, tu, true); + } + catch (Transformations::Anonymous::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } + + // Simplify the schema graph. + // + { + Transformations::Simplifier trans; + trans.transform (*schema, tu); + } + + // Calculate type sizes. + // + if (gen_hybrid) + CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, tu); + + // Try to rearrange definitions so that there is no forward + // inheritance. + // + try + { + Processing::Inheritance::Processor proc; + proc.process (*schema, tu, gen_hybrid ? "fixed" : 0); + } + catch (Processing::Inheritance::Processor::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + + // Normalize and annotate complex content restrictions. + // + if (gen_parser || gen_serializer) + { + try + { + Transformations::Restriction trans; + trans.transform (*schema, tu); + } + catch (Transformations::Restriction::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } + + // Generate mapping. + // + TypeMap::Namespaces parser_type_map, serializer_type_map; + + if (gen_hybrid) + { + try + { + sloc += CXX::Hybrid::Generator::generate_tree ( + *h_ops, + *schema, + tu, + disabled_w, + parser_type_map, + serializer_type_map, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + + if (gen_parser) + { + try + { + sloc += CXX::Parser::Generator::generate ( + *p_ops, + *schema, + tu, + parser_type_map, + true, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Parser::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + + if (gen_serializer) + { + try + { + sloc += CXX::Serializer::Generator::generate ( + *s_ops, + *schema, + tu, + serializer_type_map, + true, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Serializer::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + + if (gen_hybrid) + { + if (gen_parser) + { + try + { + sloc += CXX::Hybrid::Generator::generate_parser ( + *h_ops, + *schema, + tu, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + + if (gen_serializer) + { + try + { + sloc += CXX::Hybrid::Generator::generate_serializer ( + *h_ops, + *schema, + tu, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + } + } + } + else + { + // File-per-type compilation mode. + // + SemanticGraph::Paths paths; + + for (Size i (1); i < args.size (); ++i) + { + try + { + paths.push_back ( + SemanticGraph::Path (args[i], boost::filesystem::native)); + } + catch (SemanticGraph::InvalidPath const&) + { + e << "error: '" << args[i] << "' is not a valid " + << "filesystem path" << endl; + + return 1; + } + } + + if (paths.size () > 1 && + ((cmd == "cxx-parser" && + p_ops->value ()) || + (cmd == "cxx-serializer" && + s_ops->value ()))) + { + e << "info: generating test driver for the first schema only: '" << + paths[0] << "'" << endl; + } + + XSDFrontend::Parser parser ( + cmd != "cxx-hybrid", + !common_ops.value (), + loc_translator, + disabled_w); + + Evptr schema (parser.parse (paths)); + + // Morph anonymous types. + // + if (!common_ops.value ()) + { + try + { + Transformations::Anonymous trans (anon_translator); + trans.transform (*schema, "", false); + } + catch (Transformations::Anonymous::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } + + // Simplify the schema graph. + // + { + Transformations::Simplifier trans; + trans.transform (*schema, ""); + } + + // Calculate type sizes. + // + if (gen_hybrid) + CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, ""); + + // Normalize and annotate complex content restrictions. + // + if (gen_parser || gen_serializer) + { + try + { + Transformations::Restriction trans; + trans.transform (*schema, ""); + } + catch (Transformations::Restriction::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } + + // Rearrange the graph so that each type is in a seperate + // schema file. + // + typedef Cult::Containers::Vector Schemas; + + TypeSchemaTranslator type_translator ( + common_ops.value (), + common_ops.value ()); + + Transformations::SchemaPerType trans ( + type_translator, gen_hybrid ? "fixed" : 0); + Schemas schemas (trans.transform (*schema)); + + // Generate code. + // + for (Schemas::Iterator b (schemas.begin ()), i (b), e (schemas.end ()); + i != e; ++i) + { + SemanticGraph::Schema& s (**i); + SemanticGraph::Path path (s.used_begin ()->path ()); + + TypeMap::Namespaces parser_type_map, serializer_type_map; + + if (gen_hybrid) + { + try + { + sloc += CXX::Hybrid::Generator::generate_tree ( + *h_ops, + s, + path, + disabled_w, + parser_type_map, + serializer_type_map, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostic has already been issued. + // + return 1; + } + } + + if (gen_parser) + { + try + { + // Only generate driver for the first schema. + // + sloc += CXX::Parser::Generator::generate ( + *p_ops, + s, + path, + parser_type_map, + i == b, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Parser::Generator::Failed const&) + { + // Diagnostic has already been issued. + // + return 1; + } + } + + if (gen_serializer) + { + try + { + // Only generate driver for the first schema. + // + sloc += CXX::Serializer::Generator::generate ( + *s_ops, + s, + path, + serializer_type_map, + i == b, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Serializer::Generator::Failed const&) + { + // Diagnostic has already been issued. + // + return 1; + } + } + + if (gen_hybrid) + { + if (gen_parser) + { + try + { + sloc += CXX::Hybrid::Generator::generate_parser ( + *h_ops, + s, + path, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + + if (gen_serializer) + { + try + { + sloc += CXX::Hybrid::Generator::generate_serializer ( + *h_ops, + s, + path, + disabled_w, + file_list, + unlinks); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + // Diagnostics has already been issued. + // + return 1; + } + } + } + } + } + + // See if we need to produce the file list. + // + if (NarrowString fl = common_ops.value ()) + { + typedef boost::filesystem::ofstream OutputFileStream; + + try + { + OutputFileStream ofs; + SemanticGraph::Path path (fl); + + ofs.open (fl, std::ios_base::out); + + if (!ofs.is_open ()) + { + wcerr << path << ": error: unable to open in write mode" << endl; + return 1; + } + + NarrowString d (common_ops.value ()); + expand_nl (d); + + if (NarrowString p = common_ops.value ()) + { + expand_nl (p); + ofs << p; + } + + for (FileList::Iterator i (file_list.begin ()), e (file_list.end ()); + i != e;) + { + ofs << *i; + + if (++i != e) + ofs << d; + } + + if (NarrowString e = common_ops.value ()) + { + expand_nl (e); + ofs << e; + } + } + catch (SemanticGraph::InvalidPath const&) + { + wcerr << "error: '" << fl.c_str () << "' is not a valid " + << "filesystem path" << endl; + return 1; + } + } + + if (show_sloc) + e << "total: " << sloc << endl; + + if (UnsignedLong sloc_limit = common_ops.value ()) + { + if (sloc_limit < sloc) + { + e << "error: SLOC limit of " << sloc_limit + << " lines has been exceeded" << endl; + + return 1; + } + } + + unlinks.cancel (); + + return 0; + } + catch (LocationTranslator::Failed const&) + { + // Diagnostic has already been issued. + } + catch (AnonymousNameTranslator::Failed const&) + { + // Diagnostic has already been issued. + } + catch (TypeSchemaTranslator::Failed const&) + { + // Diagnostic has already been issued. + } + catch (Transformations::SchemaPerType::Failed const&) + { + // Diagnostic has already been issued. + } + catch (XSDFrontend::InvalidSchema const&) + { + // Diagnostic has already been issued. + } + catch (CLI::UnexpectedOption const& e) + { + wcerr << "error: unknown option '" << e.option ().c_str () << "'" << endl + << "info: try '" << argv[0] << " help' for usage information" + << endl; + } + catch (CLI::OptionFormat const& e) + { + wcerr << "error: value for option '" << e.option ().c_str () + << "' is invalid or missing" << endl + << "info: try '" << argv[0] << " help' for usage information" + << endl; + } + catch (CLI::OptionFile const& e) + { + if (e.value ()) + wcerr << "error: " << e.value ().c_str () << ": " + << e.description ().c_str () << endl; + else + wcerr << "error: missing --options-file argument" << endl; + } + + return 1; +} + +// LocationTranslator +// + +LocationTranslator:: +LocationTranslator (NarrowStrings const& map, + NarrowStrings const& regex, + Boolean trace) + : trace_ (trace) +{ + // Map. + // + for (NarrowStrings::ConstIterator i (map.begin ()); i != map.end (); ++i) + { + // Split the string in two parts at the last '='. + // + Size pos (i->rfind ('=')); + + if (pos == NarrowString::npos) + { + wcerr << "error: invalid location map: '" << i->c_str () << + "': delimiter ('=') not found" << endl; + + throw Failed (); + } + + map_[NarrowString (*i, 0, pos)] = NarrowString (*i, pos + 1); + } + + // Regex. + // + for (NarrowStrings::ConstIterator i (regex.begin ()); i != regex.end (); ++i) + { + try + { + regex_.push_back (Regex (*i)); + } + catch (RegexFormat const& e) + { + wcerr << "error: invalid location regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + } +} + +NarrowString LocationTranslator:: +translate (NarrowString const& l) +{ + // First check the cache. + // + Cache::ConstIterator ci (cache_.find (l)); + + if (ci != cache_.end ()) + return ci->second; + + // Then check the direct map. + // + Map::ConstIterator mi (map_.find (l)); + + if (mi != map_.end ()) + { + cache_[l] = mi->second; + return mi->second; + } + + // Finally try regex. + // + if (trace_) + wcerr << "location: '" << l.c_str () << "'" << endl; + + for (RegexVector::ReverseIterator i (regex_.rbegin ()); + i != regex_.rend (); ++i) + { + if (trace_) + wcerr << "try: '" << i->pattern () << "' : "; + + if (i->match (l)) + { + NarrowString r (i->merge (l)); + + if (trace_) + wcerr << "'" << r.c_str () << "' : +" << endl; + + cache_[l] = r; + return r; + } + + if (trace_) + wcerr << '-' << endl; + } + + // No match - return the original location. + // + cache_[l] = l; + return l; +} + +// AnonymousNameTranslator +// + +AnonymousNameTranslator:: +AnonymousNameTranslator (NarrowStrings const& regex, Boolean trace) + : trace_ (trace) +{ + for (NarrowStrings::ConstIterator i (regex.begin ()); i != regex.end (); ++i) + { + try + { + regex_.push_back (Regex (*i)); + } + catch (RegexFormat const& e) + { + wcerr << "error: invalid anonymous type regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } +} + +WideString AnonymousNameTranslator:: +translate (WideString const& file, + WideString const& ns, + WideString const& name, + WideString const& xpath) +{ + if (regex_.empty ()) + return name; + + WideString s (file + L' ' + ns + L' ' + xpath); + + if (trace_) + wcerr << "anonymous type: '" << s << "'" << endl; + + for (RegexVector::ReverseIterator i (regex_.rbegin ()); + i != regex_.rend (); ++i) + { + if (trace_) + wcerr << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + WideString r (i->merge (s)); + + if (trace_) + wcerr << "'" << r << "' : +" << endl; + + return r; + } + + if (trace_) + wcerr << '-' << endl; + } + + // No match - return the name. + // + return name; +} + +// TypeSchemaTranslator +// + +TypeSchemaTranslator:: +TypeSchemaTranslator (NarrowStrings const& regex, Boolean trace) + : trace_ (trace) +{ + for (NarrowStrings::ConstIterator i (regex.begin ()); i != regex.end (); ++i) + { + try + { + regex_.push_back (Regex (*i)); + } + catch (RegexFormat const& e) + { + wcerr << "error: invalid type file regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } +} + +WideString TypeSchemaTranslator:: +translate (WideString const& ns, WideString const& name) +{ + if (regex_.empty ()) + return name; + + WideString s (ns + L' ' + name); + + if (trace_) + wcerr << "type: '" << s << "'" << endl; + + for (RegexVector::ReverseIterator i (regex_.rbegin ()); + i != regex_.rend (); ++i) + { + if (trace_) + wcerr << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + WideString r (i->merge (s)); + + if (trace_) + wcerr << "'" << r << "' : +" << endl; + + return r; + } + + if (trace_) + wcerr << '-' << endl; + } + + // No match - return the type name. + // + return name; +} + +// +// +Void +expand_nl (NarrowString& s) +{ + for (Size i (0); i < s.size ();) + { + if (s[i] == '\\' && (i + 1) < s.size () && s[i + 1] == 'n') + { + NarrowString tmp (s, 0, i); + tmp += '\n'; + tmp.append (s.c_str () + i + 2); + s = tmp; + } + else + ++i; + } +} diff --git a/xsde/xsde.hxx b/xsde/xsde.hxx new file mode 100644 index 0000000..2da67d5 --- /dev/null +++ b/xsde/xsde.hxx @@ -0,0 +1,79 @@ +// file : xsde/xsde.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSDE_HXX +#define XSDE_HXX + +#include // Path + +#include +#include +#include + +#include // std::remove + +using namespace Cult::Types; + +// +// +typedef Cult::Containers::Set WarningSet; + +// +// +typedef Cult::Containers::Vector FileList; + +// +// +struct AutoUnlink +{ + AutoUnlink (XSDFrontend::SemanticGraph::Path const& file) + : file_ (file), canceled_ (false) + { + } + + ~AutoUnlink () + { + if (!canceled_) + { + std::remove (file_.native_file_string ().c_str ()); + } + } + + void + cancel () + { + canceled_ = true; + } + +private: + XSDFrontend::SemanticGraph::Path file_; + Boolean canceled_; +}; + +// +// +struct AutoUnlinks +{ + Void + add (XSDFrontend::SemanticGraph::Path const& file) + { + unlinks_.push_back (Evptr (new AutoUnlink (file))); + } + + Void + cancel () + { + for (Unlinks::Iterator i (unlinks_.begin ()); i != unlinks_.end (); ++i) + { + (*i)->cancel (); + } + } + +private: + typedef Cult::Containers::Vector > Unlinks; + Unlinks unlinks_; +}; + +#endif // XSDE_HXX -- cgit v1.1