aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
commit707cc94fe52463870a9c6c8e2e66eaaa389e601d (patch)
tree13e10ff28bf4455d915f9d59b401bdbb62a393cb
Start tracking XSD/e with git after version 3.0.03.0.0
-rw-r--r--GPLv2340
-rw-r--r--INSTALL35
-rw-r--r--LICENSE12
-rw-r--r--NEWS227
-rw-r--r--README19
-rw-r--r--build/bootstrap.make54
-rw-r--r--build/configuration-rules.make18
-rw-r--r--build/configuration.make54
-rwxr-xr-xbuild/configure160
-rw-r--r--build/import/libbackend-elements/LICENSE340
-rw-r--r--build/import/libbackend-elements/configuration-rules.make15
-rwxr-xr-xbuild/import/libbackend-elements/configure55
-rw-r--r--build/import/libbackend-elements/stub.make32
-rw-r--r--build/import/libboost/LICENSE340
-rw-r--r--build/import/libboost/configuration-rules.make15
-rwxr-xr-xbuild/import/libboost/configure83
-rw-r--r--build/import/libboost/date-time/rules.make39
-rw-r--r--build/import/libboost/date-time/stub.make32
-rw-r--r--build/import/libboost/filesystem/rules.make41
-rw-r--r--build/import/libboost/filesystem/stub.make32
-rw-r--r--build/import/libboost/regex/rules.make38
-rw-r--r--build/import/libboost/regex/stub.make32
-rw-r--r--build/import/libboost/version1
-rw-r--r--build/import/libcult/LICENSE340
-rw-r--r--build/import/libcult/configuration-rules.make15
-rwxr-xr-xbuild/import/libcult/configure55
-rw-r--r--build/import/libcult/stub.make30
-rw-r--r--build/import/libxsd-frontend/LICENSE22
-rw-r--r--build/import/libxsd-frontend/configuration-rules.make15
-rwxr-xr-xbuild/import/libxsd-frontend/configure55
-rw-r--r--build/import/libxsd-frontend/stub.make30
-rw-r--r--build/xsde/hybrid/xsd-cxx.make139
-rw-r--r--build/xsde/parser/xsd-cxx.make103
-rw-r--r--build/xsde/serializer/xsd-cxx.make103
-rw-r--r--documentation/cxx/hybrid/guide/figure-1.pngbin0 -> 11933 bytes
-rw-r--r--documentation/cxx/hybrid/guide/figure-1.svg217
-rw-r--r--documentation/cxx/hybrid/guide/guide.html2ps65
-rw-r--r--documentation/cxx/hybrid/guide/index.xhtml5099
-rw-r--r--documentation/cxx/hybrid/guide/makefile12
-rw-r--r--documentation/cxx/parser/guide/figure-1.pngbin0 -> 34195 bytes
-rw-r--r--documentation/cxx/parser/guide/figure-1.svg373
-rw-r--r--documentation/cxx/parser/guide/guide.html2ps65
-rw-r--r--documentation/cxx/parser/guide/index.xhtml5236
-rw-r--r--documentation/cxx/parser/guide/makefile12
-rw-r--r--documentation/cxx/serializer/guide/figure-1.pngbin0 -> 30198 bytes
-rw-r--r--documentation/cxx/serializer/guide/figure-1.svg372
-rw-r--r--documentation/cxx/serializer/guide/guide.html2ps65
-rw-r--r--documentation/cxx/serializer/guide/index.xhtml6391
-rw-r--r--documentation/cxx/serializer/guide/makefile12
-rw-r--r--documentation/default.css319
-rw-r--r--documentation/makefile18
-rw-r--r--documentation/xsde.11940
-rw-r--r--documentation/xsde.xhtml1578
-rw-r--r--examples/cxx/hybrid/README37
-rw-r--r--examples/cxx/hybrid/compositors/README28
-rw-r--r--examples/cxx/hybrid/compositors/compositors.xsd44
-rw-r--r--examples/cxx/hybrid/compositors/driver.cxx89
-rw-r--r--examples/cxx/hybrid/compositors/makefile62
-rw-r--r--examples/cxx/hybrid/filter/README71
-rw-r--r--examples/cxx/hybrid/filter/driver.cxx98
-rw-r--r--examples/cxx/hybrid/filter/makefile80
-rw-r--r--examples/cxx/hybrid/filter/people-custom-pimpl.cxx26
-rw-r--r--examples/cxx/hybrid/filter/people-custom-pimpl.hxx24
-rw-r--r--examples/cxx/hybrid/filter/people-custom-simpl.cxx32
-rw-r--r--examples/cxx/hybrid/filter/people-custom-simpl.hxx23
-rw-r--r--examples/cxx/hybrid/filter/people.xml35
-rw-r--r--examples/cxx/hybrid/filter/people.xsd37
-rw-r--r--examples/cxx/hybrid/hello/README37
-rw-r--r--examples/cxx/hybrid/hello/driver.cxx66
-rw-r--r--examples/cxx/hybrid/hello/hello.xml20
-rw-r--r--examples/cxx/hybrid/hello/hello.xsd22
-rw-r--r--examples/cxx/hybrid/hello/makefile71
-rw-r--r--examples/cxx/hybrid/library/README45
-rw-r--r--examples/cxx/hybrid/library/driver.cxx159
-rw-r--r--examples/cxx/hybrid/library/library.xml53
-rw-r--r--examples/cxx/hybrid/library/library.xsd69
-rw-r--r--examples/cxx/hybrid/library/makefile78
-rw-r--r--examples/cxx/hybrid/makefile36
-rw-r--r--examples/cxx/hybrid/minimal/README46
-rw-r--r--examples/cxx/hybrid/minimal/driver.cxx265
-rw-r--r--examples/cxx/hybrid/minimal/makefile78
-rw-r--r--examples/cxx/hybrid/minimal/people.xml28
-rw-r--r--examples/cxx/hybrid/minimal/people.xsd37
-rw-r--r--examples/cxx/hybrid/multiroot/README48
-rw-r--r--examples/cxx/hybrid/multiroot/balance.xml17
-rw-r--r--examples/cxx/hybrid/multiroot/deposit.xml18
-rw-r--r--examples/cxx/hybrid/multiroot/driver.cxx224
-rw-r--r--examples/cxx/hybrid/multiroot/makefile72
-rw-r--r--examples/cxx/hybrid/multiroot/protocol.xsd51
-rw-r--r--examples/cxx/hybrid/multiroot/withdraw.xml18
-rw-r--r--examples/cxx/hybrid/streaming/README71
-rw-r--r--examples/cxx/hybrid/streaming/driver.cxx83
-rw-r--r--examples/cxx/hybrid/streaming/makefile79
-rw-r--r--examples/cxx/hybrid/streaming/object-pimpl.cxx47
-rw-r--r--examples/cxx/hybrid/streaming/object-pimpl.hxx33
-rw-r--r--examples/cxx/hybrid/streaming/object-simpl.cxx69
-rw-r--r--examples/cxx/hybrid/streaming/object-simpl.hxx32
-rw-r--r--examples/cxx/hybrid/streaming/position.xml22
-rw-r--r--examples/cxx/hybrid/streaming/position.xsd28
-rw-r--r--examples/cxx/hybrid/wildcard/README76
-rw-r--r--examples/cxx/hybrid/wildcard/body.cxx26
-rw-r--r--examples/cxx/hybrid/wildcard/body.hxx81
-rw-r--r--examples/cxx/hybrid/wildcard/driver.cxx188
-rw-r--r--examples/cxx/hybrid/wildcard/email.xml31
-rw-r--r--examples/cxx/hybrid/wildcard/email.xsd45
-rw-r--r--examples/cxx/hybrid/wildcard/envelope-pimpl.cxx111
-rw-r--r--examples/cxx/hybrid/wildcard/envelope-pimpl.hxx81
-rw-r--r--examples/cxx/hybrid/wildcard/envelope-simpl.cxx137
-rw-r--r--examples/cxx/hybrid/wildcard/envelope-simpl.hxx67
-rw-r--r--examples/cxx/hybrid/wildcard/makefile80
-rw-r--r--examples/cxx/makefile20
-rw-r--r--examples/cxx/parser/README32
-rw-r--r--examples/cxx/parser/generated/README36
-rw-r--r--examples/cxx/parser/generated/library.xml53
-rw-r--r--examples/cxx/parser/generated/library.xsd79
-rw-r--r--examples/cxx/parser/generated/makefile71
-rw-r--r--examples/cxx/parser/hello/README33
-rw-r--r--examples/cxx/parser/hello/driver.cxx82
-rw-r--r--examples/cxx/parser/hello/hello.xml20
-rw-r--r--examples/cxx/parser/hello/hello.xsd22
-rw-r--r--examples/cxx/parser/hello/makefile64
-rw-r--r--examples/cxx/parser/library/README53
-rw-r--r--examples/cxx/parser/library/driver.cxx131
-rw-r--r--examples/cxx/parser/library/library-pimpl-mixin.cxx184
-rw-r--r--examples/cxx/parser/library/library-pimpl-mixin.hxx136
-rw-r--r--examples/cxx/parser/library/library-pimpl-tiein.cxx208
-rw-r--r--examples/cxx/parser/library/library-pimpl-tiein.hxx152
-rw-r--r--examples/cxx/parser/library/library.hxx242
-rw-r--r--examples/cxx/parser/library/library.map16
-rw-r--r--examples/cxx/parser/library/library.xml53
-rw-r--r--examples/cxx/parser/library/library.xsd79
-rw-r--r--examples/cxx/parser/library/makefile72
-rw-r--r--examples/cxx/parser/makefile53
-rw-r--r--examples/cxx/parser/minimal/README51
-rw-r--r--examples/cxx/parser/minimal/driver.cxx145
-rw-r--r--examples/cxx/parser/minimal/gender.hxx14
-rw-r--r--examples/cxx/parser/minimal/makefile66
-rw-r--r--examples/cxx/parser/minimal/people-pimpl-mixin.hxx82
-rw-r--r--examples/cxx/parser/minimal/people-pimpl-tiein.hxx90
-rw-r--r--examples/cxx/parser/minimal/people.map7
-rw-r--r--examples/cxx/parser/minimal/people.xml28
-rw-r--r--examples/cxx/parser/minimal/people.xsd37
-rw-r--r--examples/cxx/parser/mixed/README54
-rw-r--r--examples/cxx/parser/mixed/anchor.hxx34
-rw-r--r--examples/cxx/parser/mixed/driver.cxx123
-rw-r--r--examples/cxx/parser/mixed/makefile66
-rw-r--r--examples/cxx/parser/mixed/text.map7
-rw-r--r--examples/cxx/parser/mixed/text.xml18
-rw-r--r--examples/cxx/parser/mixed/text.xsd29
-rw-r--r--examples/cxx/parser/multiroot/README61
-rw-r--r--examples/cxx/parser/multiroot/balance.xml17
-rw-r--r--examples/cxx/parser/multiroot/deposit.xml18
-rw-r--r--examples/cxx/parser/multiroot/driver.cxx245
-rw-r--r--examples/cxx/parser/multiroot/makefile71
-rw-r--r--examples/cxx/parser/multiroot/protocol-pimpl-mixin.cxx47
-rw-r--r--examples/cxx/parser/multiroot/protocol-pimpl-mixin.hxx49
-rw-r--r--examples/cxx/parser/multiroot/protocol-pimpl-tiein.cxx59
-rw-r--r--examples/cxx/parser/multiroot/protocol-pimpl-tiein.hxx55
-rw-r--r--examples/cxx/parser/multiroot/protocol.hxx62
-rw-r--r--examples/cxx/parser/multiroot/protocol.map12
-rw-r--r--examples/cxx/parser/multiroot/protocol.xsd51
-rw-r--r--examples/cxx/parser/multiroot/withdraw.xml18
-rw-r--r--examples/cxx/parser/polymorphism/README38
-rw-r--r--examples/cxx/parser/polymorphism/driver.cxx115
-rw-r--r--examples/cxx/parser/polymorphism/makefile71
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-mixin.cxx86
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-mixin.hxx69
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-tiein.cxx104
-rw-r--r--examples/cxx/parser/polymorphism/supermen-pimpl-tiein.hxx81
-rw-r--r--examples/cxx/parser/polymorphism/supermen.xml26
-rw-r--r--examples/cxx/parser/polymorphism/supermen.xsd49
-rw-r--r--examples/cxx/parser/polyroot/README47
-rw-r--r--examples/cxx/parser/polyroot/batman.xml17
-rw-r--r--examples/cxx/parser/polyroot/driver.cxx216
-rw-r--r--examples/cxx/parser/polyroot/makefile71
-rw-r--r--examples/cxx/parser/polyroot/person.xml16
-rw-r--r--examples/cxx/parser/polyroot/superman.xml17
-rw-r--r--examples/cxx/parser/polyroot/supermen-pimpl-mixin.cxx83
-rw-r--r--examples/cxx/parser/polyroot/supermen-pimpl-mixin.hxx65
-rw-r--r--examples/cxx/parser/polyroot/supermen-pimpl-tiein.cxx101
-rw-r--r--examples/cxx/parser/polyroot/supermen-pimpl-tiein.hxx77
-rw-r--r--examples/cxx/parser/polyroot/supermen.xsd40
-rw-r--r--examples/cxx/parser/wildcard/README33
-rw-r--r--examples/cxx/parser/wildcard/driver.cxx359
-rw-r--r--examples/cxx/parser/wildcard/email.xml32
-rw-r--r--examples/cxx/parser/wildcard/email.xsd51
-rw-r--r--examples/cxx/parser/wildcard/makefile64
-rw-r--r--examples/cxx/serializer/README20
-rw-r--r--examples/cxx/serializer/hello/README25
-rw-r--r--examples/cxx/serializer/hello/driver.cxx90
-rw-r--r--examples/cxx/serializer/hello/hello.xsd22
-rw-r--r--examples/cxx/serializer/hello/makefile64
-rw-r--r--examples/cxx/serializer/library/README44
-rw-r--r--examples/cxx/serializer/library/driver.cxx140
-rw-r--r--examples/cxx/serializer/library/library-simpl-mixin.cxx184
-rw-r--r--examples/cxx/serializer/library/library-simpl-mixin.hxx138
-rw-r--r--examples/cxx/serializer/library/library-simpl-tiein.cxx208
-rw-r--r--examples/cxx/serializer/library/library-simpl-tiein.hxx154
-rw-r--r--examples/cxx/serializer/library/library.hxx270
-rw-r--r--examples/cxx/serializer/library/library.map22
-rw-r--r--examples/cxx/serializer/library/library.xsd79
-rw-r--r--examples/cxx/serializer/library/makefile72
-rw-r--r--examples/cxx/serializer/makefile49
-rw-r--r--examples/cxx/serializer/minimal/README47
-rw-r--r--examples/cxx/serializer/minimal/driver.cxx139
-rw-r--r--examples/cxx/serializer/minimal/makefile66
-rw-r--r--examples/cxx/serializer/minimal/people-simpl-mixin.hxx82
-rw-r--r--examples/cxx/serializer/minimal/people-simpl-tiein.hxx90
-rw-r--r--examples/cxx/serializer/minimal/people.hxx30
-rw-r--r--examples/cxx/serializer/minimal/people.map9
-rw-r--r--examples/cxx/serializer/minimal/people.xsd37
-rw-r--r--examples/cxx/serializer/polymorphism/README44
-rw-r--r--examples/cxx/serializer/polymorphism/driver.cxx120
-rw-r--r--examples/cxx/serializer/polymorphism/makefile73
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-mixin.cxx83
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-mixin.hxx51
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-tiein.cxx108
-rw-r--r--examples/cxx/serializer/polymorphism/supermen-simpl-tiein.hxx69
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.hxx129
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.map10
-rw-r--r--examples/cxx/serializer/polymorphism/supermen.xsd49
-rw-r--r--examples/cxx/serializer/polyroot/README46
-rw-r--r--examples/cxx/serializer/polyroot/driver.cxx142
-rw-r--r--examples/cxx/serializer/polyroot/makefile73
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.cxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-mixin.hxx35
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.cxx59
-rw-r--r--examples/cxx/serializer/polyroot/supermen-simpl-tiein.hxx53
-rw-r--r--examples/cxx/serializer/polyroot/supermen.hxx129
-rw-r--r--examples/cxx/serializer/polyroot/supermen.map9
-rw-r--r--examples/cxx/serializer/polyroot/supermen.xsd41
-rw-r--r--examples/cxx/serializer/wildcard/README37
-rw-r--r--examples/cxx/serializer/wildcard/driver.cxx410
-rw-r--r--examples/cxx/serializer/wildcard/email.hxx194
-rw-r--r--examples/cxx/serializer/wildcard/email.map12
-rw-r--r--examples/cxx/serializer/wildcard/email.xsd51
-rw-r--r--examples/cxx/serializer/wildcard/makefile66
-rw-r--r--examples/makefile20
-rw-r--r--libxsde/makefile26
-rw-r--r--libxsde/xsde/c/expat/COPYING22
-rw-r--r--libxsde/xsde/c/expat/ascii.h85
-rw-r--r--libxsde/xsde/c/expat/asciitab.h36
-rw-r--r--libxsde/xsde/c/expat/config.h42
-rw-r--r--libxsde/xsde/c/expat/expat.h1013
-rw-r--r--libxsde/xsde/c/expat/expat_external.h119
-rw-r--r--libxsde/xsde/c/expat/iasciitab.h37
-rw-r--r--libxsde/xsde/c/expat/internal.h73
-rw-r--r--libxsde/xsde/c/expat/latin1tab.h36
-rw-r--r--libxsde/xsde/c/expat/nametab.h150
-rw-r--r--libxsde/xsde/c/expat/utf8tab.h37
-rw-r--r--libxsde/xsde/c/expat/xmlparse.c6260
-rw-r--r--libxsde/xsde/c/expat/xmlrole.c1466
-rw-r--r--libxsde/xsde/c/expat/xmlrole.h114
-rw-r--r--libxsde/xsde/c/expat/xmltok.c1671
-rw-r--r--libxsde/xsde/c/expat/xmltok.h316
-rw-r--r--libxsde/xsde/c/expat/xmltok_impl.c1792
-rw-r--r--libxsde/xsde/c/expat/xmltok_impl.h46
-rw-r--r--libxsde/xsde/c/expat/xmltok_ns.c106
-rw-r--r--libxsde/xsde/c/genx/COPYING39
-rw-r--r--libxsde/xsde/c/genx/char-props.c380
-rw-r--r--libxsde/xsde/c/genx/genx.c2118
-rw-r--r--libxsde/xsde/c/genx/genx.h322
-rw-r--r--libxsde/xsde/cxx/buffer.cxx145
-rw-r--r--libxsde/xsde/cxx/buffer.hxx149
-rw-r--r--libxsde/xsde/cxx/buffer.ixx213
-rw-r--r--libxsde/xsde/cxx/compilers/vc-6/post.hxx6
-rw-r--r--libxsde/xsde/cxx/compilers/vc-6/pre.hxx33
-rw-r--r--libxsde/xsde/cxx/compilers/vc-7/post.hxx6
-rw-r--r--libxsde/xsde/cxx/compilers/vc-7/pre.hxx37
-rw-r--r--libxsde/xsde/cxx/compilers/vc-8/post.hxx6
-rw-r--r--libxsde/xsde/cxx/compilers/vc-8/pre.hxx30
-rw-r--r--libxsde/xsde/cxx/config.hxx27
-rw-r--r--libxsde/xsde/cxx/date-time.hxx415
-rw-r--r--libxsde/xsde/cxx/date-time.ixx725
-rw-r--r--libxsde/xsde/cxx/errno.hxx23
-rw-r--r--libxsde/xsde/cxx/errno.ixx44
-rw-r--r--libxsde/xsde/cxx/exceptions.hxx21
-rw-r--r--libxsde/xsde/cxx/hashmap.cxx210
-rw-r--r--libxsde/xsde/cxx/hashmap.hxx156
-rw-r--r--libxsde/xsde/cxx/hashmap.ixx177
-rw-r--r--libxsde/xsde/cxx/hybrid/any-type.hxx26
-rw-r--r--libxsde/xsde/cxx/hybrid/base.hxx370
-rw-r--r--libxsde/xsde/cxx/hybrid/sequence.cxx31
-rw-r--r--libxsde/xsde/cxx/hybrid/sequence.hxx921
-rw-r--r--libxsde/xsde/cxx/hybrid/sequence.ixx881
-rw-r--r--libxsde/xsde/cxx/hybrid/sequence.txx133
-rw-r--r--libxsde/xsde/cxx/hybrid/xml-schema.hxx23
-rw-r--r--libxsde/xsde/cxx/parser/context.cxx18
-rw-r--r--libxsde/xsde/cxx/parser/context.hxx139
-rw-r--r--libxsde/xsde/cxx/parser/context.ixx91
-rw-r--r--libxsde/xsde/cxx/parser/elements.cxx201
-rw-r--r--libxsde/xsde/cxx/parser/elements.hxx248
-rw-r--r--libxsde/xsde/cxx/parser/elements.ixx221
-rw-r--r--libxsde/xsde/cxx/parser/error.cxx20
-rw-r--r--libxsde/xsde/cxx/parser/error.hxx135
-rw-r--r--libxsde/xsde/cxx/parser/error.ixx143
-rw-r--r--libxsde/xsde/cxx/parser/exceptions.cxx64
-rw-r--r--libxsde/xsde/cxx/parser/exceptions.hxx103
-rw-r--r--libxsde/xsde/cxx/parser/exceptions.ixx66
-rw-r--r--libxsde/xsde/cxx/parser/expat/document.cxx1044
-rw-r--r--libxsde/xsde/cxx/parser/expat/document.hxx337
-rw-r--r--libxsde/xsde/cxx/parser/expat/document.ixx53
-rw-r--r--libxsde/xsde/cxx/parser/expat/xml-error.cxx25
-rw-r--r--libxsde/xsde/cxx/parser/expat/xml-error.hxx28
-rw-r--r--libxsde/xsde/cxx/parser/map.cxx35
-rw-r--r--libxsde/xsde/cxx/parser/map.hxx87
-rw-r--r--libxsde/xsde/cxx/parser/map.ixx41
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/any-type.hxx43
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx241
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/base64-binary.hxx55
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/boolean.cxx80
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/boolean.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/byte.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/byte.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/date-time.cxx154
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/date-time.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/date.cxx126
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/date.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/decimal.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/decimal.hxx46
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/double.cxx62
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/double.hxx46
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/duration.cxx166
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/duration.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/float.cxx76
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/float.hxx46
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gday.cxx88
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gday.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gmonth-day.cxx100
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gmonth-day.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gmonth.cxx88
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gmonth.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gyear-month.cxx121
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gyear-month.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gyear.cxx115
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/gyear.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/hex-binary.cxx159
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/hex-binary.hxx55
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/id-stl.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/id-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/id.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/id.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idref-stl.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idref-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idref.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idref.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idrefs-stl.cxx94
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idrefs-stl.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idrefs.cxx133
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/idrefs.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/int.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/int.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/integer.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/integer.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/language-stl.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/language-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/language.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/language.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/long-long.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/long-long.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/long.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/long.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/name-stl.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/name-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/name.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/name.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/ncname-stl.cxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/ncname-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/ncname.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/ncname.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/negative-integer.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/negative-integer.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtoken-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtoken.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtoken.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.cxx90
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtokens-stl.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtokens.cxx129
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/nmtokens.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/non-negative-integer.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/non-negative-integer.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/non-positive-integer.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/non-positive-integer.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/normalized-string-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/normalized-string.cxx60
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/normalized-string.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/number.cxx127
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/number.hxx37
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/parser.cxx473
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/parser.hxx196
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/parser.ixx77
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/positive-integer.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/positive-integer.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/qname-stl.cxx58
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/qname-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/qname.cxx153
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/qname.hxx55
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/short.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/short.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/string-stl.cxx38
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/string-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/string.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/string.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/time-zone.cxx53
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/time-zone.hxx32
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/time.cxx118
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/time.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/token-stl.cxx73
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/token-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/token.cxx94
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/token.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-byte.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-byte.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-int.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-int.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-long-long.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-long.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-long.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-short.cxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/unsigned-short.hxx48
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/uri-stl.cxx49
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/uri-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/uri.cxx67
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/uri.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx82
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.cxx612
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.hxx1388
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/xml-schema-pskel.ixx704
-rw-r--r--libxsde/xsde/cxx/parser/state.cxx37
-rw-r--r--libxsde/xsde/cxx/parser/state.hxx89
-rw-r--r--libxsde/xsde/cxx/parser/state.ixx102
-rw-r--r--libxsde/xsde/cxx/parser/substitution-map-load.hxx31
-rw-r--r--libxsde/xsde/cxx/parser/substitution-map.cxx236
-rw-r--r--libxsde/xsde/cxx/parser/substitution-map.hxx115
-rw-r--r--libxsde/xsde/cxx/parser/substitution-map.ixx71
-rw-r--r--libxsde/xsde/cxx/parser/validating/any-type.hxx43
-rw-r--r--libxsde/xsde/cxx/parser/validating/base64-binary.cxx281
-rw-r--r--libxsde/xsde/cxx/parser/validating/base64-binary.hxx58
-rw-r--r--libxsde/xsde/cxx/parser/validating/boolean.cxx93
-rw-r--r--libxsde/xsde/cxx/parser/validating/boolean.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/validating/byte.cxx71
-rw-r--r--libxsde/xsde/cxx/parser/validating/byte.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/date-time.cxx259
-rw-r--r--libxsde/xsde/cxx/parser/validating/date-time.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/date.cxx182
-rw-r--r--libxsde/xsde/cxx/parser/validating/date.hxx51
-rw-r--r--libxsde/xsde/cxx/parser/validating/decimal.cxx74
-rw-r--r--libxsde/xsde/cxx/parser/validating/decimal.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/double.cxx99
-rw-r--r--libxsde/xsde/cxx/parser/validating/double.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/duration.cxx265
-rw-r--r--libxsde/xsde/cxx/parser/validating/duration.hxx51
-rw-r--r--libxsde/xsde/cxx/parser/validating/float.cxx118
-rw-r--r--libxsde/xsde/cxx/parser/validating/float.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/gday.cxx112
-rw-r--r--libxsde/xsde/cxx/parser/validating/gday.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/gmonth-day.cxx137
-rw-r--r--libxsde/xsde/cxx/parser/validating/gmonth-day.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/gmonth.cxx112
-rw-r--r--libxsde/xsde/cxx/parser/validating/gmonth.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/gyear-month.cxx161
-rw-r--r--libxsde/xsde/cxx/parser/validating/gyear-month.hxx51
-rw-r--r--libxsde/xsde/cxx/parser/validating/gyear.cxx138
-rw-r--r--libxsde/xsde/cxx/parser/validating/gyear.hxx50
-rw-r--r--libxsde/xsde/cxx/parser/validating/hex-binary.cxx172
-rw-r--r--libxsde/xsde/cxx/parser/validating/hex-binary.hxx58
-rw-r--r--libxsde/xsde/cxx/parser/validating/id-stl.cxx60
-rw-r--r--libxsde/xsde/cxx/parser/validating/id-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/id.cxx80
-rw-r--r--libxsde/xsde/cxx/parser/validating/id.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/idref-stl.cxx60
-rw-r--r--libxsde/xsde/cxx/parser/validating/idref-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/idref.cxx79
-rw-r--r--libxsde/xsde/cxx/parser/validating/idref.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/idrefs-stl.cxx133
-rw-r--r--libxsde/xsde/cxx/parser/validating/idrefs-stl.hxx57
-rw-r--r--libxsde/xsde/cxx/parser/validating/idrefs.cxx136
-rw-r--r--libxsde/xsde/cxx/parser/validating/idrefs.hxx57
-rw-r--r--libxsde/xsde/cxx/parser/validating/inheritance-map-load.hxx35
-rw-r--r--libxsde/xsde/cxx/parser/validating/inheritance-map.cxx111
-rw-r--r--libxsde/xsde/cxx/parser/validating/inheritance-map.hxx63
-rw-r--r--libxsde/xsde/cxx/parser/validating/inheritance-map.ixx34
-rw-r--r--libxsde/xsde/cxx/parser/validating/int.cxx75
-rw-r--r--libxsde/xsde/cxx/parser/validating/int.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/integer.cxx75
-rw-r--r--libxsde/xsde/cxx/parser/validating/integer.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/language-stl.cxx95
-rw-r--r--libxsde/xsde/cxx/parser/validating/language-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/language.cxx114
-rw-r--r--libxsde/xsde/cxx/parser/validating/language.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/long-long.cxx75
-rw-r--r--libxsde/xsde/cxx/parser/validating/long-long.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/long.cxx75
-rw-r--r--libxsde/xsde/cxx/parser/validating/long.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/name-stl.cxx86
-rw-r--r--libxsde/xsde/cxx/parser/validating/name-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/name.cxx105
-rw-r--r--libxsde/xsde/cxx/parser/validating/name.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/ncname-stl.cxx60
-rw-r--r--libxsde/xsde/cxx/parser/validating/ncname-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/ncname.cxx79
-rw-r--r--libxsde/xsde/cxx/parser/validating/ncname.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/negative-integer.cxx71
-rw-r--r--libxsde/xsde/cxx/parser/validating/negative-integer.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtoken-stl.cxx79
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtoken-stl.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtoken.cxx98
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtoken.hxx47
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtokens-stl.cxx127
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtokens-stl.hxx57
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtokens.cxx132
-rw-r--r--libxsde/xsde/cxx/parser/validating/nmtokens.hxx57
-rw-r--r--libxsde/xsde/cxx/parser/validating/non-negative-integer.cxx66
-rw-r--r--libxsde/xsde/cxx/parser/validating/non-negative-integer.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/validating/non-positive-integer.cxx71
-rw-r--r--libxsde/xsde/cxx/parser/validating/non-positive-integer.hxx54
-rw-r--r--libxsde/xsde/cxx/parser/validating/normalized-string-stl.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/validating/normalized-string-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/normalized-string.cxx60
-rw-r--r--libxsde/xsde/cxx/parser/validating/normalized-string.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/number.cxx133
-rw-r--r--libxsde/xsde/cxx/parser/validating/number.hxx37
-rw-r--r--libxsde/xsde/cxx/parser/validating/parser.cxx633
-rw-r--r--libxsde/xsde/cxx/parser/validating/parser.hxx304
-rw-r--r--libxsde/xsde/cxx/parser/validating/parser.ixx121
-rw-r--r--libxsde/xsde/cxx/parser/validating/positive-integer.cxx64
-rw-r--r--libxsde/xsde/cxx/parser/validating/positive-integer.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/qname-stl.cxx79
-rw-r--r--libxsde/xsde/cxx/parser/validating/qname-stl.hxx49
-rw-r--r--libxsde/xsde/cxx/parser/validating/qname.cxx180
-rw-r--r--libxsde/xsde/cxx/parser/validating/qname.hxx58
-rw-r--r--libxsde/xsde/cxx/parser/validating/short.cxx70
-rw-r--r--libxsde/xsde/cxx/parser/validating/short.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/string-stl.cxx38
-rw-r--r--libxsde/xsde/cxx/parser/validating/string-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/string.cxx48
-rw-r--r--libxsde/xsde/cxx/parser/validating/string.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/time-zone.cxx79
-rw-r--r--libxsde/xsde/cxx/parser/validating/time-zone.hxx32
-rw-r--r--libxsde/xsde/cxx/parser/validating/time.cxx181
-rw-r--r--libxsde/xsde/cxx/parser/validating/time.hxx51
-rw-r--r--libxsde/xsde/cxx/parser/validating/token-stl.cxx73
-rw-r--r--libxsde/xsde/cxx/parser/validating/token-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/token.cxx94
-rw-r--r--libxsde/xsde/cxx/parser/validating/token.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-byte.cxx66
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-byte.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-int.cxx66
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-int.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-long-long.cxx64
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-long-long.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-long.cxx64
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-long.hxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-short.cxx66
-rw-r--r--libxsde/xsde/cxx/parser/validating/unsigned-short.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/validating/uri-stl.cxx53
-rw-r--r--libxsde/xsde/cxx/parser/validating/uri-stl.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/uri.cxx71
-rw-r--r--libxsde/xsde/cxx/parser/validating/uri.hxx44
-rw-r--r--libxsde/xsde/cxx/parser/validating/xml-schema-pimpl.hxx82
-rw-r--r--libxsde/xsde/cxx/parser/validating/xml-schema-pskel.cxx617
-rw-r--r--libxsde/xsde/cxx/parser/validating/xml-schema-pskel.hxx1385
-rw-r--r--libxsde/xsde/cxx/parser/validating/xml-schema-pskel.ixx704
-rw-r--r--libxsde/xsde/cxx/parser/xml-schema.hxx20
-rw-r--r--libxsde/xsde/cxx/post.hxx14
-rw-r--r--libxsde/xsde/cxx/pre.hxx15
-rw-r--r--libxsde/xsde/cxx/qname-stl.hxx59
-rw-r--r--libxsde/xsde/cxx/qname-stl.ixx82
-rw-r--r--libxsde/xsde/cxx/qname.cxx71
-rw-r--r--libxsde/xsde/cxx/qname.hxx99
-rw-r--r--libxsde/xsde/cxx/qname.ixx125
-rw-r--r--libxsde/xsde/cxx/ro-string.cxx116
-rw-r--r--libxsde/xsde/cxx/ro-string.hxx281
-rw-r--r--libxsde/xsde/cxx/ro-string.ixx409
-rw-r--r--libxsde/xsde/cxx/schema-error.cxx69
-rw-r--r--libxsde/xsde/cxx/schema-error.hxx84
-rw-r--r--libxsde/xsde/cxx/schema-error.ixx16
-rw-r--r--libxsde/xsde/cxx/sequence-base.cxx135
-rw-r--r--libxsde/xsde/cxx/sequence-base.hxx83
-rw-r--r--libxsde/xsde/cxx/sequence-base.ixx57
-rw-r--r--libxsde/xsde/cxx/serializer/context.cxx107
-rw-r--r--libxsde/xsde/cxx/serializer/context.hxx261
-rw-r--r--libxsde/xsde/cxx/serializer/context.ixx449
-rw-r--r--libxsde/xsde/cxx/serializer/elements.cxx122
-rw-r--r--libxsde/xsde/cxx/serializer/elements.hxx302
-rw-r--r--libxsde/xsde/cxx/serializer/elements.ixx569
-rw-r--r--libxsde/xsde/cxx/serializer/error.cxx20
-rw-r--r--libxsde/xsde/cxx/serializer/error.hxx121
-rw-r--r--libxsde/xsde/cxx/serializer/error.ixx128
-rw-r--r--libxsde/xsde/cxx/serializer/exceptions.cxx62
-rw-r--r--libxsde/xsde/cxx/serializer/exceptions.hxx91
-rw-r--r--libxsde/xsde/cxx/serializer/exceptions.ixx44
-rw-r--r--libxsde/xsde/cxx/serializer/genx/document.cxx822
-rw-r--r--libxsde/xsde/cxx/serializer/genx/document.hxx280
-rw-r--r--libxsde/xsde/cxx/serializer/genx/document.ixx84
-rw-r--r--libxsde/xsde/cxx/serializer/genx/xml-error.cxx48
-rw-r--r--libxsde/xsde/cxx/serializer/genx/xml-error.hxx28
-rw-r--r--libxsde/xsde/cxx/serializer/map.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/map.hxx96
-rw-r--r--libxsde/xsde/cxx/serializer/map.ixx51
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/any-type.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/base64-binary.cxx166
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/base64-binary.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/base64-binary.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/boolean.cxx30
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/boolean.hxx39
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/byte.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/byte.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date-time.cxx78
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date-time.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date-time.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date.cxx59
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/date.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/decimal.cxx54
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/decimal.hxx50
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/decimal.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/double.cxx103
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/double.hxx60
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/double.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/duration.cxx171
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/duration.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/duration.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/float.cxx103
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/float.hxx60
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/float.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gday.cxx57
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gday.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gday.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth-day.cxx59
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth-day.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth-day.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth.cxx57
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gmonth.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear-month.cxx59
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear-month.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear-month.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear.cxx54
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/gyear.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/hex-binary.cxx70
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/hex-binary.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/hex-binary.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/id-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/id-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/id.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/id.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/id.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idref-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idref-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idref.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idref.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idref.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.cxx108
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs.cxx109
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/idrefs.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/int.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/int.hxx39
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/integer.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/language-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/language-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/language.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/language.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/language.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/long-long.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/long-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/long.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/name-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/name-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/name.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/name.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/name.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/ncname-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/ncname-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/ncname.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/ncname.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/ncname.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/negative-integer.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/negative-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtoken-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtoken.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtoken.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtoken.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.cxx108
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens.cxx109
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/nmtokens.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/non-negative-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/non-positive-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.cxx36
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/normalized-string-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/normalized-string.cxx44
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/normalized-string.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/normalized-string.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/positive-integer.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/positive-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname-stl.cxx50
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname-stl.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname.cxx62
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/qname.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/serializer.cxx29
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/serializer.hxx58
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/serializer.ixx61
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/short.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/short.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/string-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/string-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/string.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/string.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/string.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/time-zone.cxx65
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/time-zone.hxx33
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/time.cxx73
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/time.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/time.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/token-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/token-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/token.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/token.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/token.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-byte.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-int.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-int.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-long-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-long.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-short.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/unsigned-short.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/uri-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/uri-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/uri.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/uri.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/uri.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx82
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.cxx560
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx1382
-rw-r--r--libxsde/xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx704
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map-load.hxx40
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.cxx248
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.hxx88
-rw-r--r--libxsde/xsde/cxx/serializer/substitution-map.ixx33
-rw-r--r--libxsde/xsde/cxx/serializer/validating/any-type.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/base64-binary.cxx166
-rw-r--r--libxsde/xsde/cxx/serializer/validating/base64-binary.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/base64-binary.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/boolean.cxx30
-rw-r--r--libxsde/xsde/cxx/serializer/validating/boolean.hxx39
-rw-r--r--libxsde/xsde/cxx/serializer/validating/byte.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/byte.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date-time.cxx87
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date-time.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date-time.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date.cxx71
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/decimal.cxx66
-rw-r--r--libxsde/xsde/cxx/serializer/validating/decimal.hxx50
-rw-r--r--libxsde/xsde/cxx/serializer/validating/decimal.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/double.cxx105
-rw-r--r--libxsde/xsde/cxx/serializer/validating/double.hxx60
-rw-r--r--libxsde/xsde/cxx/serializer/validating/double.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/duration.cxx195
-rw-r--r--libxsde/xsde/cxx/serializer/validating/duration.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/duration.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/float.cxx105
-rw-r--r--libxsde/xsde/cxx/serializer/validating/float.hxx60
-rw-r--r--libxsde/xsde/cxx/serializer/validating/float.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gday.cxx67
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gday.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gday.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx68
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth-day.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth-day.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth.cxx67
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear-month.cxx68
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear-month.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear-month.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear.cxx67
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gyear.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/hex-binary.cxx70
-rw-r--r--libxsde/xsde/cxx/serializer/validating/hex-binary.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/hex-binary.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/id-stl.cxx38
-rw-r--r--libxsde/xsde/cxx/serializer/validating/id-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/id.cxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/id.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/id.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idref-stl.cxx38
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idref-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idref.cxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idref.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idref.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs-stl.cxx109
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs-stl.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs.cxx110
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/idrefs.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/inheritance-map-load.hxx35
-rw-r--r--libxsde/xsde/cxx/serializer/validating/inheritance-map.cxx111
-rw-r--r--libxsde/xsde/cxx/serializer/validating/inheritance-map.hxx63
-rw-r--r--libxsde/xsde/cxx/serializer/validating/inheritance-map.ixx34
-rw-r--r--libxsde/xsde/cxx/serializer/validating/int.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/int.hxx39
-rw-r--r--libxsde/xsde/cxx/serializer/validating/integer.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/language-stl.cxx73
-rw-r--r--libxsde/xsde/cxx/serializer/validating/language-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/language.cxx81
-rw-r--r--libxsde/xsde/cxx/serializer/validating/language.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/language.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/long-long.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/long-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/long.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/name-stl.cxx62
-rw-r--r--libxsde/xsde/cxx/serializer/validating/name-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/name.cxx70
-rw-r--r--libxsde/xsde/cxx/serializer/validating/name.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/name.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/ncname-stl.cxx38
-rw-r--r--libxsde/xsde/cxx/serializer/validating/ncname-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/ncname.cxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/ncname.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/ncname.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/negative-integer.cxx51
-rw-r--r--libxsde/xsde/cxx/serializer/validating/negative-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtoken-stl.cxx53
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtoken-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtoken.cxx61
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtoken.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtoken.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens-stl.cxx109
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens-stl.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens.cxx110
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens.hxx52
-rw-r--r--libxsde/xsde/cxx/serializer/validating/nmtokens.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/non-negative-integer.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/non-negative-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/non-positive-integer.cxx51
-rw-r--r--libxsde/xsde/cxx/serializer/validating/non-positive-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/normalized-string-stl.cxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/normalized-string-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/normalized-string.cxx55
-rw-r--r--libxsde/xsde/cxx/serializer/validating/normalized-string.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/normalized-string.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/positive-integer.cxx51
-rw-r--r--libxsde/xsde/cxx/serializer/validating/positive-integer.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname-stl.cxx68
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname-stl.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname-stl.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname.cxx79
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/qname.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/serializer.cxx29
-rw-r--r--libxsde/xsde/cxx/serializer/validating/serializer.hxx58
-rw-r--r--libxsde/xsde/cxx/serializer/validating/serializer.ixx61
-rw-r--r--libxsde/xsde/cxx/serializer/validating/short.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/short.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/string-stl.cxx35
-rw-r--r--libxsde/xsde/cxx/serializer/validating/string-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/string.cxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/string.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/string.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time-zone.cxx65
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time-zone.hxx40
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time-zone.ixx32
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time.cxx79
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time.hxx43
-rw-r--r--libxsde/xsde/cxx/serializer/validating/time.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/token-stl.cxx58
-rw-r--r--libxsde/xsde/cxx/serializer/validating/token-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/token.cxx66
-rw-r--r--libxsde/xsde/cxx/serializer/validating/token.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/token.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-byte.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-byte.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-int.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-int.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-long-long.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-long-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-long.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-long.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-short.cxx45
-rw-r--r--libxsde/xsde/cxx/serializer/validating/unsigned-short.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/uri-stl.cxx39
-rw-r--r--libxsde/xsde/cxx/serializer/validating/uri-stl.hxx41
-rw-r--r--libxsde/xsde/cxx/serializer/validating/uri.cxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/uri.hxx47
-rw-r--r--libxsde/xsde/cxx/serializer/validating/uri.ixx22
-rw-r--r--libxsde/xsde/cxx/serializer/validating/xml-schema-simpl.hxx82
-rw-r--r--libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.cxx560
-rw-r--r--libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.hxx1382
-rw-r--r--libxsde/xsde/cxx/serializer/validating/xml-schema-sskel.ixx704
-rw-r--r--libxsde/xsde/cxx/serializer/xml-schema.hxx20
-rw-r--r--libxsde/xsde/cxx/strdupx.cxx48
-rw-r--r--libxsde/xsde/cxx/strdupx.hxx27
-rw-r--r--libxsde/xsde/cxx/string-sequence-stl.cxx147
-rw-r--r--libxsde/xsde/cxx/string-sequence-stl.hxx135
-rw-r--r--libxsde/xsde/cxx/string-sequence-stl.ixx204
-rw-r--r--libxsde/xsde/cxx/string-sequence.cxx76
-rw-r--r--libxsde/xsde/cxx/string-sequence.hxx133
-rw-r--r--libxsde/xsde/cxx/string-sequence.ixx233
-rw-r--r--libxsde/xsde/cxx/string.cxx75
-rw-r--r--libxsde/xsde/cxx/string.hxx112
-rw-r--r--libxsde/xsde/cxx/string.ixx149
-rw-r--r--libxsde/xsde/cxx/sys-error.cxx27
-rw-r--r--libxsde/xsde/cxx/sys-error.hxx42
-rw-r--r--libxsde/xsde/cxx/sys-error.ixx16
-rw-r--r--libxsde/xsde/cxx/version.hxx29
-rw-r--r--libxsde/xsde/cxx/xml/char-table.cxx27
-rw-r--r--libxsde/xsde/cxx/xml/char-table.hxx24
-rw-r--r--libxsde/xsde/cxx/xml/ncname.cxx43
-rw-r--r--libxsde/xsde/cxx/xml/ncname.hxx23
-rw-r--r--libxsde/xsde/makefile558
-rw-r--r--makefile43
-rw-r--r--tests/cxx/hashmap/driver.cxx98
-rw-r--r--tests/cxx/hashmap/makefile61
-rw-r--r--tests/cxx/hashmap/output9
-rw-r--r--tests/cxx/hybrid/built-in/driver.cxx56
-rw-r--r--tests/cxx/hybrid/built-in/makefile88
-rw-r--r--tests/cxx/hybrid/built-in/output5
-rw-r--r--tests/cxx/hybrid/built-in/test.xml24
-rw-r--r--tests/cxx/hybrid/built-in/test.xsd125
-rw-r--r--tests/cxx/hybrid/choice/driver.cxx70
-rw-r--r--tests/cxx/hybrid/choice/makefile88
-rw-r--r--tests/cxx/hybrid/choice/output1
-rw-r--r--tests/cxx/hybrid/choice/test.xml57
-rw-r--r--tests/cxx/hybrid/choice/test.xsd174
-rw-r--r--tests/cxx/hybrid/compositor/includee.xsd14
-rw-r--r--tests/cxx/hybrid/compositor/includer.xsd14
-rw-r--r--tests/cxx/hybrid/compositor/test.xsd186
-rw-r--r--tests/cxx/hybrid/compositor/tmp.xsd87
-rw-r--r--tests/cxx/hybrid/file-per-type/a.xsd14
-rw-r--r--tests/cxx/hybrid/file-per-type/b.xsd16
-rw-r--r--tests/cxx/hybrid/file-per-type/test.xsd9
-rw-r--r--tests/cxx/hybrid/list/driver.cxx56
-rw-r--r--tests/cxx/hybrid/list/makefile88
-rw-r--r--tests/cxx/hybrid/list/output1
-rw-r--r--tests/cxx/hybrid/list/test.xml8
-rw-r--r--tests/cxx/hybrid/list/test.xsd35
-rw-r--r--tests/cxx/hybrid/makefile29
-rw-r--r--tests/cxx/hybrid/reorder/test.xsd26
-rw-r--r--tests/cxx/hybrid/sequences/driver.cxx442
-rw-r--r--tests/cxx/hybrid/sequences/makefile61
-rw-r--r--tests/cxx/hybrid/size/test.xsd136
-rw-r--r--tests/cxx/hybrid/test-template/driver.cxx56
-rw-r--r--tests/cxx/hybrid/test-template/makefile88
-rw-r--r--tests/cxx/hybrid/test-template/output1
-rw-r--r--tests/cxx/hybrid/test-template/test.xml5
-rw-r--r--tests/cxx/hybrid/test-template/test.xsd12
-rw-r--r--tests/cxx/hybrid/union/driver.cxx56
-rw-r--r--tests/cxx/hybrid/union/makefile88
-rw-r--r--tests/cxx/hybrid/union/output1
-rw-r--r--tests/cxx/hybrid/union/test.xml6
-rw-r--r--tests/cxx/hybrid/union/test.xsd26
-rw-r--r--tests/cxx/makefile24
-rw-r--r--tests/cxx/parser/built-in/driver.cxx661
-rw-r--r--tests/cxx/parser/built-in/makefile79
-rw-r--r--tests/cxx/parser/built-in/output-long167
-rw-r--r--tests/cxx/parser/built-in/output-long-long167
-rw-r--r--tests/cxx/parser/built-in/test-long-long.xml199
-rw-r--r--tests/cxx/parser/built-in/test-long.xml199
-rw-r--r--tests/cxx/parser/built-in/test.xsd63
-rw-r--r--tests/cxx/parser/duplicate/makefile79
-rw-r--r--tests/cxx/parser/duplicate/output3
-rw-r--r--tests/cxx/parser/duplicate/test.xml9
-rw-r--r--tests/cxx/parser/duplicate/test.xsd16
-rw-r--r--tests/cxx/parser/enumeration/driver.cxx99
-rw-r--r--tests/cxx/parser/enumeration/gender.hxx15
-rw-r--r--tests/cxx/parser/enumeration/makefile76
-rw-r--r--tests/cxx/parser/enumeration/output3
-rw-r--r--tests/cxx/parser/enumeration/test.map7
-rw-r--r--tests/cxx/parser/enumeration/test.xml10
-rw-r--r--tests/cxx/parser/enumeration/test.xsd35
-rw-r--r--tests/cxx/parser/error-handling/codes/driver.cxx276
-rw-r--r--tests/cxx/parser/error-handling/codes/makefile74
-rw-r--r--tests/cxx/parser/error-handling/codes/output15
-rw-r--r--tests/cxx/parser/error-handling/codes/test.map4
-rw-r--r--tests/cxx/parser/error-handling/codes/test.xml9
-rw-r--r--tests/cxx/parser/error-handling/codes/test.xsd19
-rw-r--r--tests/cxx/parser/error-handling/exceptions/driver.cxx256
-rw-r--r--tests/cxx/parser/error-handling/exceptions/makefile75
-rw-r--r--tests/cxx/parser/error-handling/exceptions/output15
-rw-r--r--tests/cxx/parser/error-handling/exceptions/test.map4
-rw-r--r--tests/cxx/parser/error-handling/exceptions/test.xml9
-rw-r--r--tests/cxx/parser/error-handling/exceptions/test.xsd19
-rw-r--r--tests/cxx/parser/error-handling/makefile24
-rw-r--r--tests/cxx/parser/generated-impl/makefile79
-rw-r--r--tests/cxx/parser/generated-impl/output122
-rw-r--r--tests/cxx/parser/generated-impl/test.xml168
-rw-r--r--tests/cxx/parser/generated-impl/test.xsd142
-rw-r--r--tests/cxx/parser/list/driver.cxx127
-rw-r--r--tests/cxx/parser/list/makefile72
-rw-r--r--tests/cxx/parser/list/output26
-rw-r--r--tests/cxx/parser/list/test.xml25
-rw-r--r--tests/cxx/parser/list/test.xsd25
-rw-r--r--tests/cxx/parser/makefile57
-rw-r--r--tests/cxx/parser/name-clash/inheritance/driver.cxx87
-rw-r--r--tests/cxx/parser/name-clash/inheritance/makefile72
-rw-r--r--tests/cxx/parser/name-clash/inheritance/output2
-rw-r--r--tests/cxx/parser/name-clash/inheritance/test.xml8
-rw-r--r--tests/cxx/parser/name-clash/inheritance/test.xsd22
-rw-r--r--tests/cxx/parser/polymorphism/driver.cxx124
-rw-r--r--tests/cxx/parser/polymorphism/makefile73
-rw-r--r--tests/cxx/parser/polymorphism/output14
-rw-r--r--tests/cxx/parser/polymorphism/test.xml19
-rw-r--r--tests/cxx/parser/polymorphism/test.xsd45
-rw-r--r--tests/cxx/parser/recursive/driver.cxx172
-rw-r--r--tests/cxx/parser/recursive/makefile73
-rw-r--r--tests/cxx/parser/recursive/output22
-rw-r--r--tests/cxx/parser/recursive/test.xml11
-rw-r--r--tests/cxx/parser/recursive/test.xsd27
-rw-r--r--tests/cxx/parser/reset/driver.cxx300
-rw-r--r--tests/cxx/parser/reset/fail-schema.xml8
-rw-r--r--tests/cxx/parser/reset/fail-xml.xml7
-rw-r--r--tests/cxx/parser/reset/makefile75
-rw-r--r--tests/cxx/parser/reset/output8
-rw-r--r--tests/cxx/parser/reset/pass.xml7
-rw-r--r--tests/cxx/parser/reset/test.xsd27
-rw-r--r--tests/cxx/parser/test-template/driver.cxx77
-rw-r--r--tests/cxx/parser/test-template/makefile72
-rw-r--r--tests/cxx/parser/test-template/output1
-rw-r--r--tests/cxx/parser/test-template/test.xml7
-rw-r--r--tests/cxx/parser/test-template/test.xsd12
-rw-r--r--tests/cxx/parser/union/driver.cxx62
-rw-r--r--tests/cxx/parser/union/makefile72
-rw-r--r--tests/cxx/parser/union/output3
-rw-r--r--tests/cxx/parser/union/test.xml10
-rw-r--r--tests/cxx/parser/union/test.xsd16
-rw-r--r--tests/cxx/parser/validation/all/driver.cxx121
-rw-r--r--tests/cxx/parser/validation/all/makefile82
-rw-r--r--tests/cxx/parser/validation/all/test-000.std46
-rw-r--r--tests/cxx/parser/validation/all/test-000.xml53
-rw-r--r--tests/cxx/parser/validation/all/test-001.std6
-rw-r--r--tests/cxx/parser/validation/all/test-001.xml11
-rw-r--r--tests/cxx/parser/validation/all/test-002.std4
-rw-r--r--tests/cxx/parser/validation/all/test-002.xml9
-rw-r--r--tests/cxx/parser/validation/all/test-003.std6
-rw-r--r--tests/cxx/parser/validation/all/test-003.xml12
-rw-r--r--tests/cxx/parser/validation/all/test.xsd20
-rw-r--r--tests/cxx/parser/validation/any/driver.cxx139
-rw-r--r--tests/cxx/parser/validation/any/makefile82
-rw-r--r--tests/cxx/parser/validation/any/test-000.std29
-rw-r--r--tests/cxx/parser/validation/any/test-000.xml21
-rw-r--r--tests/cxx/parser/validation/any/test.xsd20
-rw-r--r--tests/cxx/parser/validation/attribute/driver.cxx275
-rw-r--r--tests/cxx/parser/validation/attribute/makefile72
-rw-r--r--tests/cxx/parser/validation/attribute/output24
-rw-r--r--tests/cxx/parser/validation/attribute/test.xml10
-rw-r--r--tests/cxx/parser/validation/attribute/test.xsd71
-rw-r--r--tests/cxx/parser/validation/built-in/any-type/driver.cxx187
-rw-r--r--tests/cxx/parser/validation/built-in/any-type/makefile82
-rw-r--r--tests/cxx/parser/validation/built-in/any-type/test-000.std113
-rw-r--r--tests/cxx/parser/validation/built-in/any-type/test-000.xml41
-rw-r--r--tests/cxx/parser/validation/built-in/any-type/test.xsd31
-rw-r--r--tests/cxx/parser/validation/built-in/binary/driver.cxx176
-rw-r--r--tests/cxx/parser/validation/built-in/binary/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/boolean/driver.cxx150
-rw-r--r--tests/cxx/parser/validation/built-in/boolean/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/byte/driver.cxx280
-rw-r--r--tests/cxx/parser/validation/built-in/byte/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/date-time/driver.cxx1833
-rw-r--r--tests/cxx/parser/validation/built-in/date-time/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/float/driver.cxx309
-rw-r--r--tests/cxx/parser/validation/built-in/float/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/int/driver.cxx116
-rw-r--r--tests/cxx/parser/validation/built-in/int/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/integer/driver.cxx317
-rw-r--r--tests/cxx/parser/validation/built-in/integer/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/long-long/driver.cxx118
-rw-r--r--tests/cxx/parser/validation/built-in/long-long/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/long/driver.cxx106
-rw-r--r--tests/cxx/parser/validation/built-in/long/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/makefile35
-rw-r--r--tests/cxx/parser/validation/built-in/qname/driver.cxx132
-rw-r--r--tests/cxx/parser/validation/built-in/qname/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/short/driver.cxx116
-rw-r--r--tests/cxx/parser/validation/built-in/short/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/string/driver.cxx613
-rw-r--r--tests/cxx/parser/validation/built-in/string/makefile61
-rw-r--r--tests/cxx/parser/validation/built-in/uri/driver.cxx66
-rw-r--r--tests/cxx/parser/validation/built-in/uri/makefile61
-rw-r--r--tests/cxx/parser/validation/choice/driver.cxx158
-rw-r--r--tests/cxx/parser/validation/choice/makefile81
-rw-r--r--tests/cxx/parser/validation/choice/test-000.std22
-rw-r--r--tests/cxx/parser/validation/choice/test-000.xml30
-rw-r--r--tests/cxx/parser/validation/choice/test-001.std4
-rw-r--r--tests/cxx/parser/validation/choice/test-001.xml10
-rw-r--r--tests/cxx/parser/validation/choice/test-002.std11
-rw-r--r--tests/cxx/parser/validation/choice/test-002.xml17
-rw-r--r--tests/cxx/parser/validation/choice/test-003.std5
-rw-r--r--tests/cxx/parser/validation/choice/test-003.xml11
-rw-r--r--tests/cxx/parser/validation/choice/test-004.std4
-rw-r--r--tests/cxx/parser/validation/choice/test-004.xml11
-rw-r--r--tests/cxx/parser/validation/choice/test.xsd24
-rw-r--r--tests/cxx/parser/validation/makefile26
-rw-r--r--tests/cxx/parser/validation/restriction/driver.cxx122
-rw-r--r--tests/cxx/parser/validation/restriction/makefile81
-rw-r--r--tests/cxx/parser/validation/restriction/test-000.std0
-rw-r--r--tests/cxx/parser/validation/restriction/test-000.xml31
-rw-r--r--tests/cxx/parser/validation/restriction/test-001.std1
-rw-r--r--tests/cxx/parser/validation/restriction/test-001.xml11
-rw-r--r--tests/cxx/parser/validation/restriction/test-002.std1
-rw-r--r--tests/cxx/parser/validation/restriction/test-002.xml12
-rw-r--r--tests/cxx/parser/validation/restriction/test-003.std1
-rw-r--r--tests/cxx/parser/validation/restriction/test-003.xml16
-rw-r--r--tests/cxx/parser/validation/restriction/test-004.std1
-rw-r--r--tests/cxx/parser/validation/restriction/test-004.xml10
-rw-r--r--tests/cxx/parser/validation/restriction/test-005.std1
-rw-r--r--tests/cxx/parser/validation/restriction/test-005.xml11
-rw-r--r--tests/cxx/parser/validation/restriction/test.xsd82
-rw-r--r--tests/cxx/parser/validation/sequence/driver.cxx185
-rw-r--r--tests/cxx/parser/validation/sequence/makefile81
-rw-r--r--tests/cxx/parser/validation/sequence/test-000.std56
-rw-r--r--tests/cxx/parser/validation/sequence/test-000.xml46
-rw-r--r--tests/cxx/parser/validation/sequence/test-001.std4
-rw-r--r--tests/cxx/parser/validation/sequence/test-001.xml10
-rw-r--r--tests/cxx/parser/validation/sequence/test-002.std20
-rw-r--r--tests/cxx/parser/validation/sequence/test-002.xml27
-rw-r--r--tests/cxx/parser/validation/sequence/test-003.std5
-rw-r--r--tests/cxx/parser/validation/sequence/test-003.xml17
-rw-r--r--tests/cxx/parser/validation/sequence/test-004.std4
-rw-r--r--tests/cxx/parser/validation/sequence/test-004.xml14
-rw-r--r--tests/cxx/parser/validation/sequence/test-005.std6
-rw-r--r--tests/cxx/parser/validation/sequence/test-005.xml15
-rw-r--r--tests/cxx/parser/validation/sequence/test-006.std13
-rw-r--r--tests/cxx/parser/validation/sequence/test-006.xml17
-rw-r--r--tests/cxx/parser/validation/sequence/test.xsd28
-rw-r--r--tests/cxx/serializer/all/driver.cxx108
-rw-r--r--tests/cxx/serializer/all/makefile72
-rw-r--r--tests/cxx/serializer/all/output1
-rw-r--r--tests/cxx/serializer/all/test.xsd27
-rw-r--r--tests/cxx/serializer/built-in/driver.cxx1304
-rw-r--r--tests/cxx/serializer/built-in/makefile79
-rw-r--r--tests/cxx/serializer/built-in/output-long13
-rw-r--r--tests/cxx/serializer/built-in/output-long-long13
-rw-r--r--tests/cxx/serializer/built-in/test.xsd64
-rw-r--r--tests/cxx/serializer/choice/driver.cxx253
-rw-r--r--tests/cxx/serializer/choice/makefile72
-rw-r--r--tests/cxx/serializer/choice/output1
-rw-r--r--tests/cxx/serializer/choice/test.xsd51
-rw-r--r--tests/cxx/serializer/complex/driver.cxx87
-rw-r--r--tests/cxx/serializer/complex/makefile72
-rw-r--r--tests/cxx/serializer/complex/output1
-rw-r--r--tests/cxx/serializer/complex/test.xsd33
-rw-r--r--tests/cxx/serializer/enumeration/boolean.hxx15
-rw-r--r--tests/cxx/serializer/enumeration/driver.cxx74
-rw-r--r--tests/cxx/serializer/enumeration/makefile75
-rw-r--r--tests/cxx/serializer/enumeration/output1
-rw-r--r--tests/cxx/serializer/enumeration/test.map7
-rw-r--r--tests/cxx/serializer/enumeration/test.xsd35
-rw-r--r--tests/cxx/serializer/error-handling/codes/driver.cxx327
-rw-r--r--tests/cxx/serializer/error-handling/codes/makefile72
-rw-r--r--tests/cxx/serializer/error-handling/codes/output20
-rw-r--r--tests/cxx/serializer/error-handling/codes/test.xsd22
-rw-r--r--tests/cxx/serializer/error-handling/exceptions/driver.cxx285
-rw-r--r--tests/cxx/serializer/error-handling/exceptions/makefile72
-rw-r--r--tests/cxx/serializer/error-handling/exceptions/output20
-rw-r--r--tests/cxx/serializer/error-handling/exceptions/test.xsd22
-rw-r--r--tests/cxx/serializer/error-handling/makefile24
-rw-r--r--tests/cxx/serializer/generated-driver/makefile75
-rw-r--r--tests/cxx/serializer/generated-driver/output1
-rw-r--r--tests/cxx/serializer/generated-driver/test-simpl.cxx28
-rw-r--r--tests/cxx/serializer/generated-driver/test-simpl.hxx27
-rw-r--r--tests/cxx/serializer/generated-driver/test.xsd12
-rw-r--r--tests/cxx/serializer/generated-impl/makefile84
-rw-r--r--tests/cxx/serializer/generated-impl/test.xsd193
-rw-r--r--tests/cxx/serializer/list/driver.cxx114
-rw-r--r--tests/cxx/serializer/list/makefile72
-rw-r--r--tests/cxx/serializer/list/output1
-rw-r--r--tests/cxx/serializer/list/test.xsd25
-rw-r--r--tests/cxx/serializer/makefile52
-rw-r--r--tests/cxx/serializer/polymorphism/driver.cxx203
-rw-r--r--tests/cxx/serializer/polymorphism/makefile73
-rw-r--r--tests/cxx/serializer/polymorphism/output1
-rw-r--r--tests/cxx/serializer/polymorphism/test.xsd64
-rw-r--r--tests/cxx/serializer/recursive/driver.cxx135
-rw-r--r--tests/cxx/serializer/recursive/makefile72
-rw-r--r--tests/cxx/serializer/recursive/output1
-rw-r--r--tests/cxx/serializer/recursive/test.xsd27
-rw-r--r--tests/cxx/serializer/reset/driver.cxx281
-rw-r--r--tests/cxx/serializer/reset/makefile72
-rw-r--r--tests/cxx/serializer/reset/output7
-rw-r--r--tests/cxx/serializer/reset/test.xsd27
-rw-r--r--tests/cxx/serializer/restriction/driver.cxx246
-rw-r--r--tests/cxx/serializer/restriction/makefile72
-rw-r--r--tests/cxx/serializer/restriction/output1
-rw-r--r--tests/cxx/serializer/restriction/test.xsd175
-rw-r--r--tests/cxx/serializer/sequence/driver.cxx231
-rw-r--r--tests/cxx/serializer/sequence/makefile72
-rw-r--r--tests/cxx/serializer/sequence/output1
-rw-r--r--tests/cxx/serializer/sequence/test.xsd51
-rw-r--r--tests/cxx/serializer/test-template/driver.cxx48
-rw-r--r--tests/cxx/serializer/test-template/makefile72
-rw-r--r--tests/cxx/serializer/test-template/output1
-rw-r--r--tests/cxx/serializer/test-template/test.xsd12
-rw-r--r--tests/cxx/serializer/union/driver.cxx93
-rw-r--r--tests/cxx/serializer/union/makefile72
-rw-r--r--tests/cxx/serializer/union/output1
-rw-r--r--tests/cxx/serializer/union/test.xsd25
-rw-r--r--tests/cxx/serializer/validation/any/driver.cxx317
-rw-r--r--tests/cxx/serializer/validation/any/makefile72
-rw-r--r--tests/cxx/serializer/validation/any/output9
-rw-r--r--tests/cxx/serializer/validation/any/test.xsd53
-rw-r--r--tests/cxx/serializer/validation/attribute/driver.cxx247
-rw-r--r--tests/cxx/serializer/validation/attribute/makefile72
-rw-r--r--tests/cxx/serializer/validation/attribute/output9
-rw-r--r--tests/cxx/serializer/validation/attribute/test.xsd21
-rw-r--r--tests/cxx/serializer/validation/built-in/date-time/driver.cxx398
-rw-r--r--tests/cxx/serializer/validation/built-in/date-time/makefile61
-rw-r--r--tests/cxx/serializer/validation/built-in/decimal/driver.cxx46
-rw-r--r--tests/cxx/serializer/validation/built-in/decimal/makefile61
-rw-r--r--tests/cxx/serializer/validation/built-in/integer/driver.cxx63
-rw-r--r--tests/cxx/serializer/validation/built-in/integer/makefile61
-rw-r--r--tests/cxx/serializer/validation/built-in/makefile20
-rw-r--r--tests/cxx/serializer/validation/built-in/qname/driver.cxx70
-rw-r--r--tests/cxx/serializer/validation/built-in/qname/makefile61
-rw-r--r--tests/cxx/serializer/validation/built-in/string/driver.cxx485
-rw-r--r--tests/cxx/serializer/validation/built-in/string/makefile61
-rw-r--r--tests/cxx/serializer/validation/choice/driver.cxx114
-rw-r--r--tests/cxx/serializer/validation/choice/makefile72
-rw-r--r--tests/cxx/serializer/validation/choice/output2
-rw-r--r--tests/cxx/serializer/validation/choice/test.xsd21
-rw-r--r--tests/cxx/serializer/validation/element/driver.cxx106
-rw-r--r--tests/cxx/serializer/validation/element/makefile72
-rw-r--r--tests/cxx/serializer/validation/element/output2
-rw-r--r--tests/cxx/serializer/validation/element/test.xsd19
-rw-r--r--tests/cxx/serializer/validation/makefile24
-rw-r--r--tests/cxx/serializer/validation/sequence/driver.cxx102
-rw-r--r--tests/cxx/serializer/validation/sequence/makefile72
-rw-r--r--tests/cxx/serializer/validation/sequence/output1
-rw-r--r--tests/cxx/serializer/validation/sequence/test.xsd21
-rw-r--r--tests/cxx/serializer/wildcard/driver.cxx237
-rw-r--r--tests/cxx/serializer/wildcard/makefile72
-rw-r--r--tests/cxx/serializer/wildcard/output1
-rw-r--r--tests/cxx/serializer/wildcard/test.xsd25
-rw-r--r--tests/cxx/string/driver.cxx102
-rw-r--r--tests/cxx/string/makefile61
-rw-r--r--tests/makefile18
-rw-r--r--tests/type-map/driver.cxx47
-rw-r--r--version1
-rw-r--r--xsde/cxx/elements.cxx1089
-rw-r--r--xsde/cxx/elements.hxx599
-rw-r--r--xsde/cxx/hybrid/cli.hxx188
-rw-r--r--xsde/cxx/hybrid/elements.cxx493
-rw-r--r--xsde/cxx/hybrid/elements.hxx1880
-rw-r--r--xsde/cxx/hybrid/generator.cxx2476
-rw-r--r--xsde/cxx/hybrid/generator.hxx90
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.cxx837
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.cxx330
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx574
-rw-r--r--xsde/cxx/hybrid/parser-header.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx709
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx1185
-rw-r--r--xsde/cxx/hybrid/parser-source.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.cxx847
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.cxx330
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx534
-rw-r--r--xsde/cxx/hybrid/serializer-header.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx723
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx1001
-rw-r--r--xsde/cxx/hybrid/serializer-source.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-forward.cxx626
-rw-r--r--xsde/cxx/hybrid/tree-forward.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx2459
-rw-r--r--xsde/cxx/hybrid/tree-header.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx1817
-rw-r--r--xsde/cxx/hybrid/tree-inline.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx1993
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx850
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx1672
-rw-r--r--xsde/cxx/hybrid/tree-source.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-type-map.cxx248
-rw-r--r--xsde/cxx/hybrid/tree-type-map.hxx32
-rw-r--r--xsde/cxx/hybrid/validator.cxx584
-rw-r--r--xsde/cxx/hybrid/validator.hxx35
-rw-r--r--xsde/cxx/parser/attribute-validation-source.cxx468
-rw-r--r--xsde/cxx/parser/attribute-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/characters-validation-source.cxx76
-rw-r--r--xsde/cxx/parser/characters-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/cli.hxx156
-rw-r--r--xsde/cxx/parser/driver-source.cxx1139
-rw-r--r--xsde/cxx/parser/driver-source.hxx22
-rw-r--r--xsde/cxx/parser/element-validation-source.cxx2120
-rw-r--r--xsde/cxx/parser/element-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/elements.cxx258
-rw-r--r--xsde/cxx/parser/elements.hxx431
-rw-r--r--xsde/cxx/parser/generator.cxx1615
-rw-r--r--xsde/cxx/parser/generator.hxx56
-rw-r--r--xsde/cxx/parser/impl-header.cxx309
-rw-r--r--xsde/cxx/parser/impl-header.hxx22
-rw-r--r--xsde/cxx/parser/impl-source.cxx543
-rw-r--r--xsde/cxx/parser/impl-source.hxx22
-rw-r--r--xsde/cxx/parser/name-processor.cxx1326
-rw-r--r--xsde/cxx/parser/name-processor.hxx32
-rw-r--r--xsde/cxx/parser/parser-forward.cxx112
-rw-r--r--xsde/cxx/parser/parser-forward.hxx22
-rw-r--r--xsde/cxx/parser/parser-header.cxx1818
-rw-r--r--xsde/cxx/parser/parser-header.hxx22
-rw-r--r--xsde/cxx/parser/parser-inline.cxx721
-rw-r--r--xsde/cxx/parser/parser-inline.hxx22
-rw-r--r--xsde/cxx/parser/parser-source.cxx1626
-rw-r--r--xsde/cxx/parser/parser-source.hxx22
-rw-r--r--xsde/cxx/parser/print-impl-common.hxx1063
-rw-r--r--xsde/cxx/parser/state-processor.cxx319
-rw-r--r--xsde/cxx/parser/state-processor.hxx28
-rw-r--r--xsde/cxx/parser/type-processor.cxx352
-rw-r--r--xsde/cxx/parser/type-processor.hxx34
-rw-r--r--xsde/cxx/parser/validator.cxx704
-rw-r--r--xsde/cxx/parser/validator.hxx36
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.cxx463
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/cli.hxx154
-rw-r--r--xsde/cxx/serializer/driver-source.cxx1047
-rw-r--r--xsde/cxx/serializer/driver-source.hxx22
-rw-r--r--xsde/cxx/serializer/element-validation-source.cxx903
-rw-r--r--xsde/cxx/serializer/element-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/elements.cxx278
-rw-r--r--xsde/cxx/serializer/elements.hxx443
-rw-r--r--xsde/cxx/serializer/generator.cxx1600
-rw-r--r--xsde/cxx/serializer/generator.hxx56
-rw-r--r--xsde/cxx/serializer/impl-header.cxx488
-rw-r--r--xsde/cxx/serializer/impl-header.hxx22
-rw-r--r--xsde/cxx/serializer/impl-source.cxx664
-rw-r--r--xsde/cxx/serializer/impl-source.hxx22
-rw-r--r--xsde/cxx/serializer/name-processor.cxx1409
-rw-r--r--xsde/cxx/serializer/name-processor.hxx32
-rw-r--r--xsde/cxx/serializer/serializer-forward.cxx112
-rw-r--r--xsde/cxx/serializer/serializer-forward.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-header.cxx2006
-rw-r--r--xsde/cxx/serializer/serializer-header.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-inline.cxx631
-rw-r--r--xsde/cxx/serializer/serializer-inline.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-source.cxx2703
-rw-r--r--xsde/cxx/serializer/serializer-source.hxx22
-rw-r--r--xsde/cxx/serializer/type-processor.cxx356
-rw-r--r--xsde/cxx/serializer/type-processor.hxx34
-rw-r--r--xsde/cxx/serializer/validator.cxx501
-rw-r--r--xsde/cxx/serializer/validator.hxx36
-rw-r--r--xsde/elements.hxx135
-rw-r--r--xsde/makefile162
-rw-r--r--xsde/processing/inheritance/processor.cxx517
-rw-r--r--xsde/processing/inheritance/processor.hxx38
-rw-r--r--xsde/type-map/lexer.cxx133
-rw-r--r--xsde/type-map/lexer.hxx80
-rw-r--r--xsde/type-map/parser.cxx281
-rw-r--r--xsde/type-map/parser.hxx46
-rw-r--r--xsde/type-map/type-map.hxx160
-rw-r--r--xsde/usage.hxx226
-rw-r--r--xsde/xsde.cxx1422
-rw-r--r--xsde/xsde.hxx79
1382 files changed, 196632 insertions, 0 deletions
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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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
+ <schema>-driver.cxx to <schema>-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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@kolpackov.net>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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
--- /dev/null
+++ b/documentation/cxx/hybrid/guide/figure-1.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2471"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="hybrid.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/boris/hybrid.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective2477" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="mm"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.5980613"
+ inkscape:cx="243.67741"
+ inkscape:cy="741.86348"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1002"
+ inkscape:window-height="853"
+ inkscape:window-x="276"
+ inkscape:window-y="78">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2479" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:16.80470467;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect7825"
+ width="203.0603"
+ height="115.96954"
+ x="78.263054"
+ y="236.86377" />
+ <rect
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:18.24513817;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2489"
+ width="169.64984"
+ height="20.998301"
+ x="95.946136"
+ y="265.48535" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.91242504px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ x="145.5929"
+ y="271.39957"
+ id="text7835"
+ sodipodi:linespacing="100%"
+ transform="scale(0.9741498,1.0265362)"><tspan
+ y="271.39957"
+ x="145.5929"
+ sodipodi:role="line"
+ id="tspan2585">Object Model</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10.91242504px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ x="151.27502"
+ y="177.57848"
+ id="text2500"
+ sodipodi:linespacing="100%"
+ transform="scale(0.9741498,1.0265362)"><tspan
+ sodipodi:role="line"
+ id="tspan2570"
+ x="151.27502"
+ y="177.57848">Parser</tspan></text>
+ <g
+ id="g2631"
+ transform="matrix(0.7818522,0,0,0.7818522,12.112543,35.072306)">
+ <rect
+ y="355.19925"
+ x="103.22679"
+ height="34.53841"
+ width="84.758575"
+ id="rect2532"
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:16.53946114;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ transform="scale(0.9741498,1.0265362)"
+ sodipodi:linespacing="100%"
+ id="text2534"
+ y="366.63315"
+ x="124.96281"
+ style="font-size:13.95714664px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ xml:space="preserve"><tspan
+ y="366.63315"
+ x="124.96281"
+ id="tspan2603"
+ sodipodi:role="line">Parser</tspan></text>
+ </g>
+ <g
+ id="g2636"
+ transform="matrix(0.7818522,0,0,0.7818522,18.187466,35.76421)">
+ <rect
+ y="354.78888"
+ x="232.87415"
+ height="34.474037"
+ width="85.579155"
+ id="rect2594"
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:16.60383415;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ transform="scale(0.9741498,1.0265362)"
+ sodipodi:linespacing="100%"
+ id="text2596"
+ y="367.06186"
+ x="241.66556"
+ style="font-size:13.95714664px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ xml:space="preserve"><tspan
+ y="367.06186"
+ x="241.66556"
+ id="tspan2598"
+ sodipodi:role="line">Serializer</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="147.14096"
+ y="244.02005"
+ id="text2845"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2610"
+ x="147.14096"
+ y="244.02005">C++/Hybrid</tspan></text>
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:16.53161621;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2617"
+ width="202.50182"
+ height="30.237684"
+ x="78.263412"
+ y="177.76631" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="147.56195"
+ y="196.06781"
+ id="text2619"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2623"
+ x="147.56195"
+ y="196.06781">Application</tspan></text>
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:15.20303345;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2641"
+ width="85.640442"
+ height="29.708515"
+ x="77.687241"
+ y="382.08945" />
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:15.19906044;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2643"
+ width="85.584244"
+ height="29.71249"
+ x="195.71512"
+ y="381.7876" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="88.750069"
+ y="400.15198"
+ id="text2645"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2653"
+ x="88.750069"
+ y="400.15198">C++/Parser</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="196.68718"
+ y="400.15198"
+ id="text2649"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2655"
+ x="196.68718"
+ y="400.15198">C++/Serializer</tspan></text>
+ </g>
+</svg>
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: "
+<div align=center>
+ <h1><big>Embedded C++/Hybrid Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ 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 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Hybrid Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2009 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,parse,serialize,create,modify,write,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Hybrid Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li, ol.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+
+ /* XML Schema features table. */
+ #features {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #features th, #features td {
+ border: 1px solid;
+ padding : 0.6em 0.6em 0.6em 0.6em;
+ }
+
+ #features th {
+ background : #cde8f6;
+ }
+
+ #features td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Hybrid Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing XML Document and Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ <tr><th>2.5</th><td><a href="#2.5">Adding Serialization</a></td></tr>
+ <tr><th>2.6</th><td><a href="#2.6">A Minimal Version</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Standard Template Library</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">C++ Exceptions</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">XML Schema Validation</a></td></tr>
+ <tr><th>3.5</th><td><a href="#3.5">64-bit Integer Type</a></td></tr>
+ <tr><th>3.6</th><td><a href="#3.6">Parser and Serializer Reuse</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Working with Object Models</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Namespaces</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Memory Management</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Attributes and Elements</a></td></tr>
+ <tr><th>4.4</th><td><a href="#4.4">Compositors</a></td></tr>
+ <tr><th>4.5</th><td><a href="#4.5">Accessing the Object Model</a></td></tr>
+ <tr><th>4.6</th><td><a href="#4.6">Modifying the Object Model</a></td></tr>
+ <tr><th>4.7</th><td><a href="#4.7">Creating the Object Model from Scratch</a></td></tr>
+ <tr><th>4.8</th><td><a href="#4.8">Customizing the Object Model</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Mapping for Built-In XML Schema Types</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Mapping for <code>QName</code></a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>s</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">Mapping for <code>base54Binary</code> and <code>hexBinary</code>s</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">Time Zone Representation</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">Mapping for <code>date</code></a></td></tr>
+ <tr><th>5.6</th><td><a href="#5.6">Mapping for <code>dateTime</code></a></td></tr>
+ <tr><th>5.7</th><td><a href="#5.7">Mapping for <code>duration</code></a></td></tr>
+ <tr><th>5.8</th><td><a href="#5.8">Mapping for <code>gDay</code></a></td></tr>
+ <tr><th>5.9</th><td><a href="#5.9">Mapping for <code>gMonth</code></a></td></tr>
+ <tr><th>5.10</th><td><a href="#5.10">Mapping for <code>gMonthDay</code></a></td></tr>
+ <tr><th>5.11</th><td><a href="#5.11">Mapping for <code>gYear</code></a></td></tr>
+ <tr><th>5.12</th><td><a href="#5.12">Mapping for <code>gYearMonth</code></a></td></tr>
+ <tr><th>5.13</th><td><a href="#5.13">Mapping for <code>time</code></a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Parsing and Serialization</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1">Customizing Parsers and Serializers</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>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.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">Embedded
+ C++/Parser Mapping Getting Started Guide</a>. The C++/Hybrid
+ mapping uses C++/Parser for XML parsing.</li>
+
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">Embedded
+ C++/Serializer Mapping Getting Started Guide</a>. The C++/Hybrid
+ mapping uses C++/Serializer for XML serialization.</li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/hybrid/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Hybrid mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>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.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>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
+ <a href="http://www.codesynthesis.com/products/xsde/c++/parser/">Embedded
+ C++/Parser</a> and
+ <a href="http://www.codesynthesis.com/products/xsde/c++/serializer/">Embedded
+ C++/Serializer</a>
+ 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:</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>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.
+ </p>
+
+ <p>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.
+ </p>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>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:
+ </p>
+
+ <ul class="list">
+ <li>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.</li>
+
+ <li>String-based flow control defers error detection to runtime.
+ It also reduces code readability and maintainability.</li>
+
+ <li>Lack of type safety and inefficient use of resources due to
+ the data being represented as text.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>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.</p>
+
+ <p>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:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> 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.</li>
+
+ <li><b>Natural representation.</b> The object representation allows
+ you to access the XML data using your domain vocabulary instead
+ of generic elements, attributes, and text.</li>
+
+ <li><b>Concise code.</b> With the object representation the
+ application implementation is simpler and thus easier
+ to read and understand.</li>
+
+ <li><b>Safety.</b> 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.</li>
+
+ <li><b>Maintainability.</b> 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.</li>
+
+ <li><b>Efficiency.</b> 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.
+
+ <p>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.</p>
+ </li>
+ </ul>
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>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 <code>hello</code>
+ example which can be found in the <code>examples/cxx/hybrid/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing XML Document and Schema</a></h2>
+
+ <p>First, we need to get an idea about the structure
+ of the XML documents we are going to process. Our
+ <code>hello.xml</code>, for example, could look like this:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>earth&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with XML Schema, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in <code>hello.xml</code>. The <code>hello</code> type
+ is defined as a sequence of the nested <code>greeting</code> and
+ <code>name</code> 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 <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounded</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>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.</p>
+
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++.
+ To do this we invoke the XSD/e compiler from a terminal (UNIX) or
+ a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-aggregate hello.xsd
+ </pre>
+
+ <p>This invocation of the XSD/e compiler produces three pairs of C++ files:
+ <code>hello.hxx</code> and <code>hello.cxx</code>,
+ <code>hello-pskel.hxx</code> and <code>hello-pskel.cxx</code>, as well as
+ <code>hello-pimpl.hxx</code> and <code>hello-pimpl.cxx</code>. 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
+ <code>--generate-parser</code> XSD/e compiler option.</p>
+
+ <p>You may be wondering what is the <code>--generate-aggregate</code>
+ 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 <code>--generate-aggregate</code> 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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> 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
+ <code>hello</code> root element in the next section.</p>
+
+ <p>The following code fragment is taken from <code>hello.hxx</code>; it
+ shows what the C++ object model for our "Hello World" XML vocabulary
+ looks like:
+ </p>
+
+ <pre class="c++">
+class hello
+{
+public:
+ hello ();
+
+ // greeting
+ //
+ const std::string&amp;
+ greeting () const;
+
+ std::string&amp;
+ greeting ();
+
+ void
+ greeting (const std::string&amp;);
+
+ // name
+ //
+ typedef xsde::string_sequence name_sequence;
+ typedef name_sequence::iterator name_iterator;
+ typedef name_sequence::const_iterator name_const_iterator;
+
+ const name_sequence&amp;
+ name () const;
+
+ name_sequence&amp;
+ name ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The <code>hello</code> C++ class corresponds to the
+ <code>hello</code> XML Schema type. For each element
+ in this type a set of accessor and modifier functions
+ are generated inside the <code>hello</code> class. Note
+ that the member functions for the <code>greeting</code> and
+ <code>name</code> elements are different because of the
+ different cardinalities these two elements have
+ (<code>greeting</code> is a required single element and
+ <code>name</code> is a sequence of elements).</p>
+
+ <p>It is also evident that the built-in XML Schema type
+ <code>string</code> is mapped to <code>std::string</code>.
+ The internal <code>string_sequence</code> class that
+ is used in the <code>name_sequence</code> type definition
+ has an interface similar to <code>std::vector</code>. The
+ mapping between the built-in XML Schema types and C++ types
+ is described in more detail in <a href="#5">Chapter 5,
+ "Mapping for Built-in XML Schema Types"</a>.</p>
+
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>At this point we have all the parts we need to do something useful
+ with the information stored in our XML document:
+ </p>
+
+ <pre class="c++">
+#include &lt;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 &lt;&lt; h->greeting () &lt;&lt; ", " &lt;&lt; *i &lt;&lt; "!" &lt;&lt; endl;
+ }
+
+ delete h;
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>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 <code>hello_paggr</code> class is the parser
+ aggregate class we discussed earlier. Parsing is covered in more
+ detail in <a href="#6">Chapter 6, "Parsing and Serialization"</a>.
+ 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 <code>xml_schema::parser_exception</code> exception
+ in case something goes wrong.
+ </p>
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving our application from the previous section in
+ <code>driver.cxx</code>, 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:
+ </p>
+
+ <pre class="terminal">
+$ 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!
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.</p>
+
+ <p>We can also test the error handling. To test XML well-formedness
+ checking, we can try to parse <code>hello.hxx</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.hxx
+hello.hxx:1:0: not well-formed (invalid token)
+ </pre>
+
+ <p>We can also try to parse a valid XML but not from our
+ vocabulary, for example <code>hello.xsd</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+ </pre>
+
+ <h2><a name="2.5">2.5 Adding Serialization</a></h2>
+
+ <p>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
+ <code>--generate-serializer</code> option to our XSD/e
+ compiler invocation:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+ --generate-aggregate hello.xsd
+ </pre>
+
+ <p>This will result in two additional pairs of C++ files:
+ <code>hello-sskel.hxx</code> and <code>hello-sskel.cxx</code>, as well as
+ <code>hello-simpl.hxx</code> and <code>hello-simpl.cxx</code>.
+ 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 <code>hello</code> root element.</p>
+
+ <p>Let us first examine an application that modifies an existing
+ object model and serializes it back to XML:</p>
+
+ <pre class="c++">
+#include &lt;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&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>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 (<code>cout</code>) for us to inspect.
+ We could have also written the result to a file or memory
+ buffer by creating an instance of <code>std::ofstream</code>
+ or <code>std::ostringstream</code> and passing it to
+ <code>serialize()</code> instead of <code>cout</code>.
+ The <code>hello_saggr</code> class is the serializer aggregate
+ class we discussed earlier. Serialization is covered in more
+ detail in <a href="#6">Chapter 6, "Parsing and Serialization"</a>.</p>
+
+ <p>If we now compile and run this application (don't forget to
+ compile and link <code>hello-sskel.cxx</code> and
+ <code>hello-simpl.cxx</code>), we will see the
+ output as shown in the following listing:</p>
+
+ <pre class="xml">
+&lt;hello>
+ &lt;greeting>Hi&lt;/greeting>
+ &lt;name>sun&lt;/name>
+ &lt;name>earth&lt;/name>
+ &lt;name>world&lt;/name>
+ &lt;name>mars&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <p>
+ We can also test XML Schema validation. We can "accidently"
+ remove all the names from the object model by adding the following
+ after: <code>push_back ("mars")</code>:</p>
+
+ <pre class="c++">
+h->name ().clear ();
+ </pre>
+
+ <p>This will violate our vocabulary specification which requires
+ at least one <code>name</code> element to be present. If we
+ make the above change and recompile our application, we will
+ get the following output:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xml
+error: expected element not encountered
+ </pre>
+
+ <p>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 <code>--generate-parser</code> option since
+ we don't need support for XML parsing.</p>
+
+ <pre class="c++">
+#include &lt;sstream>
+#include &lt;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&amp; 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 &lt;&lt; ostr.c_str () &lt;&lt; endl;
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>In this example we used the generated default constructor to
+ create an empty instance of type <code>hello</code>. 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:</p>
+
+ <pre class="xml">
+&lt;hello>
+ &lt;greeting>Hi&lt;/greeting>
+ &lt;name>Jane&lt;/name>
+ &lt;name>John&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <h2><a name="2.6">2.6 A Minimal Version</a></h2>
+
+ <p>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.</p>
+
+ <p>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
+ (<code>libxsde.a</code>) to disable STL, iostream, and
+ exceptions.</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --no-stl --no-iostream --no-exceptions \
+ --generate-parser --generate-serializer --generate-aggregate \
+ hello.xsd
+ </pre>
+
+ <p>If you now study the generated <code>hello.hxx</code> file,
+ you will notice that the use of <code>std::string</code> type
+ is replaced with <code>char*</code>. When STL is disabled,
+ built-in XML Schema type <code>string</code> is mapped to a
+ C string. The following listing presents the content of
+ <code>driver.cxx</code> in full:</p>
+
+ <pre class="c++">
+#include &lt;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) &amp;&amp; ferror (f))
+ {
+ io_error = true;
+ break;
+ }
+
+ doc_p.parse (buf, s, feof (f) != 0);
+ pe = doc_p._error ();
+
+ } while (!pe &amp;&amp; !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;
+ }
+}
+ </pre>
+
+ <p>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
+ <a href="#6">Chapter 6, "Parsing and Serialization"</a>. On the other
+ hand, the access and modification of the object model stayed
+ relatively unchanged. The only noticeable change is the use
+ of the <code>xml_schema::strdupx</code> 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 <code>strdup</code>
+ because the object model expects the strings to be allocated
+ with C++ operator <code>new[]</code> while C <code>strdup</code>
+ uses <code>malloc</code> (on most implementations operator
+ <code>new</code> is implemented in terms of <code>malloc</code>
+ so you can probably use <code>strdup</code> if you really
+ want to).</p>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="3">3 Mapping Configuration</a></h1>
+
+ <p>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.</p>
+
+ <p>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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>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.</p>
+
+ <h2><a name="3.1">3.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> option to the XSD/e compiler when
+ translating your schemas.</p>
+
+ <p>When STL is disabled, all string-based XML Schema types
+ (see <a href="#5">Chapter 5, "Mapping for Built-In XML Schema
+ Types"</a>) are mapped to C-style <code>char*</code> instead of
+ <code>std::string</code>. 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 <code>new[]</code>. To simplify
+ creation of such strings from string literals, the generated
+ code provides the <code>strdupx</code> and <code>strndupx</code>
+ functions in the <code>xml_schema</code> namespace. These functions
+ are similar to C <code>strdup</code> and <code>strndup</code> except
+ that they use operator <code>new[]</code> instead of <code>malloc</code>
+ to allocate the string:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ char*
+ strdupx (const char*);
+
+ char*
+ strndupx (const char*, size_t);
+}
+ </pre>
+
+ <h2><a name="3.2">3.2 Input/Output Stream Library</a></h2>
+
+ <p>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 <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, a
+ number of overloaded <code>parse()</code> and <code>serialize()</code>
+ functions in the document parser (<code>xml_schema::document_pimpl</code>)
+ and document serializer (<code>xml_schema::document_simpl</code>) become
+ unavailable. See
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded
+ C++/Parser Mapping Getting Started Guide and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide for details.
+ </p>
+
+ <h2><a name="3.3">3.3 C++ Exceptions</a></h2>
+
+ <p>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 <code>--no-exceptions</code> 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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded C++/Parser
+ Mapping Getting Started Guide. For more information on error handling
+ during serialization, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide. For more information on
+ error handling in the object model, see <a href="#4">Chapter 4, "Working
+ with Object Models"</a> below.
+ </p>
+
+ <h2><a name="3.4">3.4 XML Schema Validation</a></h2>
+
+ <p>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 <code>--suppress-parser-val</code>
+ 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 <code>--suppress-serializer-val</code>
+ option to the XSD/e compiler when translating your schemas. If you
+ are disabling validation during both parsing and serialization, you
+ can use the <code>--suppress-validation</code> option instead of the
+ two options mentioned above.</p>
+
+ <p>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.</p>
+
+ <h2><a name="3.5">3.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ built-in XML Schema types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> 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 <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="3.6">3.6 Parser and Serializer Reuse</a></h2>
+
+ <p>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 <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.
+ The XSD/e runtime should be configured in accordance with the
+ reuse style used in the generated code. See <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#5.6">Section 5.6,
+ "Parser Reuse"</a> in the Embedded C++/Parser Mapping Getting Started
+ Guide and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#6.6">Section 6.6,
+ "Serializer Reuse"</a> in the Embedded C++/Serializer Mapping Getting
+ Started Guide for details.</p>
+
+
+ <!-- Chapater 4 -->
+
+
+ <h1><a name="4">4 Working with Object Models</a></h1>
+
+ <p>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.</p>
+
+ <p>In this chapter we will use the following schema that describes a
+ collection of person records. We save it in <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="middle-name" type="xs:string" minOccurs="0"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:unsignedShort"/>
+ &lt;/xs:sequence>
+ &lt;xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema is saved
+ in <code>people.xml</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three generated object model classes: <code>gender</code>,
+ <code>person</code> and <code>people</code>. Here is how they
+ look with STL enabled:</p>
+
+ <pre class="c++">
+// gender (fixed-length)
+//
+class gender: public std::string
+{
+public:
+ gender ();
+ gender (const gender&amp;);
+ gender&amp; operator= (const gender&amp;);
+};
+
+// person (fixed-length)
+//
+class person
+{
+public:
+ person ();
+ person (const person&amp;);
+ person&amp; operator= (const person&amp;);
+
+ // id
+ //
+ unsigned int
+ id () const;
+
+ unsigned int&amp;
+ id ();
+
+ void
+ id (unsigned int);
+
+ // first-name
+ //
+ const std::string&amp;
+ first_name () const;
+
+ std::string&amp;
+ first_name ();
+
+ void
+ first_name (const std::string&amp;);
+
+ // middle-name
+ //
+ bool
+ middle_name_present () const;
+
+ void
+ middle_name_present (bool);
+
+ const std::string&amp;
+ middle_name () const;
+
+ std::string&amp;
+ middle_name ();
+
+ void
+ middle_name (const std::string&amp;);
+
+ // last-name
+ //
+ const std::string&amp;
+ last_name () const;
+
+ std::string&amp;
+ last_name ();
+
+ void
+ last_name (const std::string&amp;);
+
+ // gender
+ //
+ const ::gender&amp;
+ gender () const;
+
+ ::gender&amp;
+ gender ();
+
+ void
+ gender (const ::gender&amp;);
+
+ // age
+ //
+ unsigned short
+ age () const;
+
+ unsigned short&amp;
+ age ();
+
+ void
+ age (unsigned short);
+
+private:
+ ...
+};
+
+// people (variable-length)
+//
+class people
+{
+public:
+ people ();
+
+private:
+ people (const people&amp;);
+ people&amp; operator= (const people&amp;);
+
+public:
+ // person
+ //
+ typedef xsde::fix_sequence&lt;person> person_sequence;
+ typedef person_sequence::iterator person_iterator;
+ typedef person_sequence::const_iterator person_const_iterator;
+
+ const person_sequence&amp;
+ person () const;
+
+ person_sequence&amp;
+ person ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>We will examine these classes in detail in the subsequent
+ sections.</p>
+
+ <h2><a name="4.1">4.1 Namespaces</a></h2>
+
+ <p>XSD/e maps XML namespaces specified in the <code>targetNamespace</code>
+ 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 <code>'/'</code> as the name
+ separator. For example, the <code>http://www.codesynthesis.com/cs/my</code>
+ XML namespace is mapped to the <code>cs::my</code> C++ namespace.</p>
+
+ <p>The default mapping of namespace URIs to C++ namespaces
+ can be altered using the <code>--namespace-map</code> and
+ <code>--namespace-regex</code> compiler options. For example,
+ to map the <code>http://www.codesynthesis.com/my</code> XML
+ namespace to the <code>cs::my</code> C++ namespace, we can use
+ the following option:</p>
+
+ <pre class="terminal">
+--namespace-map http://www.codesynthesis.com/my=cs::my
+ </pre>
+
+ <p>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 <code>people.xsd</code> schema
+ into the <code>records</code> C++ namespace by adding the following
+ option:</p>
+
+ <pre class="terminal">
+--namespace-map =records
+ </pre>
+
+
+ <h2><a name="4.2">4.2 Memory Management</a></h2>
+
+ <p>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:</p>
+
+ <ol class="list">
+ <li>it is an XML Schema <code>list</code> type</li>
+
+ <li>it is an XML Schema <code>union</code> type and STL is disabled</li>
+
+ <li>it derives from a variable-length type</li>
+
+ <li>it contains an element or attribute of a variable-length type</li>
+
+ <li>it contains an element or compositor (<code>sequence</code>
+ or <code>choice</code>) with <code>maxOccurs</code>
+ greater than one</li>
+
+ <li>it is recursive (that is, one of its elements contains
+ a reference, directly or indirectly, to the type itself)</li>
+ </ol>
+
+ <p>The following build-in XML Schema types are variable-length:
+ <code>base64Binary</code>, <code>hexBinary</code>, <code>NMTOKENS</code>,
+ and <code>IDREFS</code>. Furthermore, if STL is disabled, all
+ string-based build-in XML Schema types are variable-length,
+ namely: <code>string</code>, <code>normalizedString</code>,
+ <code>token</code>, <code>Name</code>, <code>NMTOKEN</code>,
+ <code>NCName</code>, <code>language</code>, <code>QName</code>,
+ <code>ID</code>, <code>IDFER</code>, and <code>anyURI</code>.</p>
+
+ <p>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 <code>people</code> type is
+ variable-length because it contains a sequence of <code>person</code>
+ elements (<code>maxOccurs="unbounded"</code>). If we recompile
+ the <code>people.xsd</code> schema with the <code>--no-stl</code>
+ option, the first two types will also become variable-length
+ since <code>gender</code> inherits from and <code>person</code>
+ contains elements of the <code>string</code> built-in type. And
+ when STL is disabled, <code>string</code> is variable-length.</p>
+
+ <p>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 <code>std::string</code> is expected to support the
+ referenced-counted copy-on-write optimization, which makes
+ copying cheap).</p>
+
+ <p>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.</p>
+
+ <p>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 <code>new</code> and will eventually delete it
+ with operator <code>delete</code>. As an example, let us extend
+ our <code>people.xsd</code> schema with the following type:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="staff">
+ &lt;xs:sequence>
+ &lt;xs:element name="permanent" type="people"/>
+ &lt;xs:element name="contract" type="people"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>If we compile it with XSD/e, we will get the following C++
+ class:</p>
+
+ <pre class="c++">
+// staff (variable-length)
+//
+class staff
+{
+public:
+ staff ();
+
+private:
+ staff (const staff&amp;);
+ staff&amp; operator= (const staff&amp;);
+
+public:
+ // permanent
+ //
+ const people&amp;
+ permanent () const;
+
+ people&amp;
+ permanent ();
+
+ void
+ permanent (people*);
+
+ // contract
+ //
+ const people&amp;
+ contract () const;
+
+ people&amp;
+ contract ();
+
+ void
+ contract (people*);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>Notice that unlike, say, the <code>first_name()</code> modifier
+ function in the <code>person</code> class, the <code>permanent()</code>
+ and <code>contract()</code> modifiers expect a pointer to the
+ <code>people</code> object. The following listing shows how
+ we can create and populate an instance of the <code>staff</code>
+ class. The use of smart pointers to hold the results of dynamic
+ allocations is omitted for brevity:</p>
+
+ <pre class="c++">
+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.
+ </pre>
+
+ <h2><a name="4.3">4.3 Attributes and Elements</a></h2>
+
+ <p>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:
+ <em>one</em>, <em>optional</em>, and <em>sequence</em>.</p>
+
+ <p>The <em>one</em> cardinality class covers all elements that should
+ occur exactly once as well as the required attributes. In our
+ example, the <code>first-name</code>, <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements as well as
+ the <code>id</code> attribute belong to this cardinality class.
+ The following code fragment shows again the accessor and modifier
+ functions that are generated for the <code>first-name</code> element
+ in the <code>person</code> class:</p>
+
+ <pre class="c++">
+class person
+{
+ // first-name
+ //
+ const std::string&amp;
+ first_name () const;
+
+ std::string&amp;
+ first_name ();
+
+ void
+ first_name (const std::string&amp;);
+};
+ </pre>
+
+ <p>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.</p>
+
+ <p>The <em>optional</em> cardinality class covers all elements that
+ can occur zero or one time as well as optional attributes. In our
+ example, the <code>middle-name</code> 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 <code>person</code> class:</p>
+
+ <pre class="c++">
+class person
+{
+ // middle-name
+ //
+ bool
+ middle_name_present () const;
+
+ void
+ middle_name_present (bool);
+
+ const std::string&amp;
+ middle_name () const;
+
+ std::string&amp;
+ middle_name ();
+
+ void
+ middle_name (const std::string&amp;);
+};
+ </pre>
+
+ <p>Compared to the <em>one</em> cardinality class, <em>optional</em> adds
+ two extra functions for querying and modifying the element's presence
+ status. The following example shows how we can use these functions:</p>
+
+ <pre class="c++">
+person&amp; p = ...
+
+if (p.middle_name_present ())
+{
+ cout &lt;&lt; p.middle_name () &lt;&lt; endl;
+ p.middle_name_present (false); // Reset to the "not present" state.
+}
+ </pre>
+
+ <p>Finally, the <em>sequence</em> cardinality class covers all elements
+ that can occur more than once. In our example, the
+ <code>person</code> element in the <code>people</code> 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 <code>people</code>
+ class:</p>
+
+ <pre class="c++">
+class people
+{
+ // person
+ //
+ typedef xsde::fix_sequence&lt;person> person_sequence;
+ typedef person_sequence::iterator person_iterator;
+ typedef person_sequence::const_iterator person_const_iterator;
+
+ const person_sequence&amp;
+ person () const;
+
+ person_sequence&amp;
+ person ();
+};
+ </pre>
+
+ <p>The <code>person_sequence</code> type is a sequence container for the
+ element's values. It has an interface similar to <code>std::vector</code>
+ and we will discuss it in more detail shortly. The <code>person_iterator</code>
+ and <code>person_const_iterator</code> types are read-write and read-only
+ (constant) iterators for the <code>person_sequence</code>
+ container.</p>
+
+ <p>Unlike other two cardinality classes, the <em>sequence</em> 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.</p>
+
+ <p>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.</p>
+
+ <p>When exceptions are enabled, the fixed-length type sequences
+ are implemented in terms of the following class template:</p>
+
+ <pre class="c++">
+template &lt;typename T>
+class fix_sequence
+{
+public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T&amp; reference;
+ typedef const T&amp; 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&amp;);
+
+private:
+ fix_sequence (const fix_sequence&amp;);
+
+ fix_sequence&amp;
+ operator= (fix_sequence&amp;);
+
+public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ T&amp;
+ front ();
+
+ const T&amp;
+ front () const;
+
+ T&amp;
+ back ();
+
+ const T&amp;
+ back () const;
+
+ T&amp;
+ operator[] (size_t);
+
+ const T&amp;
+ 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&amp;);
+
+ iterator
+ insert (iterator, const T&amp;);
+
+ void
+ reserve (size_t);
+};
+ </pre>
+
+ <p>When C++ exceptions are disabled, the signatures of the
+ <code>push_back()</code>, <code>insert()</code>, and
+ <code>reserve()</code> functions change as follows:</p>
+
+ <pre class="c++">
+template &lt;typename T>
+class fix_sequence
+{
+public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+public:
+ error
+ push_back (const T&amp;);
+
+ error
+ insert (iterator, const T&amp;);
+
+ error
+ insert (iterator, const T&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+};
+ </pre>
+
+ <p>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.</p>
+
+ <p>When exceptions are enabled, the variable-length type sequences
+ are implemented in terms of the following class template:</p>
+
+ <pre class="c++">
+template &lt;typename T>
+class var_sequence
+{
+public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T&amp; reference;
+ typedef const T&amp; const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef &lt;implementation details> iterator;
+ typedef &lt;implementation details> const_iterator;
+
+public:
+ var_sequence ();
+
+ void
+ swap (var_sequence&amp;);
+
+private:
+ var_sequence (const var_sequence&amp;);
+
+ var_sequence&amp;
+ operator= (var_sequence&amp;);
+
+public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ T&amp;
+ front ();
+
+ const T&amp;
+ front () const;
+
+ T&amp;
+ back ();
+
+ const T&amp;
+ back () const;
+
+ T&amp;
+ operator[] (size_t);
+
+ const T&amp;
+ 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);
+};
+ </pre>
+
+ <p>Most of this interface is identical to the fixed-length type
+ version except for the <code>push_back()</code> and
+ <code>insert()</code> 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.</p>
+
+ <p>When C++ exceptions are disabled, the <code>push_back()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ return an error code to signal the out of memory condition:</p>
+
+ <pre class="c++">
+template &lt;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&amp; result);
+
+ error
+ reserve (size_t);
+};
+ </pre>
+
+
+ <p>When STL is enabled, the string sequence have the same
+ interface as <code>fix_sequence&lt;std::string></code>. When
+ STL is disabled and strings are mapped to <code>char*</code>,
+ the string sequence has a special interface. When C++ exceptions are
+ enabled, it has the following definition:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ 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);
+ };
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. Similar to <code>var_sequence</code>, these two functions
+ free the passed string if the reallocation of the underlying
+ sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ If you detach the underlying element string, then it should
+ eventually be deallocated with operator <code>delete[]</code>.</p>
+
+ <p>When C++ exceptions are disabled, the signatures of the
+ <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ in the <code>string_sequence</code> class change as follows:</p>
+
+ <pre class="c++">
+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&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <h2><a name="4.4">4.4 Compositors</a></h2>
+
+ <p>The XML Schema language provides three compositor constructs that
+ are used to group elements: <code>all</code>, <code>sequence</code>,
+ and <code>choice</code>. If a compositor has an <em>optional</em>
+ or <em>sequence</em> cardinality class (see <a href="#4.3">Section
+ 4.3, "Attributes and Elements"</a>) or if a compositor is
+ inside <code>choice</code>, 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.</p>
+
+ <p>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 <a href="#4.2">Section
+ 4.2, "Memory Management"</a>). Consider the following schema
+ fragment as an example:</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;sequence>
+ &lt;sequence minOccurs="0">
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string" maxOccurs="unbounded"/>
+ &lt;/sequence>
+ &lt;sequence maxOccurs="unbounded">
+ &lt;element name="c" type="int"/>
+ &lt;element name="d" type="string"/>
+ &lt;/sequence>
+ &lt;/sequence>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown below:</p>
+
+ <pre class="c++">
+// type (variable-length)
+//
+class type
+{
+public:
+ type ();
+
+private:
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+public:
+ // sequence (variable-length)
+ //
+ class sequence_type
+ {
+ public:
+ sequence_type ();
+
+ private:
+ sequence_type (const sequence_type&amp;);
+ sequence_type&amp; operator= (const sequence_type&amp;);
+
+ public:
+ // a
+ //
+ int
+ a () const;
+
+ int&amp;
+ 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&amp;
+ b () const;
+
+ b_sequence&amp;
+ b ();
+
+ private:
+ ...
+ };
+
+ bool
+ sequence_present () const;
+
+ void
+ sequence_present (bool);
+
+ const sequence_type&amp;
+ sequence () const;
+
+ sequence_type&amp;
+ sequence ();
+
+ void
+ sequence (sequence_type*);
+
+ // sequence1 (fixed-length)
+ //
+ class sequence1_type
+ {
+ public:
+ sequence1_type ();
+ sequence1_type (const sequence1_type&amp;);
+ sequence1_type&amp; operator= (const sequence1_type&amp;);
+
+ // c
+ //
+ int
+ c () const;
+
+ int&amp;
+ c ();
+
+ void
+ c (int);
+
+ // d
+ //
+ const std::string&amp;
+ d () const;
+
+ std::string&amp;
+ d ();
+
+ void
+ d (const std::string&amp;);
+
+ private:
+ ...
+ };
+
+ typedef xsde::fix_sequence&lt;sequence1_type> sequence1_sequence;
+ typedef sequence1_sequence::iterator sequence1_iterator;
+ typedef sequence1_sequence::const_iterator sequence1_const_iterator;
+
+ const sequence1_sequence&amp;
+ sequence1 () const;
+
+ sequence1_sequence&amp;
+ sequence1 ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The content of the outer <code>sequence</code> compositor is
+ generated in-line since this compositor belongs to the <em>one</em>
+ cardinality class. The first nested <code>sequence</code> compositor
+ is optional (<code>minOccurs="0"</code>), which results in a corresponding
+ nested class. Notice that the <code>sequence_type</code> is
+ variable-length and the accessor and modifier functions corresponding
+ to this <code>sequence</code> compositor are the same as for an
+ optional element or attribute. Similarly, the second nested
+ compositor is of the <em>sequence</em> cardinality class
+ (<code>maxOccurs="unbounded"</code>), which also results in a
+ nested class and a set of accessor functions.</p>
+
+ <p>Generated code corresponding to an <code>all</code> and
+ <code>sequence</code> compositor, whether in-line or as a
+ nested class, simply define accessor and modifier functions
+ for the elements that this compositor contains. For the
+ <code>choice</code> 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:</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;choice>
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string"/>
+ &lt;element name="c" type="boolean"/>
+ &lt;/choice>
+&lt;/complexType>
+ </pre>
+
+
+ <p>The corresponding object model class is shown next:</p>
+
+ <pre class="c++">
+// type (fixed-length)
+//
+class type
+{
+public:
+ type ();
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+ // 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&amp;
+ a ();
+
+ void
+ a (int);
+
+ // b
+ //
+ const std::string&amp;
+ b () const;
+
+ std::string&amp;
+ b ();
+
+ void
+ b (const std::string&amp;);
+
+ // c
+ //
+ bool
+ c () const;
+
+ bool&amp;
+ c ();
+
+ void
+ c (bool);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The extra type is the <code>choice_arm_tag</code> enumeration
+ which defines a set of tags corresponding to each choice arm.
+ There are also the <code>choice_arm()</code> 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:</p>
+
+ <pre class="c++">
+type&amp; x = ...
+
+switch (x.choice_arm ())
+{
+case type::a_tag:
+ {
+ cout &lt;&lt; "a: " &lt;&lt; x.a () &lt;&lt; endl;
+ break;
+ }
+case type::b_tag:
+ {
+ cout &lt;&lt; "b: " &lt;&lt; x.b () &lt;&lt; endl;
+ break;
+ }
+case type::c_tag:
+ {
+ cout &lt;&lt; "c: " &lt;&lt; x.c () &lt;&lt; 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";
+ </pre>
+
+ <p>The following slightly more complex example triggers the generation of
+ nested classes for the <code>choice</code> compositor as well as for
+ the <code>sequence</code> compositor inside <code>choice</code>.
+ Notice that the nested class for <code>sequence</code> is generated
+ because it is in <code>choice</code> even though its cardinality
+ class is <em>one</em>.</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;choice maxOccurs="unbounded">
+ &lt;sequence>
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string"/>
+ &lt;/sequence>
+ &lt;element name="c" type="boolean"/>
+ &lt;/choice>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown next:</p>
+
+ <pre class="c++">
+// type (variable-length)
+//
+class type
+{
+public:
+ type ();
+
+private:
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+public:
+ // choice (fixed-length)
+ //
+ class choice_type
+ {
+ public:
+ choice_type ();
+ choice_type (const choice_type&amp;);
+ choice_type&amp; operator= (const choice_type&amp;);
+
+ 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&amp;);
+ sequence_type&amp; operator= (const sequence_type&amp;);
+
+ // a
+ //
+ int
+ a () const;
+
+ int&amp;
+ a ();
+
+ void
+ a (int);
+
+ // b
+ //
+ const std::string&amp;
+ b () const;
+
+ std::string&amp;
+ b ();
+
+ void
+ b (const std::string&amp;);
+
+ private:
+ ...
+ };
+
+ const sequence_type&amp;
+ sequence () const;
+
+ sequence_type&amp;
+ sequence ();
+
+ void
+ sequence (const sequence_type&amp;);
+
+ // c
+ //
+ bool
+ c () const;
+
+ bool&amp;
+ c ();
+
+ void
+ c (bool);
+
+ private:
+ ...
+ };
+
+ typedef xsde::fix_sequence&lt;choice_type> choice_sequence;
+ typedef choice_sequence::iterator choice_iterator;
+ typedef choice_sequence::const_iterator choice_const_iterator;
+
+ const choice_sequence&amp;
+ choice () const;
+
+ choice_sequence&amp;
+ choice ();
+
+private:
+ ...
+};
+ </pre>
+
+ <h2><a name="4.5">4.5 Accessing the Object Model</a></h2>
+
+ <p>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
+ <code>people.xml</code> file:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;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&lt;people> ppl (people_p.post ());
+
+ // Iterate over individual person records.
+ //
+ people::person_sequence&amp; ps = ppl->person ();
+
+ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+ {
+ person&amp; p = *i;
+
+ // Print names: first-name and last-name are required elements,
+ // middle-name is optional.
+ //
+ cout &lt;&lt; "name: " &lt;&lt; p.first_name () &lt;&lt; " ";
+
+ if (p.middle_name_present ())
+ cout &lt;&lt; p.middle_name () &lt;&lt; " ";
+
+ cout &lt;&lt; p.last_name () &lt;&lt; endl;
+
+ // Print gender, age, and id which are all required.
+ //
+ cout &lt;&lt; "gender: " &lt;&lt; p.gender () &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; p.age () &lt;&lt; endl
+ &lt;&lt; "id: " &lt;&lt; p.id () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+}
+ </pre>
+
+ <p>This code shows common patterns of accessing elements and attributes
+ with different cardinality classes. For the sequence element
+ (<code>person</code> in the <code>people</code> type) we first obtain a
+ reference to the container and then iterate over individual
+ records. The values of elements and attributes with the
+ <em>one</em> cardinality class (<code>first-name</code>,
+ <code>last-name</code>, <code>gender</code>, <code>age</code>,
+ and <code>id</code>) can be obtained directly by calling the
+ corresponding accessor functions. For the optional
+ <code>middle-name</code> element we first check if the value is present
+ and only then call the corresponding accessor to retrieve it.</p>
+
+ <p>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 (<code>ps</code> and <code>p</code> 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.</p>
+
+ <p>If we run the above application on our sample
+ <code>people.xml</code>, the output looks as follows:</p>
+
+ <pre class="terminal">
+name: John Doe
+gender: male
+age: 32
+id: 1
+
+name: Jane Mary Doe
+gender: female
+age: 28
+id: 2
+ </pre>
+
+
+ <h2><a name="4.6">4.6 Modifying the Object Model</a></h2>
+
+ <p>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
+ <code>people.xml</code> file:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;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&lt;people> ppl (people_p.post ());
+
+ // Iterate over individual person records and increment
+ // the age.
+ //
+ people::person_sequence&amp; 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&amp; john = ps[0];
+ person&amp; 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 ();
+}
+ </pre>
+
+ <p>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 <code>middle-name</code> element as well
+ as clear its value. Finally, the example adds a copy of the
+ John Doe record to the <code>person</code> element sequence.</p>
+
+ <p>Note that in this case using references for the <code>ps</code>,
+ <code>john</code>, and <code>jane</code> 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.</p>
+
+ <p>If we run the above application on our sample <code>people.xml</code>,
+ the output looks as follows:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>33&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>29&lt;/age>
+ &lt;/person>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>33&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <h2><a name="4.7">4.7 Creating the Object Model from Scratch</a></h2>
+
+ <p>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 <code>people.xml</code>
+ file:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+#include "people.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+ people ppl;
+ people::person_sequence&amp; 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 ();
+}
+ </pre>
+
+ <p>The only new part in the above application is the calls
+ to the <code>people</code> and <code>person</code>
+ constructors. As a general rule, a newly created instance
+ does not assign any values to its elements and attributes.
+ That is, members with the <em>one</em> cardinality
+ class are left uninitialized, members with the <em>optional</em>
+ cardinality class are set to the "not present" state,
+ and members with the <em>sequence</em> cardinality class
+ have empty containers. After the instance has been
+ created, we can set its element and attribute values
+ using the modifier functions.</p>
+
+ <p>The above application produces the following output:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0" ?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <h2><a name="4.8">4.8 Customizing the Object Model</a></h2>
+
+ <p>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 <code>void*</code>,
+ 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
+ <a href="#6.1">Section 6.1, "Customizing Parsers and
+ Serializers"</a> for details.</p>
+
+ <p>To instruct the XSD/e compiler to include custom data
+ in a specific object model class, we need to use the
+ <code>--custom-data</code> 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
+ <code>type::sequence1</code>. If we would like to
+ add the ability to store custom data in the generated
+ <code>person</code> class for our person records
+ vocabulary, we can compile <code>people.xsd</code>
+ like this:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --custom-type person people.xsd
+ </pre>
+
+ <p>The resulting <code>person</code> class will have the
+ following extra set of type definitions and functions:</p>
+
+
+ <pre class="c++">
+// 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&amp;
+ custom_data () const;
+
+ custom_data_sequence&amp;
+ custom_data ();
+};
+ </pre>
+
+ <p>Notice also that the <code>person</code> class is now variable-length
+ since it contains a sequence. When C++ exceptions are enabled, the
+ custom data sequence has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+private:
+ data_sequence (const data_sequence&amp;);
+
+ data_sequence&amp;
+ operator= (data_sequence&amp;);
+
+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);
+};
+ </pre>
+
+ <p>The <code>destructor()</code> 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 <code>push_back()</code> and <code>insert()</code>
+ functions free the passed object if the reallocation of the
+ underlying sequence buffer fails.</p>
+
+ <p>When exceptions are disabled, the <code>push_back()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ return an error code to signal the out of memory condition:</p>
+
+ <pre class="c++">
+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&amp; result);
+
+ error
+ reserve (size_t);
+};
+ </pre>
+
+ <p>The following code fragment shows how we can store and retrieve
+ custom data in the <code>person</code> class:</p>
+
+ <pre class="c++">
+class data
+{
+ ...
+};
+
+void
+destroy_data (void* p, size_t)
+{
+ delete static_cast&lt;data*> (p);
+}
+
+person&amp; = ...;
+person::custom_data_sequence&amp; cd = p.custom_data ();
+
+cd.destructor (&amp;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&lt;data*> (*i);
+}
+ </pre>
+
+
+ <!-- Built-in XML Schema Type Parsers -->
+
+
+ <h1><a name="5">5 Mapping for Built-In XML Schema Types</a></h1>
+
+ <p>In XML Schema, built-in types, such as <code>int</code>,
+ <code>string</code>, etc., are defined in the XML Schema namespace.
+ By default this namespace is mapped to C++ namespace
+ <code>xml_schema</code> (this mapping can be altered
+ with the <code>--namespace-map</code> 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.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Alias in the <code>xml_schema</code> namespace</th>
+ <th>C++ type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_</code></td>
+ <td><code>long</code> or<br/> <code>long&nbsp;long</code><br/>
+ <a href="#3.5">Section 3.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long</code></td>
+ <td><code>unsigned&nbsp;long</code> or
+ <code>unsigned&nbsp;long&nbsp;long</code><br/>
+ <a href="#3.5">Section 3.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer</code></td>
+ <td><code>unsigned long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer</code></td>
+ <td><code>unsigned long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_</code></td>
+ <td><code>float</code></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens</code></td>
+ <td><a href="#5.2">Section 5.2, "Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname</code></td>
+ <td><a href="#5.1">Section 5.1, "Mapping for <code>QName</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs</code></td>
+ <td><a href="#5.2">Section 5.2, "Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary</code></td>
+ <td><a href="#5.3">Section 5.3, "Mapping for <code>base64Binary</code> and <code>hexBinary</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary</code></td>
+ <td><a href="#5.3">Section 5.3, "Mapping for <code>base64Binary</code> and <code>hexBinary</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date</code></td>
+ <td><a href="#5.5">Section 5.5, "Mapping for <code>date</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time</code></td>
+ <td><a href="#5.6">Section 5.6, "Mapping for <code>dateTime</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration</code></td>
+ <td><a href="#5.7">Section 5.7, "Mapping for <code>duration</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday</code></td>
+ <td><a href="#5.8">Section 5.8, "Mapping for <code>gDay</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth</code></td>
+ <td><a href="#5.9">Section 5.9, "Mapping for <code>gMonth</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day</code></td>
+ <td><a href="#5.10">Section 5.10, "Mapping for <code>gMonthDay</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear</code></td>
+ <td><a href="#5.11">Section 5.11, "Mapping for <code>gYear</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month</code></td>
+ <td><a href="#5.12">Section 5.12, "Mapping for <code>gYearMonth</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time</code></td>
+ <td><a href="#5.13">Section 5.13, "Mapping for <code>time</code>"</a></td>
+ </tr>
+ </table>
+
+ <p>As you can see from the table above a number of built-in
+ XML Schema types are mapped to fundamental C++ types such
+ as <code>int</code> or <code>bool</code>. All string-based
+ XML Schema types are mapped to either <code>std::string</code>
+ or <code>char*</code>, depending on whether the use of STL is
+ enabled or not. A number of built-in types, such as
+ <code>QName</code>, 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.</p>
+
+ <p>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
+ <code>xml_schema</code> namespace is used (C++ does not allow
+ inheritance from fundamental types). For example:</p>
+
+ <pre class="xml">
+&lt;complexType name="measure">
+ &lt;simpleContent>
+ &lt;extension base="int">
+ &lt;attribute name="unit" type="string" use="required"/>
+ &lt;/extension>
+ &lt;/simpleContent>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown below:</p>
+
+ <pre class="c++">
+// measure (fixed-length)
+//
+class measure: public xml_schema::int_base
+{
+public:
+ measure ();
+ measure (const measure&amp;);
+ measure&amp; operator= (const measure&amp;);
+
+ // unit
+ //
+ const std::string&amp;
+ unit () const;
+
+ std::string&amp;
+ unit ();
+
+ void
+ unit (const std::string&amp;);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The <code>xml_schema::int_base</code> class has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class int_base
+ {
+ public:
+ int_base ();
+
+ int_base&amp;
+ operator= (int);
+
+ public:
+ int
+ base_value () const;
+
+ int&amp;
+ base_value ();
+
+ void
+ base_value (int);
+
+ operator const int&amp; () const;
+ operator int&amp; ();
+ };
+}
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_base
+ {
+ public:
+ string_base ();
+
+ string_base&amp;
+ operator= (char* x)
+
+ public:
+ const char*
+ base_value () const;
+
+ char*
+ base_value ();
+
+ void
+ base_value (char* x);
+
+ operator const char* () const;
+ operator char* ();
+ };
+}
+ </pre>
+
+ <p>Note that the <code>string_base</code> object assumes ownership
+ of the strings passed to the assignment operator and the
+ <code>base_value()</code> modifier.</p>
+
+ <h2><a name="5.1">5.1 Mapping for <code>QName</code></a></h2>
+
+ <p>The <code>QName</code> built-in XML Schema type is mapped to the
+ <code>qname</code> class which represents an XML qualified name.
+ With STL enabled (<a href="#3.1">Section 3.1, "Standard Template
+ Library"</a>), it has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#3.3">Section 3.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="5.2">5.2 Mapping for <code>NMTOKENS</code> and <code>IDREFS</code></a></h2>
+
+ <p>The <code>NMTOKENS</code> and <code>IDREFS</code> built-in
+ XML Schema types are mapped to the string sequence type which
+ is discussed in <a href="#4.3">Section 4.3, "Attributes and
+ Elements"</a>.</p>
+
+ <h2><a name="5.3">5.3 Mapping for <code>base64Binary</code> and <code>hexBinary</code></a></h2>
+
+ <p>The <code>base64Binary</code> and <code>hexBinary</code> built-in
+ XML Schema types are mapped to the <code>buffer</code> class.
+ With C++ exceptions enabled (<a href="#3.3">Section 3.3, "C++
+ Exceptions"</a>), it has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ 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&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> class has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="5.4">5.4 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>time_zone</code> base class is used to represent this
+ information:</p>
+
+ <pre class="c++">
+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&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> 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.</p>
+
+ <h2><a name="5.5">5.5 Mapping for <code>date</code></a></h2>
+
+ <p>The <code>date</code> built-in XML Schema type is mapped to the
+ <code>date</code> 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 <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="5.6">5.6 Mapping for <code>dateTime</code></a></h2>
+
+ <p>The <code>dateTime</code> built-in XML Schema type is mapped to the
+ <code>date_time</code> 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
+ <code>xml_schema::time_zone</code> class refer to <a href="#5.4">Section
+ 5.4, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="5.7">5.7 Mapping for <code>duration</code></a></h2>
+
+ <p>The <code>duration</code> built-in XML Schema type is mapped to the
+ <code>duration</code> class which represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+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&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="5.8">5.8 Mapping for <code>gDay</code></a></h2>
+
+ <p>The <code>gDay</code> built-in XML Schema type is mapped to the
+ <code>gday</code> class which represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="5.9">5.9 Mapping for <code>gMonth</code></a></h2>
+
+ <p>The <code>gMonth</code> built-in XML Schema type is mapped to the
+ <code>gmonth</code> class which represents a month of the year
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="5.10">5.10 Mapping for <code>gMonthDay</code></a></h2>
+
+ <p>The <code>gMonthDay</code> built-in XML Schema type is mapped to the
+ <code>gmonth_day</code> 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 <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="5.11">5.11 Mapping for <code>gYear</code></a></h2>
+
+ <p>The <code>gYear</code> built-in XML Schema type is mapped to the
+ <code>gyear</code> class which represents a year with
+ an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="5.12">5.12 Mapping for <code>gYearMonth</code></a></h2>
+
+ <p>The <code>gYearMonth</code> built-in XML Schema type is mapped to the
+ <code>gyear_month</code> class which represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="5.13">5.13 Mapping for <code>time</code></a></h2>
+
+ <p>The <code>time</code> built-in XML Schema type is mapped to the
+ <code>time</code> class which represents hours, minutes,
+ and seconds with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+ <!-- Parsing and Serialization -->
+
+ <h1><a name="6">6 Parsing and Serialization</a></h1>
+
+ <p>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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">Embedded
+ C++/Parser Mapping Getting Started Guide</a> and the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">Embedded
+ C++/Serializer Mapping Getting Started Guide</a> for more detailed
+ information on these mappings.</p>
+
+ <p>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 <code>--generate-parser</code>
+ XSD/e command line option. Similarly, to generate serializer
+ skeletons and implementations, you will need to use the
+ <code>--generate-serializer</code> option.</p>
+
+ <p>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 <code>--generate-aggregate</code> options. Aggregate
+ classes instantiate and connect all the necessary individual
+ parser and serializer implementations for a particular root
+ element or type. Consider again the <code>hello.xsd</code>
+ schema from <a href="#2">Chapter 2, "Hello World Example"</a>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>If we compile this schema with the <code>--generate-parser</code>,
+ <code>--generate-serializer</code>, and <code>--generate-aggregate</code>
+ options, we will have two aggregate classes, <code>hello_paggr</code>
+ and <code>hello_saggr</code>, generated for the root <code>hello</code>
+ element. The interface of the <code>hello_paggr</code> class is
+ presented below:</p>
+
+ <pre class="c++">
+class hello_paggr
+{
+public:
+ hello_paggr ();
+
+ void
+ pre ();
+
+ hello*
+ post ();
+
+ hello_pimpl&amp;
+ root_parser ();
+
+ static const char*
+ root_name ();
+
+ static const char*
+ root_namespace ();
+};
+ </pre>
+
+ <p>The <code>pre()</code> and <code>post()</code> functions
+ call the corresponding callbacks on the root parser
+ implementation. The <code>root_parser()</code> function
+ returns the root parser implementation. The <code>root_name()</code>
+ and <code>root_namespace()</code> functions return the
+ root element name and namespace, respectively.</p>
+
+ <p>As was shown in <a href="#2">Chapter 2, "Hello World Example"</a>,
+ we can use this parser aggregate to create the document parser
+ (supplied by the C++/Parser mapping) and perform the parsing:</p>
+
+ <pre class="c++">
+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 ();
+ </pre>
+
+ <p>For more information on the <code>document_pimpl</code> class,
+ including the other variants of the <code>parse()</code> function
+ as well as error handling during parsing, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded C++/Parser
+ Mapping Getting Started Guide.</p>
+
+ <p>The interface of the <code>hello_saggr</code> serializer aggregate
+ mirrors that of <code>hello_paggr</code> and is presented below:</p>
+
+ <pre class="c++">
+class hello_saggr
+{
+public:
+ hello_saggr ();
+
+ void
+ pre (const hello&amp;);
+
+ void
+ post ();
+
+ hello_simpl&amp;
+ root_serializer ();
+
+ static const char*
+ root_name ();
+
+ static const char*
+ root_namespace ();
+};
+ </pre>
+
+ <p>The <code>pre()</code> and <code>post()</code> functions
+ call the corresponding callbacks on the root serializer
+ implementation. The <code>root_serializer()</code> function
+ returns the root serializer implementation. The
+ <code>root_name()</code> and <code>root_namespace()</code>
+ functions return the root element name and namespace,
+ respectively.</p>
+
+ <p>As was shown in <a href="#2">Chapter 2, "Hello World Example"</a>,
+ we can use this serializer aggregate to create the document
+ serializer (supplied by the C++/Serializer mapping) and perform
+ the serialization:</p>
+
+ <pre class="c++">
+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 ();
+ </pre>
+
+ <p>For more information on the <code>document_simpl</code> class,
+ including the other variants of the <code>serialize()</code>
+ function as well as error handling during serialization, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide.</p>
+
+ <h2><a name="6.1">6.1 Customizing Parsers and Serializers</a></h2>
+
+ <p>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.</p>
+
+ <p>To request customization of a parser or serializer
+ implementation, you will need to specify the
+ <code>--custom-parser</code> or <code>--custom-serializer</code>
+ option, respectively. The argument format for these two options
+ is <code>type[=base[/include]]</code>. The <code>type</code>
+ component is the XML Schema type name being customized. Optional
+ <code>base</code> is a C++ name that should be given to the
+ generated version. It is normally used as a base for the custom
+ implementation. Optional <code>include</code> is the header file
+ that defines the custom implementation. It is <code>#include</code>'ed
+ into the generated code immediately after (if <code>base</code>
+ is specified) or instead of the generated version. The following
+ examples show how we can use these options:</p>
+
+ <pre class="terminal">
+--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
+ </pre>
+
+ <p>The first version instructs the XSD/e compiler not to generate
+ the parser implementation for the <code>foo</code> XML Schema
+ type. The second version instructs the compiler to generate
+ the parser implementation for type <code>foo</code> but call
+ it <code>foo_base_pimpl</code>. The third version is similar to the
+ second except that the compiler generates the <code>#include</code>
+ directive with the <code>foo/foo-custom.hxx</code> file (which
+ presumably defines <code>foo_pimpl</code>) right after the
+ <code>foo_base_pimpl</code> class. The last version instructs
+ the XSD/e compiler to include <code>foo/foo-custom.hxx</code>
+ instead of generating the parser implementation for
+ <code>foo</code>. 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 <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> for details.</p>
+
+ <p>Once you specify the <code>--custom-parser</code> or
+ <code>--custom-serializer</code> 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.</p>
+
+ <p>In the remainder of this section we will examine how to
+ customize the <code>people</code> parser and serializer
+ implementations from the example presented in <a href="#4">Chapter 4,
+ "Working with Object Models"</a>. 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 <code>filter</code>
+ example in the XSD/e distribution. Other examples
+ related to parser/serializer customization are
+ <code>wildcard</code> and <code>streaming</code>.</p>
+
+ <p>First, we compile the <code>people.xsd</code> schema
+ and instruct the XSD/e compiler to customize the
+ parser and serializer implementations for the <code>people</code>
+ XML Schema type:</p>
+
+ <pre class="terminal">
+$ 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
+ </pre>
+
+ <p>The custom <code>people_pimpl</code> parser implementation
+ is based on the generated version and is saved to
+ <code>people-custom-pimpl.hxx</code>:</p>
+
+ <pre class="c++">
+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&amp; p)
+ {
+ // Check if the age constraints are met.
+ //
+ unsigned short age = p.age ();
+
+ if (age >= min_age_ &amp;&amp; age &lt;= max_age_)
+ people_base_pimpl::person (p);
+ }
+
+private:
+ unsigned short min_age_;
+ unsigned short max_age_;
+};
+ </pre>
+
+ <p>Here we override the <code>person()</code> 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 <code>person</code> 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:</p>
+
+<pre class="c++">
+virtual void
+person (const ::person* p)
+{
+ unsigned short age = p->age ();
+
+ if (age >= min_age_ &amp;&amp; age &lt;= max_age_)
+ people_base_pimpl::person (p);
+ else
+ delete p;
+}
+ </pre>
+
+ <p>The custom <code>people_simpl</code> parser implementation
+ is also based on the generated version and is saved to
+ <code>people-custom-simpl.hxx</code>:</p>
+
+ <pre class="c++">
+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&amp; i = people_base_simpl_state_.person_;
+ people::person_const_iterator&amp; e = people_base_simpl_state_.person_end_;
+
+ for (; i != e; ++i)
+ {
+ if (i->gender () == gender_)
+ break;
+ }
+
+ return i != e;
+ }
+
+private:
+ gender gender_;
+};
+ </pre>
+
+ <p>Here we override the <code>person_next()</code> callback
+ where we locate the next record that satisfies the filter
+ conditions. Note that we use the serialization state
+ provided by the generated <code>people_base_simpl</code>
+ implementation.</p>
+
+ <p>The following code fragment shows a test driver that uses
+ the above implementations to filter the data during parsing
+ and serialization:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;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&amp; 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&lt;people> ppl (people_p.post ());
+
+ // Print what we've got.
+ //
+ people::person_sequence&amp; ps = ppl->person ();
+
+ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+ {
+ cerr &lt;&lt; "first: " &lt;&lt; i->first_name () &lt;&lt; endl
+ &lt;&lt; "last: " &lt;&lt; i->last_name () &lt;&lt; endl
+ &lt;&lt; "gender: " &lt;&lt; i->gender () &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; i->age () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+
+ // Serialize.
+ //
+ people_saggr people_s;
+ people_simpl&amp; 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 ();
+}
+ </pre>
+
+ <p>If we run this test driver on the following XML document:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+ &lt;person>
+ &lt;first-name>Joe&lt;/first-name>
+ &lt;last-name>Dirt&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>25&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <p>We will get the following output:</p>
+
+ <pre class="terminal">
+first: Jane
+last: Doe
+gender: female
+age: 28
+
+first: Joe
+last: Dirt
+gender: male
+age: 25
+
+&lt;people>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+
+ </div>
+</div>
+
+
+</body>
+</html>
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
--- /dev/null
+++ b/documentation/cxx/parser/guide/figure-1.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/tmp"
+ sodipodi:docname="figure-1.svg"
+ inkscape:export-filename="/home/boris/tmp/figure-1.png"
+ inkscape:export-xdpi="76.195885"
+ inkscape:export-ydpi="76.195885">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path2934"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_l"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_l"
+ style="overflow:visible">
+ <path
+ id="path2875"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.8) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path2928"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_m"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_m"
+ style="overflow:visible">
+ <path
+ id="path2872"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path2937"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path2910"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="328.23027"
+ inkscape:cy="733.01096"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="991"
+ inkscape:window-x="154"
+ inkscape:window-y="44" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g3902">
+ <rect
+ y="194.64178"
+ x="24.142784"
+ height="106.2678"
+ width="149.70432"
+ id="rect1872"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.29799986;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3038"
+ y="219.99649"
+ x="28.284279"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="219.99649"
+ x="28.284279"
+ id="tspan3064"
+ sodipodi:role="line">class people_pimpl</tspan><tspan
+ y="236.24649"
+ x="28.284279"
+ id="tspan3066"
+ sodipodi:role="line">{</tspan><tspan
+ y="252.49649"
+ x="28.284279"
+ id="tspan3068"
+ sodipodi:role="line"> void </tspan><tspan
+ y="268.74649"
+ x="28.284279"
+ id="tspan3070"
+ sodipodi:role="line"> person ();</tspan><tspan
+ y="284.99649"
+ x="28.284279"
+ id="tspan3072"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <g
+ id="g3881">
+ <rect
+ y="124.93772"
+ x="252.43373"
+ height="245.67592"
+ width="180.01601"
+ id="rect5750"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:9.12976837;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text5752"
+ y="148.27567"
+ x="257.5889"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="148.27567"
+ x="257.5889"
+ id="tspan5900"
+ sodipodi:role="line">class person_pimpl</tspan><tspan
+ y="161.27567"
+ x="257.5889"
+ id="tspan5902"
+ sodipodi:role="line">{</tspan><tspan
+ y="174.27567"
+ x="257.5889"
+ id="tspan5904"
+ sodipodi:role="line"> void</tspan><tspan
+ y="187.27567"
+ x="257.5889"
+ id="tspan5906"
+ sodipodi:role="line"> first_name (string);</tspan><tspan
+ y="200.27567"
+ x="257.5889"
+ id="tspan5908"
+ sodipodi:role="line" /><tspan
+ y="213.27567"
+ x="257.5889"
+ id="tspan5910"
+ sodipodi:role="line"> void</tspan><tspan
+ y="226.27567"
+ x="257.5889"
+ id="tspan5912"
+ sodipodi:role="line"> last_name (string);</tspan><tspan
+ y="239.27567"
+ x="257.5889"
+ id="tspan5914"
+ sodipodi:role="line" /><tspan
+ y="252.27567"
+ x="257.5889"
+ id="tspan5916"
+ sodipodi:role="line"> void</tspan><tspan
+ y="265.27567"
+ x="257.5889"
+ id="tspan5918"
+ sodipodi:role="line"> gender ();</tspan><tspan
+ y="278.27567"
+ x="257.5889"
+ id="tspan5920"
+ sodipodi:role="line" /><tspan
+ y="291.27567"
+ x="257.5889"
+ id="tspan5922"
+ sodipodi:role="line"> void</tspan><tspan
+ y="304.27567"
+ x="257.5889"
+ id="tspan5924"
+ sodipodi:role="line"> age (short);</tspan><tspan
+ y="317.27567"
+ x="257.5889"
+ id="tspan5926"
+ sodipodi:role="line"> </tspan><tspan
+ y="330.27567"
+ x="257.5889"
+ id="tspan5928"
+ sodipodi:role="line"> void</tspan><tspan
+ y="343.27567"
+ x="257.5889"
+ id="tspan5930"
+ sodipodi:role="line"> post_person ();</tspan><tspan
+ y="356.27567"
+ x="257.5889"
+ id="tspan5932"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <g
+ id="g3845">
+ <rect
+ y="77.741814"
+ x="506.28357"
+ height="99.610825"
+ width="151.1286"
+ id="rect5955"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ transform="translate(-5.050762,12.10153)"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ id="flowRoot5957"
+ xml:space="preserve"><flowRegion
+ id="flowRegion5959"><rect
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ y="74.534515"
+ x="516.18793"
+ height="88.893425"
+ width="143.44167"
+ id="rect5961" /></flowRegion><flowPara
+ id="flowPara5965">class string_pimpl</flowPara><flowPara
+ id="flowPara5967">{</flowPara><flowPara
+ id="flowPara5969"> string</flowPara><flowPara
+ id="flowPara5971"> post_string ();</flowPara><flowPara
+ id="flowPara5973">};</flowPara><flowPara
+ id="flowPara5975" /></flowRoot> </g>
+ <g
+ id="g3857">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5977"
+ width="151.1286"
+ height="99.610825"
+ x="506.28357"
+ y="316.15808" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot5979"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.050761,250.5178)"
+ inkscape:export-filename="/tmp/figure-1.png"
+ inkscape:export-xdpi="546.53815"
+ inkscape:export-ydpi="546.53815"><flowRegion
+ id="flowRegion5981"><rect
+ id="rect5983"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara5985">class short_pimpl</flowPara><flowPara
+ id="flowPara5987">{</flowPara><flowPara
+ id="flowPara5989"> short</flowPara><flowPara
+ id="flowPara5991"> post_short ();</flowPara><flowPara
+ id="flowPara5993">};</flowPara><flowPara
+ id="flowPara5995" /></flowRoot> </g>
+ <g
+ id="g3869">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6023"
+ width="151.1286"
+ height="99.610825"
+ x="505.7785"
+ y="196.93977" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot6025"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.555838,129.2792)"><flowRegion
+ id="flowRegion6027"><rect
+ id="rect6029"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara6031">class gender_pimpl</flowPara><flowPara
+ id="flowPara6033">{</flowPara><flowPara
+ id="flowPara6035"> void</flowPara><flowPara
+ id="flowPara6037"> post_gender ();</flowPara><flowPara
+ id="flowPara6039">};</flowPara><flowPara
+ id="flowPara6041" /></flowRoot> </g>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend)"
+ d="M 265.67011,339.69956 L 210.41811,339.34242 L 210.77124,264.14332 L 127.7843,264.4432"
+ id="path6051"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccs" />
+ <path
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-type="polyline"
+ id="path6077"
+ d="M 518.20825,383.6412 L 471.23616,384.14628 L 471.4887,300.55615 L 368.70568,300.80869"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 517.1981,262.42289 L 353.55339,262.42289"
+ id="path6081"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccs" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 518.57143,145.93361 L 470.35714,146.14281 L 470.53572,183.07646 L 431.42857,183.79075"
+ id="path6089"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 470.46175,178.43361 L 470.89286,222.36218 L 423.21428,222.71932"
+ id="path6091"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="ccc" />
+ </g>
+</svg>
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: "
+<div align=center>
+ <h1><big>Embedded C++/Parser Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ 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 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Parser Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2009 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,parser,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Parser Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ ol.steps {
+ padding-left : 1.8em;
+ }
+
+ ol.steps li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+
+ /* XML Schema features table. */
+ #features {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #features th, #features td {
+ border: 1px solid;
+ padding : 0.6em 0.6em 0.6em 0.6em;
+ }
+
+ #features th {
+ background : #cde8f6;
+ }
+
+ #features td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Parser Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing XML Document and Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Parser Skeletons</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Implementing the Gender Parser</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Implementing the Person Parser</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">Implementing the People Parser</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">Connecting the Parsers Together</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Type Maps</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Object Model</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Type Map File Format</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Parser Implementations</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Standard Template Library</a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">C++ Exceptions</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">XML Schema Validation</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">64-bit Integer Type</a></td></tr>
+ <tr><th>5.6</th><td><a href="#5.6">Parser Reuse</a></td></tr>
+ <tr><th>5.7</th><td><a href="#5.7">Support for Polymorphism</a></td></tr>
+ <tr><th>5.8</th><td><a href="#5.8">A Minimal Example</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Built-In XML Schema Type Parsers</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1"><code>QName</code> Parser</a></td></tr>
+ <tr><th>6.2</th><td><a href="#6.2"><code>NMTOKENS</code> and <code>IDREFS</code> Parsers</a></td></tr>
+ <tr><th>6.3</th><td><a href="#6.3"><code>base64Binary</code> and <code>hexBinary</code> Parsers</a></td></tr>
+ <tr><th>6.4</th><td><a href="#6.4">Time Zone Representation</a></td></tr>
+ <tr><th>6.5</th><td><a href="#6.5"><code>date</code> Parser</a></td></tr>
+ <tr><th>6.6</th><td><a href="#6.6"><code>dateTime</code> Parser</a></td></tr>
+ <tr><th>6.7</th><td><a href="#6.7"><code>duration</code> Parser</a></td></tr>
+ <tr><th>6.8</th><td><a href="#6.8"><code>gDay</code> Parser</a></td></tr>
+ <tr><th>6.9</th><td><a href="#6.9"><code>gMonth</code> Parser</a></td></tr>
+ <tr><th>6.10</th><td><a href="#6.10"><code>gMonthDay</code> Parser</a></td></tr>
+ <tr><th>6.11</th><td><a href="#6.11"><code>gYear</code> Parser</a></td></tr>
+ <tr><th>6.12</th><td><a href="#6.12"><code>gYearMonth</code> Parser</a></td></tr>
+ <tr><th>6.13</th><td><a href="#6.13"><code>time</code> Parser</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>7</th><td><a href="#7">Document Parser and Error Handling</a>
+ <table class="toc">
+ <tr><th>7.1</th><td><a href="#7.1">Document Parser</a></td></tr>
+ <tr><th>7.2</th><td><a href="#7.2">Exceptions</a></td></tr>
+ <tr><th>7.3</th><td><a href="#7.3">Error Codes</a></td></tr>
+ <tr><th>7.4</th><td><a href="#7.4">Reusing Parsers after an Error</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th></th><td><a href="#A">Appendix A &mdash; Supported XML Schema Constructs</a></td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>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.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/parser/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Parser mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>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.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>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.
+ </p>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>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:
+ </p>
+
+ <ul class="list">
+ <li>Text-based representation results in inefficient use of
+ resources.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>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.</li>
+
+ <li>String-based flow control defers error detection to runtime.
+ It also reduces code readability and maintainability.</li>
+
+ <li>Lack of type safety because all information is represented
+ as text.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>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.</p>
+
+ <p>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:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> 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.</li>
+
+ <li><b>Natural representation.</b> 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.
+ </li>
+
+ <li><b>Concise code.</b> With a separate parser skeleton for each
+ XML Schema type, the application implementation is
+ simpler and thus easier to read and understand.</li>
+
+ <li><b>Safety.</b> 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.</li>
+
+ <li><b>Maintainability.</b> 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.</li>
+
+ <li><b>Efficiency.</b> 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.</li>
+ </ul>
+
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>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 <code>hello</code>
+ example which can be found in the <code>examples/cxx/parser/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing XML Document and Schema</a></h2>
+
+ <p>First, we need to get an idea about the structure
+ of the XML documents we are going to process. Our
+ <code>hello.xml</code>, for example, could look like this:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>earth&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with the XML Schema language, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in <code>hello.xml</code>. The <code>hello</code> type
+ is defined as a sequence of the nested <code>greeting</code> and
+ <code>name</code> 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 <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounde</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>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.</p>
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++ parser
+ skeletons. To do this we invoke the XSD/e compiler from a terminal
+ (UNIX) or a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-parser hello.xsd
+ </pre>
+
+ <p>The XSD/e compiler produces two C++ files: <code>hello-pskel.hxx</code>
+ and <code>hello-pskel.cxx</code>. The following code fragment is taken
+ from <code>hello-pskel.hxx</code>; it should give you an idea about what
+ gets generated:
+ </p>
+
+ <pre class="c++">
+class hello_pskel
+{
+public:
+ // Parser callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ greeting (const std::string&amp;);
+
+ virtual void
+ name (const std::string&amp;);
+
+ virtual void
+ post_hello ();
+
+ // Parser construction API.
+ //
+ void
+ greeting_parser (xml_schema::string_pskel&amp;);
+
+ void
+ name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ parsers (xml_schema::string_pskel&amp; /* greeting */,
+ xml_schema::string_pskel&amp; /* name */);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>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.</p>
+
+ <p>The <code>pre()</code> function is an initialization callback. It is
+ called when a new element of type <code>hello</code> 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.</p>
+
+ <p>The <code>post_hello()</code> function is a finalization callback. Its
+ name is constructed by adding the parser skeleton name to the
+ <code>post_</code> 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
+ <code>post_hello()</code> is <code>void</code> which means there
+ is nothing to return. More on parser return types later.
+ </p>
+
+ <p>You may be wondering why the finalization callback is called
+ <code>post_hello()</code> instead of <code>post()</code> just
+ like <code>pre()</code>. 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.</p>
+
+ <p>The <code>greeting()</code> and <code>name()</code> functions are
+ called when the <code>greeting</code> and <code>name</code> elements
+ have been parsed, respectively. Their arguments are of type
+ <code>std::string</code> and contain the data extracted from XML.</p>
+
+ <p>The last three functions are for connecting parsers to each other.
+ For example, there is a predefined parser for built-in XML Schema type
+ <code>string</code> in the XSD/e runtime. We will be using
+ it to parse the contents of <code>greeting</code> and
+ <code>name</code> elements, as shown in the next section.</p>
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>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:
+ </p>
+
+ <pre class="c++">
+#include &lt;iostream>
+#include "hello-pskel.hxx"
+
+class hello_pimpl: public hello_pskel
+{
+public:
+ virtual void
+ greeting (const std::string&amp; g)
+ {
+ greeting_ = g;
+ }
+
+ virtual void
+ name (const std::string&amp; n)
+ {
+ std::cout &lt;&lt; greeting_ &lt;&lt; ", " &lt;&lt; n &lt;&lt; "!" &lt;&lt; std::endl;
+ }
+
+private:
+ std::string greeting_;
+};
+ </pre>
+
+ <p>We left both <code>pre()</code> and <code>post_hello()</code> 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.</p>
+
+ <p>An observant reader my ask what happens if the <code>name</code>
+ element comes before <code>greeting</code>? Don't we need to
+ make sure <code>greeting_</code> was initialized and report
+ an error otherwise? The answer is no, we don't have to do
+ any of this. The <code>hello_pskel</code> 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 <code>greeting</code> and <code>name</code> elements
+ and report an error if it is violated.</p>
+
+ <p>Now it is time to put this parser implementation to work:</p>
+
+ <pre class="c++">
+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&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The first part of this code snippet instantiates individual parsers
+ and assembles them into a complete vocabulary parser.
+ <code>xml_schema::string_pimpl</code> is an implementation of a parser
+ for built-in XML Schema type <code>string</code>. 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 <a href="#6">Chapter 6,
+ "Built-In XML Schema Type Parsers"</a>). We use <code>string_pimpl</code>
+ to parse the <code>greeting</code> and <code>name</code> elements as
+ indicated by the calls to <code>greeting_parser()</code> and
+ <code>name_parser()</code>.
+ </p>
+
+ <p>Then we instantiate a document parser (<code>doc_p</code>). The
+ first argument to its constructor is the parser for
+ the root element (<code>hello_p</code> in our case). The
+ second argument is the root element name.
+ </p>
+
+ <p>The final piece is the calls to <code>pre()</code>, <code>parse()</code>,
+ and <code>post_hello()</code>. The call to <code>parse()</code>
+ perform the actual XML parsing while the calls to <code>pre()</code> and
+ <code>post_hello()</code> make sure that the parser for the root
+ element can perform proper initialization and cleanup.</p>
+
+ <p>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 <code>--generate-noop-impl</code>
+ option. Or you can generate a sample implementation that prints the
+ data store in XML by using the <code>--generate-print-impl</code>
+ option. To request the generation of a test driver you can use the
+ <code>--generate-test-driver</code> option. For more information
+ on these options refer to the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>. The <code>'generated'</code> example
+ in the XSD/e distribution shows the sample implementation generation
+ feature in action.</p>
+
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving all the parts from the previous section in
+ <code>driver.cxx</code>, 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:
+ </p>
+
+ <pre class="terminal">
+$ 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!
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.
+ We can also test the error handling. To test XML well-formedness
+ checking, we can try to parse <code>hello-pskel.hxx</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello-pskel.hxx
+hello-pskel.hxx:1:0: not well-formed (invalid token)
+ </pre>
+
+ <p>We can also try to parse a valid XML but not from our
+ vocabulary, for example <code>hello.xsd</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+ </pre>
+
+
+ <!-- Chapater 3 -->
+
+
+ <h1><a name="3">3 Parser Skeletons</a></h1>
+
+ <p>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.</p>
+
+ <p>In this and subsequent chapters we will use the following schema
+ that describes a collection of person records. We save it in
+ <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema is saved
+ in <code>people.xml</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three parser skeletons being generated: <code>gender_pskel</code>,
+ <code>person_pskel</code>, and <code>people_pskel</code>. We are going
+ to examine and implement each of them in the subsequent sections.</p>
+
+ <h2><a name="3.1">3.1 Implementing the Gender Parser</a></h2>
+
+ <p>The generated <code>gender_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+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 ();
+};
+ </pre>
+
+ <p>Notice that <code>gender_pskel</code> inherits from
+ <code>xml_schema::string_pskel</code> which is a parser skeleton
+ for built-in XML Schema type <code>string</code> 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 <code>gender_pskel</code> class also
+ declares a constructor which expects a pointer to the base
+ parser skeleton. We will discuss the purpose of this
+ constructor shortly.</p>
+
+ <p>The <code>pre()</code> and <code>post_gender()</code> callbacks
+ should look familiar from the previous chapter. Let's now
+ implement the parser. Our implementation will simply print
+ the gender to <code>cout</code>:</p>
+
+
+ <pre class="c++">
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ post_gender ()
+ {
+ std::string s = post_string ();
+ cout &lt;&lt; "gender: " &lt;&lt; s &lt;&lt; endl;
+ }
+
+private:
+ xml_schema::string_pimpl base_impl_;
+};
+ </pre>
+
+ <p>While the code is quite short, there is a lot going on. First,
+ notice that we define a member variable <code>base_impl_</code>
+ of type <code>xml_schema::string_pimpl</code> and then pass
+ it to the <code>gender_pskel</code>'s constructor. We have
+ encountered <code>xml_schema::string_pimpl</code> already; it is an
+ implementation of the <code>xml_schema::string_pskel</code> parser
+ skeleton for built-in XML Schema type <code>string</code>. By
+ passing <code>base_impl_</code> to the <code>gender_pskel</code>'s
+ constructor we provide an implementation for the part of the
+ parser skeleton that is inherited from <code>string_pskel</code>.</p>
+
+ <p>This is another common theme in the C++/Parser programming model:
+ reusing implementations of the base parsers in the derived ones.
+ In our case, <code>string_pimpl</code> will do all the dirty work
+ of extracting the data and we can just get it at the end with the
+ call to <code>post_string()</code>. For more information on parser
+ implementation reuse refer to <a href="#5.6">Section 5.6,
+ "Parser Reuse"</a>.</p>
+
+ <p>In case you are curious, here are the definitions for
+ <code>xml_schema::string_pskel</code> and
+ <code>xml_schema::string_pimpl</code>:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ virtual std::string
+ post_string ();
+
+ protected:
+ std::string str_;
+ };
+}
+ </pre>
+
+ <p>There are three new pieces in this code that we haven't seen yet.
+ Those are the <code>parser_simple_content</code> class and
+ the <code>_pre()</code> and <code>_characters()</code> functions.
+ The <code>parser_simple_content</code> 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&mdash;only text
+ and attributes. There is also the <code>parser_complex_content</code>
+ class which corresponds to the complex content mode (types with
+ nested elements, for example, <code>person</code> from
+ <code>people.xsd</code>).</p>
+
+ <p>The <code>_pre()</code> function is a parser callback. Remember we
+ talked about the <code>pre()</code> and <code>post_*()</code> callbacks
+ in the previous chapter? There are actually two more callbacks
+ with similar roles: <code>_pre()</code> and <code>_post ()</code>.
+ As a result, each parser skeleton has four special callbacks:</p>
+
+ <pre class="c++">
+ virtual void
+ pre ();
+
+ virtual void
+ _pre ();
+
+ virtual void
+ _post ();
+
+ virtual void
+ post_name ();
+ </pre>
+
+ <p><code>pre()</code> and <code>_pre()</code> are initialization
+ callbacks. They get called in that order before a new instance of the type
+ is about to be parsed. The difference between <code>pre()</code> and
+ <code>_pre()</code> is conventional: <code>pre()</code> can
+ be completely overridden by a derived parser. The derived
+ parser can also override <code>_pre()</code> but has to always call
+ the original version. This allows you to partition initialization
+ into customizable and required parts.</p>
+
+ <p>Similarly, <code>_post()</code> and <code>post_name()</code> are
+ finalization callbacks with exactly the same semantics:
+ <code>post_name()</code> can be completely overridden by the derived
+ parser while the original <code>_post()</code> should always be called.
+ </p>
+
+ <p>The final bit we need to discuss in this section is the
+ <code>_characters()</code> 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.</p>
+
+ <p>At this point you might be wondering why some <code>post_*()</code>
+ callbacks, for example <code>post_string()</code>, return some data
+ while others, for example <code>post_gender()</code>, have
+ <code>void</code> as a return type. This is a valid concern
+ and it will be addressed in the next chapter.</p>
+
+ <h2><a name="3.2">3.2 Implementing the Person Parser</a></h2>
+
+ <p>The generated <code>person_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ virtual void
+ last_name (const std::string&amp;);
+
+ virtual void
+ gender ();
+
+ virtual void
+ age (short);
+
+ virtual void
+ post_person ();
+
+ // Parser construction API.
+ //
+ void
+ first_name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ last_name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ gender_parser (gender_pskel&amp;);
+
+ void
+ age_parser (xml_schema::short_pskel&amp;);
+
+ void
+ parsers (xml_schema::string_pskel&amp; /* first-name */,
+ xml_schema::string_pskel&amp; /* last-name */,
+ gender_pskel&amp; /* gender */,
+ xml_schema::short_pskel&amp; /* age */);
+};
+ </pre>
+
+
+ <p>As you can see, we have a parser callback for each of the nested
+ elements found in the <code>person</code> XML Schema type.
+ The implementation of this parser is straightforward:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ first_name (const std::string&amp; n)
+ {
+ cout &lt;&lt; "first: " &lt;&lt; f &lt;&lt; endl;
+ }
+
+ virtual void
+ last_name (const std::string&amp; l)
+ {
+ cout &lt;&lt; "last: " &lt;&lt; l &lt;&lt; endl;
+ }
+
+ virtual void
+ age (short a)
+ {
+ cout &lt;&lt; "age: " &lt;&lt; a &lt;&lt; endl;
+ }
+};
+ </pre>
+
+ <p>Notice that we didn't override the <code>gender()</code> callback
+ because all the printing is done by <code>gender_pimpl</code>.</p>
+
+ <h2><a name="3.3">3.3 Implementing the People Parser</a></h2>
+
+ <p>The generated <code>people_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ void
+ parsers (person_pskel&amp; /* person */);
+};
+ </pre>
+
+ <p>The <code>person()</code> callback will be called after parsing each
+ <code>person</code> element. While <code>person_pimpl</code> 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:</p>
+
+ <pre class="c++">
+class people_pimpl: public people_pskel
+{
+public:
+ virtual void
+ person ()
+ {
+ cout &lt;&lt; endl;
+ }
+};
+ </pre>
+
+ <p>Now it is time to put everything together.</p>
+
+
+ <h2><a name="3.4">3.4 Connecting the Parsers Together</a></h2>
+
+ <p>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:</p>
+
+ <pre class="c++">
+xml_schema::short_pimpl short_p;
+xml_schema::string_pimpl string_p;
+
+gender_pimpl gender_p;
+person_pimpl person_p;
+people_pimpl people_p;
+ </pre>
+
+ <p>Notice that our schema uses two built-in XML Schema types:
+ <code>string</code> for the <code>first-name</code> and
+ <code>last-name</code> elements as well as <code>short</code>
+ for <code>age</code>. 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 <code>*_parser()</code> functions:</p>
+
+ <pre class="c++">
+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);
+ </pre>
+
+ <p>You might be wondering what happens if you do not provide
+ a parser by not calling one of the <code>*_parser()</code> 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.</p>
+
+
+ <p>An alternative, shorter, way to connect the parsers is by using
+ the <code>parsers()</code> functions which connects all the parsers
+ for a given type at once:</p>
+
+ <pre class="c++">
+person_p.parsers (string_p, string_p, gender_p, short_p);
+people_p.parsers (person_p);
+ </pre>
+
+ <p>The following figure illustrates the resulting connections. Notice
+ the correspondence between return types of the <code>post_*()</code>
+ functions and argument types of element callbacks that are connected
+ by the arrows.</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>The last step is the construction of the document parser and
+ invocation of the complete parser on our sample XML instance:</p>
+
+ <pre class="c++">
+xml_schema::document_pimpl doc_p (people_p, "people");
+
+people_p.pre ();
+doc_p.parse ("people.xml");
+people_p.post_people ();
+ </pre>
+
+ <p>Let's consider <code>xml_schema::document_pimpl</code> in
+ more detail. While the exact definition of this class
+ varies depending on the mapping configuration, here is
+ the part relevant to our example:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class document_pimpl
+ {
+ public:
+ document_pimpl (xml_schema::parser_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_pimpl (xml_schema::parser_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+ void
+ parse (const std::string&amp; file);
+
+ void
+ parse (std::istream&amp;);
+
+ void
+ parse (const void* data, size_t size, bool last);
+ };
+}
+ </pre>
+
+ <p><code>xml_schema::document_pimpl</code> is a root parser for
+ the vocabulary. The first argument to its constructors is the
+ parser for the type of the root element (<code>people_pimpl</code>
+ 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
+ <code>document_pimpl</code>'s constructors.</p>
+
+ <p>There are also three overloaded <code>parse()</code> function
+ defined in the <code>document_pimpl</code> 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 <code>last</code> argument set to true. For more
+ information on the <code>xml_schema::document_pimpl</code> class
+ refer to <a href="#7">Chapter 7, "Document Parser and Error
+ Handling"</a>.</p>
+
+ <p>Let's now consider a step-by-step list of actions that happen
+ as we parse through <code>people.xml</code>. The content of
+ <code>people.xml</code> is repeated below for convenience.</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <ol class="steps">
+ <li><code>people_p.pre()</code> is called from
+ <code>main()</code>. We did not provide any implementation
+ for this callback so this call is a no-op.</li>
+
+ <li><code>doc_p.parse("people.xml")</code> is called from
+ <code>main()</code>. The parser opens the file and starts
+ parsing its content.</li>
+
+ <li>The parser encounters the root element. <code>doc_p</code>
+ verifies that the root element is correct and calls
+ <code>_pre()</code> on <code>people_p</code> which is also
+ a no-op. Parsing is now delegated to <code>people_p</code>.</li>
+
+ <li>The parser encounters the <code>person</code> element.
+ <code>people_p</code> determines that <code>person_p</code>
+ is responsible for parsing this element. <code>pre()</code>
+ and <code>_pre()</code> callbacks are called on <code>person_p</code>.
+ Parsing is now delegated to <code>person_p</code>.</li>
+
+ <li>The parser encounters the <code>first-name</code> element.
+ <code>person_p</code> determines that <code>string_p</code>
+ is responsible for parsing this element. <code>pre()</code>
+ and <code>_pre()</code> callbacks are called on <code>string_p</code>.
+ Parsing is now delegated to <code>string_p</code>.</li>
+
+ <li>The parser encounters character content consisting of
+ <code>"John"</code>. The <code>_characters()</code> callback is
+ called on <code>string_p</code>.</li>
+
+ <li>The parser encounters the end of <code>first-name</code>
+ element. The <code>_post()</code> and <code>post_string()</code>
+ callbacks are called on <code>string_p</code>. The
+ <code>first_name()</code> callback is called on <code>person_p</code>
+ with the return value of <code>post_string()</code>. The
+ <code>first_name()</code> implementation prints
+ <code>"first: John"</code> to <code>cout</code>.
+ Parsing is now returned to <code>person_p</code>.</li>
+
+ <li>Steps analogous to 5-7 are performed for the <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements.</li>
+
+ <li>The parser encounters the end of <code>person</code>
+ element. The <code>_post()</code> and <code>post_person()</code>
+ callbacks are called on <code>person_p</code>. The
+ <code>person()</code> callback is called on <code>people_p</code>.
+ The <code>person()</code> implementation prints a new line
+ to <code>cout</code>. Parsing is now returned to
+ <code>people_p</code>.</li>
+
+ <li>Steps 4-9 are performed for the second <code>person</code>
+ element.</li>
+
+ <li>The parser encounters the end of <code>people</code>
+ element. The <code>_post()</code> callback is called on
+ <code>people_p</code>. The <code>doc_p.parse("people.xml")</code>
+ call returns to <code>main()</code>.</li>
+
+ <li><code>people_p.post_people()</code> is called from
+ <code>main()</code> which is a no-op.</li>
+
+ </ol>
+
+
+ <!-- Chpater 4 -->
+
+
+ <h1><a name="4">4 Type Maps</a></h1>
+
+ <p>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 <em>parent</em> parser
+ which can then incorporate this sub-tree into the whole tree.</p>
+
+ <p>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.</p>
+
+ <h2><a name="4.1">4.1 Object Model</a></h2>
+
+ <p>An object model for our person record example could
+ look like this (saved in the <code>people.hxx</code> file):</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum gender
+{
+ male,
+ female
+};
+
+class person
+{
+public:
+ person (const std::string&amp; first,
+ const std::string&amp; last,
+ ::gender gender,
+ short age)
+ : first_ (first), last_ (last),
+ gender_ (gender), age_ (age)
+ {
+ }
+
+ const std::string&amp;
+ first () const
+ {
+ return first_;
+ }
+
+ const std::string&amp;
+ 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&lt;person> people;
+ </pre>
+
+ <p>While it is clear which parser is responsible for which part of
+ the object model, it is not exactly clear how, for
+ example, <code>gender_pimpl</code> will deliver <code>gender</code>
+ to <code>person_pimpl</code>. You might have noticed that
+ <code>string_pimpl</code> manages to deliver its value to the
+ <code>first_name()</code> callback of <code>person_pimpl</code>. Let's
+ see how we can utilize the same mechanism to propagate our
+ own data.</p>
+
+ <p>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 <code>post_*()</code> 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
+ <code>gender</code> we can specify the return type for
+ <code>post_gender()</code> in the <code>gender_pskel</code>
+ skeleton and the argument type for the <code>gender()</code> callback
+ in the <code>person_pskel</code> skeleton. As you might have guessed,
+ the generated code will then pass the return value from the
+ <code>post_*()</code> callback as an argument to the element or
+ attribute callback.</p>
+
+ <p>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 <code>gender</code> type from the previous paragraph.</p>
+
+ <pre class="type-map">
+include "people.hxx";
+gender ::gender ::gender;
+ </pre>
+
+ <p>The first line indicates that the generated code must include
+ <code>people.hxx</code> in order to get the definition for the
+ <code>gender</code> type. The second line specifies that both
+ argument and return types for the <code>gender</code>
+ XML Schema type should be the <code>::gender</code> 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 <code>people.map</code> and
+ then translate our schemas with the <code>--type-map</code>
+ option to let the XSD/e compiler know about our type map:</p>
+
+ <pre class="terminal">
+$ xsde cxx-parser --type-map people.map people.xsd
+ </pre>
+
+ <p>If we now look at the generated <code>people-pskel.hxx</code>,
+ we will see the following changes in the <code>gender_pskel</code> and
+ <code>person_pskel</code> skeletons:</p>
+
+ <pre class="c++">
+#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);
+
+ ...
+};
+ </pre>
+
+ <p>Notice that <code>#include "people.hxx"</code> was added to
+ the generated header file from the type map to provide the
+ definition for the <code>gender</code> enum.</p>
+
+ <h2><a name="4.2">4.2 Type Map File Format</a></h2>
+
+ <p>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 <code>post_*()</code>
+ callbacks in parser skeletons corresponding to XML Schema
+ types as well as argument types for callbacks corresponding
+ to elements and attributes of these types.</p>
+
+ <p>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 <code>void</code>.
+ By providing your own type maps you can override these predefined
+ rules. The format of the type map file is presented below:
+ </p>
+
+ <pre class="type-map">
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code>"&nbsp;"</code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the <code>post_*()</code> callback.
+ Optional <code><i>&lt;cxx-arg-type></i></code> is an argument
+ type for callbacks corresponding to elements and attributes
+ of this type. If <code><i>&lt;cxx-arg-type></i></code> is not
+ specified, it defaults to <code><i>&lt;cxx-ret-type></i></code>
+ if <code><i>&lt;cxx-ret-type></i></code> ends with <code>*</code> or
+ <code>&amp;</code> (that is, it is a pointer or a reference) and
+ <code>const&nbsp;<i>&lt;cxx-ret-type></i>&amp;</code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code>"&nbsp;"</code> or <code>&lt;&nbsp;></code> format
+ and is added with the <code>#include</code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code>http://www.example.com/xmlns/my#orange</code>
+ XML Schema type, the <code>my::orange_t*</code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>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:</p>
+
+ <pre class="type-map">
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="type-map">
+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;
+}
+ </pre>
+
+ <p>If STL is enabled (<a href="#5.1">Section 5.1, "Standard Template
+ Library"</a>), the following mapping is used for the string-based
+ XML Schema built-in types:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;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;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre class="type-map">
+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*;
+}
+ </pre>
+
+ <p>For more information about the mapping of the built-in XML Schema types
+ to C++ types refer to <a href="#6">Chapter 6, "Built-In XML Schema Type
+ Parsers"</a>. The last predefined rule maps anything that wasn't
+ mapped by previous rules to <code>void</code>:</p>
+
+ <pre class="type-map">
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+
+ <p>When you provide your own type maps with the
+ <code>--type-map</code> 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 <code>xml_schema</code> namespace. You can include the
+ custom definitions into the generated header file using the
+ <code>--hxx-prologue-*</code> options.</p>
+
+ <h2><a name="4.3">4.3 Parser Implementations</a></h2>
+
+ <p>With the knowledge from the previous section, we can proceed
+ with creating a type map that maps types in the <code>people.xsd</code>
+ schema to our object model classes in
+ <code>people.hxx</code>. In fact, we already have the beginning
+ of our type map file in <code>people.map</code>. Let's extend
+ it with the rest of the types:</p>
+
+ <pre class="type-map">
+include "people.hxx";
+
+gender ::gender ::gender;
+person ::person;
+people ::people;
+ </pre>
+
+ <p>A few things to note about this type map. We did not
+ provide the argument types for <code>person</code> and
+ <code>people</code> because the default constant reference is
+ exactly what we need. We also did not provide any mappings
+ for built-in XML Schema types <code>string</code> and
+ <code>short</code> 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:</p>
+
+ <pre class="terminal">
+$ xsde cxx-parser --type-map people.map people.xsd
+ </pre>
+
+ <p>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.</p>
+
+ <pre class="c++">
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;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&amp; f)
+ {
+ first_ = f;
+ }
+
+ virtual void
+ last_name (const std::string&amp; 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&amp; p)
+ {
+ people_.push_back (p);
+ }
+
+ virtual ::people
+ post_people ()
+ {
+ ::people r;
+ r.swap (people_);
+ return r;
+ }
+
+private:
+ ::people people_;
+};
+ </pre>
+
+ <p>This code fragment should look familiar by now. Just note that
+ all the <code>post_*()</code> callbacks now have return types instead
+ of <code>void</code>. Here is the implementation of the test
+ driver for this example:</p>
+
+ <pre class="c++">
+#include &lt;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 &lt;&lt; "first: " &lt;&lt; i->first () &lt;&lt; endl
+ &lt;&lt; "last: " &lt;&lt; i->last () &lt;&lt; endl
+ &lt;&lt; "gender: " &lt;&lt; (i->gender () == male ? "male" : "female") &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; i->age () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+}
+ </pre>
+
+ <p>The parser creation and assembly part is exactly the same as in
+ the previous chapter. The parsing part is a bit different:
+ <code>post_people()</code> now has a return value which is the
+ complete object model. We store it in the
+ <code>ppl</code> variable. The last bit of the code simply iterates
+ over the <code>people</code> vector and prints the information
+ for each person. We save the last two code fragments to
+ <code>driver.cxx</code> and proceed to compile and test
+ our new application:</p>
+
+
+ <pre class="terminal">
+$ 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
+ </pre>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="5">5 Mapping Configuration</a></h1>
+
+ <p>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.</p>
+
+ <p>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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>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.</p>
+
+ <h2><a name="5.1">5.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> 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 <code>char*</code> instead
+ of <code>std::string</code>, as described in
+ <a href="#4.2">Section 4.2, "Type Map File Format"</a>. The
+ following code fragment shows changes in the
+ signatures of <code>first_name()</code> and <code>last_name()</code>
+ callbacks from the person record example.</p>
+
+ <pre class="c++">
+class person_pskel
+{
+public:
+ virtual void
+ first_name (char*);
+
+ virtual void
+ last_name (char*);
+
+ ...
+};
+ </pre>
+
+ <p>Note that it is your responsibility to eventually release the memory
+ associated with these strings using operator <code>delete[]</code>.
+ </p>
+
+ <h2><a name="5.2">5.2 Input/Output Stream Library</a></h2>
+
+ <p>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 <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, the
+ following two <code>parse()</code> functions in the
+ <code>xml_schema::document_pimpl</code> class become unavailable:</p>
+
+ <pre class="c++">
+ void
+ parse (const std::string&amp; file);
+
+ void
+ parse (std::istream&amp;);
+ </pre>
+
+ <p>Leaving you with only one function in the form:</p>
+
+ <pre class="c++">
+ void
+ parse (const void* data, size_t size, bool last);
+ </pre>
+
+ <p>See <a href="#7.1">Section 7.1, "Document Parser"</a>
+ for more information on the semantics of these functions.</p>
+
+ <h2><a name="5.3">5.3 C++ Exceptions</a></h2>
+
+ <p>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 <code>--no-exceptions</code> 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 <a href="#7.3">Section 7.3,
+ "Error Codes"</a>.
+ </p>
+
+ <h2><a name="5.4">5.4 XML Schema Validation</a></h2>
+
+ <p>To disable support for XML Schema validation, you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--suppress-validation</code> 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.
+ </p>
+
+ <h2><a name="5.5">5.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ XML Schema built-in types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> 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 <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="5.6">5.6 Parser Reuse</a></h2>
+
+ <p>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 <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.</p>
+
+ <p>The compiler can also be instructed not to generate any support
+ for parser reuse with the <code>--reuse-style-none</code> 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.</p>
+
+
+ <p>To provide concrete examples for each reuse style we will use the
+ following schema fragment:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+
+&lt;xs:complexType name="emplyee">
+ &lt;complexContent>
+ &lt;extension base="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="position" type="xs:string"/>
+ &lt;xs:element name="salary" type="xs:unsignedLong"/>
+ &lt;/xs:sequence>
+ &lt;/extension>
+ &lt;/complexContent>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="c++">
+class person_pskel: public virtual parser_complex_content
+{
+ ...
+};
+
+class employee_pskel: public virtual person_pskel
+{
+ ...
+};
+ </pre>
+
+
+ <p>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, <em>mixing in</em>
+ the base parser implementation), for example:</p>
+
+ <pre class="c++">
+class person_pimpl: public virtual person_pskel
+{
+ ...
+};
+
+class employee_pimpl: public employee_pskel,
+ public person_pimpl
+{
+ ...
+};
+ </pre>
+
+
+ <p>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:</p>
+
+ <pre class="c++">
+class person_pskel: public parser_complex_content
+{
+ ...
+};
+
+class employee_pskel: public person_pskel
+{
+public:
+ employee_pskel (person_pskel* base_impl)
+
+ ...
+};
+ </pre>
+
+ <p>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
+ <code>0</code> 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
+ <code>person</code> and <code>employee</code> parsers
+ using the tiein style:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+ ...
+};
+
+class employee_pimpl: public employee_pskel
+{
+public:
+ employee_pimpl ()
+ : employee_pskel (&amp;base_impl_)
+ {
+ }
+
+ ...
+
+private:
+ person_pimpl base_impl_;
+};
+ </pre>
+
+ <p>Note that you cannot use the <em>tied in</em> base parser
+ instance (<code>base_impl_</code> in the above code) for
+ parsing anything except the derived type.</p>
+
+ <p>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 <code>age()</code> callback if we didn't
+ like the implementation provided by the base parser:</p>
+
+ <pre class="c++">
+class employee_pimpl: public employee_pskel
+{
+public:
+ employee_pimpl ()
+ : employee_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ age (short a)
+ {
+ ...
+ }
+
+ ...
+
+private:
+ person_pimpl base_impl_;
+};
+ </pre>
+
+ <p>In the above example the <code>age</code> element will be
+ handled by <code>emplyee_pimpl</code> while the <code>first-name</code>
+ and <code>last-name</code> callbacks will still go to
+ <code>base_impl_</code>.</p>
+
+ <p>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:</p>
+
+
+ <pre class="c++">
+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&lt;person_pimpl*> (this))
+ {
+ }
+
+ // Resolve ambiguities.
+ //
+ using emplyee_pskel::parsers;
+
+ ...
+
+protected:
+ virtual employee*
+ create ()
+ {
+ return new employee ();
+ }
+};
+ </pre>
+
+
+ <h2><a name="5.7">5.7 Support for Polymorphism</a></h2>
+
+ <p>By default the XSD/e compiler generates non-polymorphic code. If your
+ vocabulary uses XML Schema polymorphism in the form of <code>xsi:type</code>
+ and/or substitution groups, then you will need to configure the XSD/e
+ runtime with support for polymorphism, compile your schemas with the
+ <code>--generate-polymorphic</code> option to produce polymorphism-aware
+ code, as well as pass <code>true</code> as the last argument to the
+ <code>xml_schema::document</code>'s constructors. If some of your
+ schemas do not require support for polymorphism then you can compile
+ them with the <code>--runtime-polymorphic</code> option and still
+ use the XSD/e runtime configured with polymorphism support.
+ </p>
+
+ <p>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 <code>xsi:type</code> attribute value or an element
+ name from a substitution group. Consider the following schema as an
+ example:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="person" type="person"/>
+
+ &lt;xs:complexType name="superman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="person">
+ &lt;xs:attribute name="can-fly" type="xs:boolean"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="superman"
+ type="superman"
+ substitutionGroup="person"/>
+
+ &lt;xs:complexType name="batman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="superman">
+ &lt;xs:attribute name="wing-span" type="xs:unsignedInt"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="batman"
+ type="batman"
+ substitutionGroup="superman"/>
+
+ &lt;xs:complexType name="supermen">
+ &lt;xs:sequence>
+ &lt;xs:element ref="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="supermen" type="supermen"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Conforming XML documents can use the <code>superman</code>
+ and <code>batman</code> types in place of the <code>person</code>
+ type either by specifying the type with the <code>xsi:type</code>
+ attributes or by using the elements from the substitution
+ group, for instance:</p>
+
+
+ <pre class="xml">
+&lt;supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ &lt;person>
+ &lt;name>John Doe&lt;/name>
+ &lt;/person>
+
+ &lt;superman can-fly="false">
+ &lt;name>James "007" Bond&lt;/name>
+ &lt;/superman>
+
+ &lt;superman can-fly="true" wing-span="10" xsi:type="batman">
+ &lt;name>Bruce Wayne&lt;/name>
+ &lt;/superman>
+
+&lt;/supermen>
+ </pre>
+
+ <p>To print the data stored in such XML documents we can implement
+ the parsers as follows:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse person" &lt;&lt; endl;
+ }
+
+ virtual void
+ name (const std::string&amp; v)
+ {
+ cout &lt;&lt; "name: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ cout &lt;&lt; "finished parsing person" &lt;&lt; endl;
+ }
+};
+
+class superman_pimpl: public superman_pskel
+{
+public:
+ superman_pimpl ()
+ : superman_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse superman" &lt;&lt; endl;
+ }
+
+ virtual void
+ can_fly (bool v)
+ {
+ cout &lt;&lt; "can-fly: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ post_superman ();
+ }
+
+ virtual void
+ post_superman ()
+ {
+ cout &lt;&lt; "finished parsing superman" &lt;&lt; endl
+ }
+
+private:
+ person_pimpl base_impl_;
+};
+
+class batman_pimpl: public batman_pskel
+{
+public:
+ batman_pimpl ()
+ : batman_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse batman" &lt;&lt; endl;
+ }
+
+ virtual void
+ wing_span (unsigned int v)
+ {
+ cout &lt;&lt; "wing-span: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ post_superman ();
+ }
+
+ virtual void
+ post_superman ()
+ {
+ post_batman ();
+ }
+
+ virtual void
+ post_batman ()
+ {
+ cout &lt;&lt; "finished parsing batman" &lt;&lt; endl;
+ }
+
+private:
+ superman_pimpl base_impl_;
+};
+ </pre>
+
+ <p>Note that because the derived type parsers (<code>superman_pskel</code>
+ and <code>batman_pskel</code>) are called via the <code>person_pskel</code>
+ interface, we have to override the <code>post_person()</code> virtual
+ function in <code>superman_pimpl</code> and <code>batman_pimpl</code>
+ to call <code>post_superman()</code> and the <code>post_superman()</code>
+ virtual function in <code>batman_pimpl</code> to call
+ <code>post_batman()</code> (when the mixin parser reuse style is used
+ it is not necessary to override <code>post_person()</code>
+ in <code>batman_pimpl</code> since the suitable implementation
+ is inherited from <code>superman_pimpl</code>).</p>
+
+ <p>The following code fragment shows how to connect the parsers together.
+ Notice that for the <code>person</code> element in the <code>supermen_p</code>
+ parser we specify a parser map instead of a specific parser and we pass
+ <code>true</code> as the last argument to the document parser constructor
+ to indicate that we are parsing potentially-polymorphic XML documents:</p>
+
+ <pre class="c++">
+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 ();
+}
+ </pre>
+
+ <p>When polymorphism-aware code is generated, each element's
+ <code>*_parser()</code> function is overloaded to also accept
+ an object of the <code>xml_schema::parser_map</code> type.
+ For example, the <code>supermen_pskel</code> class from the
+ above example looks like this:</p>
+
+ <pre class="c++">
+class supermen_pskel: public xml_schema::parser_complex_content
+{
+public:
+
+ ...
+
+ // Parser construction API.
+ //
+ void
+ parsers (person_pskel&amp;);
+
+ // Individual element parsers.
+ //
+ void
+ person_parser (person_pskel&amp;);
+
+ void
+ person_parser (xml_schema::parser_map&amp;);
+
+ ...
+};
+ </pre>
+
+ <p>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
+ <code>xsi:type</code> 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:</p>
+
+ <pre class="c++">
+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);
+
+ ...
+}
+ </pre>
+
+
+ <p>The <code>xml_schema::parser_map</code> interface and the
+ <code>xml_schema::parser_map_impl</code> default implementation
+ are presented below:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ virtual parser_base*
+ find (const char* type) const;
+
+ virtual void
+ reset () const;
+
+ private:
+ parser_map_impl (const parser_map_impl&amp;);
+
+ parser_map_impl&amp;
+ operator= (const parser_map_impl&amp;);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>type</code> argument in the <code>find()</code> 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
+ <code>"&lt;name>&nbsp;&lt;namespace>"</code> 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 <code>_dynamic_type()</code> function. The static
+ type can be obtained by calling the static <code>_static_type()</code>
+ function, for example <code>person_pskel::_static_type()</code>.
+ Both functions return a C string (<code>const char*</code>) which
+ is valid for as long as the application is running. The
+ <code>reset()</code> 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 <a href="#7.4">Section 7.4, "Reusing Parsers
+ after an Error"</a>. The following example shows how we can
+ implement our own parser map using <code>std::map</code>:</p>
+
+
+ <pre class="c++">
+#include &lt;map>
+#include &lt;string>
+
+class parser_map: public xml_schema::parser_map
+{
+public:
+ void
+ insert (xml_schema::parser_base&amp; p)
+ {
+ map_[p._dynamic_type ()] = &amp;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&lt;std::string, xml_schema::parser_base*> map;
+ map map_;
+};
+ </pre>
+
+ <p>The XSD/e runtime provided the default implementation for the
+ <code>xml_schema::parser_map</code> interface,
+ <code>xml_schema::parser_map_impl</code>, 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.
+ </p>
+
+ <p>If C++ exceptions are disabled (<a href="#5.3">Section 5.3,
+ "C++ Exceptions"</a>), the <code>xml_schema::parser_map_impl</code>
+ class has the following additional error querying API. It can be used
+ to detect the out of memory errors after calls to the
+ <code>parser_map_impl</code>'s constructor and <code>insert()</code>
+ function.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_map_impl: public parser_map
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ error
+ _error () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>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 (<a href="#5.4">Section 5.4,
+ "XML Schema Validation"</a>), 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:</p>
+
+ <pre class="c++">
+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 &lt;&lt; "substitution hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_PARSER_SMAP_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::parser_imap_elements ();
+ load /= xml_schema::parser_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "inheritance hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_PARSER_IMAP_BUCKETS" &lt;&lt; endl;
+ }
+#endif
+
+ ...
+}
+ </pre>
+
+ <p>Most of the code presented in this section is taken from the
+ <code>polymorphism</code> example which can be found in the
+ <code>examples/cxx/parser/</code> directory of the XSD/e distribution.
+ Handling of <code>xsi:type</code> and substitution groups when used
+ on root elements requires a number of special actions as shown in
+ the <code>polyroot</code> example.</p>
+
+ <h2><a name="5.8">5.8 A Minimal Example</a></h2>
+
+ <p>The following example is a re-implementation of the person
+ records example presented in <a href="#3">Chapter 3,
+ "Parser Skeletons"</a>. It is intended to work
+ without STL, iostream, and C++ exceptions. It can be found in
+ the <code>examples/cxx/parser/minimal/</code> directory of the
+ XSD/e distribution. The <code>people.xsd</code> schema is
+ compiled with the <code>--no-stl</code>, <code>--no-iostream</code>,
+ and <code>--no-exceptions</code> options. The following listing
+ presents the implementation of parser skeletons and the test
+ driver in full.</p>
+
+ <pre class="c++">
+#include &lt;stdio.h>
+
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;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) &amp;&amp; ferror (f))
+ {
+ io_error = true;
+ break;
+ }
+
+ doc_p.parse (buf, s, feof (f) != 0);
+ e = doc_p._error ();
+
+ } while (!e &amp;&amp; !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;
+}
+ </pre>
+
+
+ <!-- Built-in XML Schema Type Parsers -->
+
+
+ <h1><a name="6">6 Built-In XML Schema Type Parsers</a></h1>
+
+ <p>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.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Parser implementation in the <code>xml_schema</code> namespace</th>
+ <th>Parser return type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">anyType and anySimpleType types</th>
+ </tr>
+ <tr>
+ <td><code>anyType</code></td>
+ <td><code>any_type_pimpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+ <tr>
+ <td><code>anySimpleType</code></td>
+ <td><code>any_simple_type_pimpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte_pimpl</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte_pimpl</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_pimpl</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short_pimpl</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_pimpl</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int_pimpl</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_pimpl</code></td>
+ <td><code>long&nbsp;long</code> or <code>long</code><br/>
+ <a href="#5.5">Section 5.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long_pimpl</code></td>
+ <td><code>unsigned&nbsp;long&nbsp;long</code> or
+ <code>unsigned&nbsp;long</code><br/>
+ <a href="#5.5">Section 5.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer_pimpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer_pimpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean_pimpl</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_pimpl</code></td>
+ <td><code>float</code></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_pimpl</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal_pimpl</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string-based types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname_pimpl</code></td>
+ <td><code>xml_schema::qname</code> or <code>xml_schema::qname*</code><br/>
+ <a href="#6.1">Section 6.1, "<code>QName</code> Parser"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">list types</th>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens_pimpl</code></td>
+ <td><code>xml_schema::string_sequence*</code><br/><a href="#6.2">Section
+ 6.2, "<code>NMTOKENS</code> and <code>IDREFS</code> Parsers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs_pimpl</code></td>
+ <td><code>xml_schema::string_sequence*</code><br/><a href="#6.2">Section
+ 6.2, "<code>NMTOKENS</code> and <code>IDREFS</code> Parsers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary_pimpl</code></td>
+ <td><code>xml_schema::buffer*</code><br/>
+ <a href="#6.3">Section 6.3, "<code>base64Binary</code> and
+ <code>hexBinary</code> Parsers"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary_pimpl</code></td>
+ <td><code>xml_schema::buffer*</code><br/>
+ <a href="#6.3">Section 6.3, "<code>base64Binary</code> and
+ <code>hexBinary</code> Parsers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date_pimpl</code></td>
+ <td><code>xml_schema::date</code><br/><a href="#6.5">Section 6.5,
+ "<code>date</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time_pimpl</code></td>
+ <td><code>xml_schema::date_time</code><br/><a href="#6.6">Section 6.6,
+ "<code>dateTime</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration_pimpl</code></td>
+ <td><code>xml_schema::duration</code><br/><a href="#6.7">Section 6.7,
+ "<code>duration</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday_pimpl</code></td>
+ <td><code>xml_schema::gday</code><br/><a href="#6.8">Section 6.8,
+ "<code>gDay</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth_pimpl</code></td>
+ <td><code>xml_schema::gmonth</code><br/><a href="#6.9">Section 6.9,
+ "<code>gMonth</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day_pimpl</code></td>
+ <td><code>xml_schema::gmonth_day</code><br/><a href="#6.10">Section 6.10,
+ "<code>gMonthDay</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear_pimpl</code></td>
+ <td><code>xml_schema::gyear</code><br/><a href="#6.11">Section 6.11,
+ "<code>gYear</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month_pimpl</code></td>
+ <td><code>xml_schema::gyear_month</code><br/><a href="#6.12">Section
+ 6.12, "<code>gYearMonth</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time_pimpl</code></td>
+ <td><code>xml_schema::time</code><br/><a href="#6.13">Section 6.13,
+ "<code>time</code> Parser"</a></td>
+ </tr>
+
+ </table>
+
+ <h2><a name="6.1">6.1 <code>QName</code> Parser</a></h2>
+
+ <p>The return type of the <code>qname_pimpl</code> parser implementation
+ is either <code>xml_schema::qname</code> when STL is enabled
+ (<a href="#5.1">Section 5.1, "Standard Template Library"</a>) or
+ <code>xml_schema::qname*</code> when STL is disabled. The
+ <code>qname</code> class represents an XML qualified name. When the
+ return type is <code>xml_schema::qname*</code>, the returned
+ object is dynamically allocated with operator <code>new</code>
+ and should eventually be deallocated with operator <code>delete</code>.
+ With STL enabled, the <code>qname</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#5.3">Section 5.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="6.2">6.2 <code>NMTOKENS</code> and <code>IDREFS</code> Parsers</a></h2>
+
+ <p>The return type of the <code>nmtokens_pimpl</code> and
+ <code>idrefs_pimpl</code> parser implementations is
+ <code>xml_schema::string_sequence*</code>.
+ The returned object is dynamically allocated with operator
+ <code>new</code> and should eventually be deallocated with
+ operator <code>delete</code>. With STL and C++ exceptions enabled
+ (<a href="#5.1">Section 5.1, "Standard Template Library"</a>,
+ <a href="#5.3">Section 5.3, "C++ Exceptions"</a>), the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp; reference;
+ typedef const std::string&amp; 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&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ std::string&amp;
+ front ();
+
+ const std::string&amp;
+ front () const;
+
+ std::string&amp;
+ back ();
+
+ const std::string&amp;
+ back () const;
+
+ std::string&amp;
+ operator[] (size_t);
+
+ const std::string&amp;
+ 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&amp;);
+
+ iterator
+ insert (iterator, const std::string&amp;);
+
+ void
+ reserve (size_t);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>When STL is enabled and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>insert()</code>, and
+ <code>reserve()</code> functions change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled, the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ 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&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new char[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. These two functions free the passed object if the reallocation
+ of the underlying sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ If you detach the underlying element string, then it should
+ eventually be deallocated with operator <code>delete[]</code>.</p>
+
+ <p>When both STL and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions change
+ as follows:</p>
+
+ <pre class="c++">
+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&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+
+ <h2><a name="6.3">6.3 <code>base64Binary</code> and <code>hexBinary</code> Parsers</a></h2>
+
+ <p>The return type of the <code>base64_binary_pimpl</code> and
+ <code>hex_binary_pimpl</code> parser implementations is
+ <code>xml_schema::buffer*</code>. The returned object is
+ dynamically allocated with operator <code>new</code> and
+ should eventually be deallocated with operator <code>delete</code>.
+ With C++ exceptions enabled (<a href="#5.3">Section 5.3, "C++
+ Exceptions"</a>), the <code>buffer</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ 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&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> type has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="6.4">6.4 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>xml_schema::time_zone</code> base class is used to represent
+ this information:</p>
+
+ <pre class="c++">
+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&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> modifier
+ function resets the time zone object to the <em>not specified</em>
+ state. If the time zone offset is negative then both hours and
+ minutes components are represented as negative integers.</p>
+
+ <h2><a name="6.5">6.5 <code>date</code> Parser</a></h2>
+
+ <p>The return type of the <code>date_pimpl</code> parser implementation
+ is <code>xml_schema::date</code> 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 <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="6.6">6.6 <code>dateTime</code> Parser</a></h2>
+
+ <p>The return type of the <code>date_time_pimpl</code> parser implementation
+ is <code>xml_schema::date_time</code> 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
+ <code>xml_schema::time_zone</code> class refer to <a href="#6.4">Section
+ 6.4, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="6.7">6.7 <code>duration</code> Parser</a></h2>
+
+ <p>The return type of the <code>duration_pimpl</code> parser implementation
+ is <code>xml_schema::duration</code> which represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+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&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="6.8">6.8 <code>gDay</code> Parser</a></h2>
+
+ <p>The return type of the <code>gday_pimpl</code> parser implementation
+ is <code>xml_schema::gday</code> which represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="6.9">6.9 <code>gMonth</code> Parser</a></h2>
+
+ <p>The return type of the <code>gmonth_pimpl</code> parser implementation
+ is <code>xml_schema::gmonth</code> which represents a month of the year
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="6.10">6.10 <code>gMonthDay</code> Parser</a></h2>
+
+ <p>The return type of the <code>gmonth_day_pimpl</code> parser implementation
+ is <code>xml_schema::gmonth_day</code> 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 <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="6.11">6.11 <code>gYear</code> Parser</a></h2>
+
+ <p>The return type of the <code>gyear_pimpl</code> parser implementation
+ is <code>xml_schema::gyear</code> which represents a year with
+ an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="6.12">6.12 <code>gYearMonth</code> Parser</a></h2>
+
+ <p>The return type of the <code>gyear_month_pimpl</code> parser implementation
+ is <code>xml_schema::gyear_month</code> which represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="6.13">6.13 <code>time</code> Parser</a></h2>
+
+ <p>The return type of the <code>time_pimpl</code> parser implementation
+ is <code>xml_schema::time</code> which represents hours, minutes,
+ and seconds with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+
+ <!-- Error Handling -->
+
+
+ <h1><a name="7">7 Document Parser and Error Handling</a></h1>
+
+ <p>In this chapter we will discuss the <code>xml_schema::document_pimpl</code>
+ type, the error handling mechanisms provided by the mapping, as well
+ as how to reuse a parser after an error has occurred.</p>
+
+ <p>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.
+ </p>
+
+ <p>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 <a href="#5.3">Section 5.3, "C++ Exceptions"</a>.</p>
+
+ <h2><a name="7.1">7.1 Document Parser</a></h2>
+
+ <p>The <code>xml_schema::document_pimpl</code> parser is a root parser for
+ the vocabulary. As mentioned in <a href="#3.4">Section 3.4,
+ "Connecting the Parsers Together"</a>, its interface varies depending
+ on the mapping configuration (<a href="#5">Chapter 5, "Mapping
+ Configuration"</a>). When STL and the iostream library are
+ enabled, the <code>xml_schema::document_pimpl</code> class has the
+ following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_base;
+
+ class document_pimpl
+ {
+ public:
+ document_pimpl (parser_base&amp;,
+ const char* root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const char* root_element_namespace,
+ const char* root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; 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&amp; 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&amp;);
+
+ // 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 ();
+ };
+}
+ </pre>
+
+ <p>When the use of STL is disabled, the constructors and the <code>parse()</code>
+ function that use <code>std::string</code> in their signatures
+ are not available. When the use of iostream is disabled, the
+ <code>parse()</code> functions that parse a local file and
+ <code>std::istream</code> are not available.</p>
+
+ <p>When support for XML Schema polymorphism is enabled, the
+ overloaded <code>document_pimpl</code> constructors have
+ additional arguments which control polymorphic parsing.
+ For more information refer to <a href="#5.7">Section 5.7,
+ "Support for Polymorphism"</a>.
+ </p>
+
+ <p>The first argument to all overloaded constructors is the
+ parser for the type of the root element. The <code>parser_base</code>
+ class is the base type for all parser skeletons. The second and
+ third arguments to the <code>document_pimpl</code>'s constructors are
+ the root element's name and namespace.</p>
+
+ <p>The <code>parse_begin()</code> and <code>parse_end()</code> functions
+ present a low-level, Expat-specific parsing API for maximum control.
+ A typical use case would look like this (pseudo-code):</p>
+
+ <pre class="c++">
+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 ());
+ </pre>
+
+ <p>Note that if your vocabulary use XML namespaces, the
+ <code>XML_ParserCreateNS()</code> functions should be used to create
+ the XML parser. Space (<code>XML_Char (' ')</code>) should be used
+ as a separator (the second argument to <code>XML_ParserCreateNS()</code>).
+ Furthermore, if XML_Parse or XML_ParseBuffer fail, call
+ <code>parse_end()</code> to determine the error which is indicated
+ either via exception or set as an error code.
+ </p>
+
+ <p>The error handling mechanisms employed by the <code>document_pimpl</code>
+ parser are described in <a href="#7.2">Section 7.2, "Exceptions"</a>
+ and <a href="#7.3">Section 7.3, "Error Codes"</a>.</p>
+
+ <h2><a name="7.2">7.2 Exceptions</a></h2>
+
+ <p>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 <code>std::bad_alloc</code>. The stream operation errors
+ are reported by throwing an instance of
+ <code>std::ios_base::failure</code>.</p>
+
+ <p>The xml and schema errors are reported by throwing the
+ <code>xml_schema::parser_xml</code> and <code>xml_schema::parser_schema</code>
+ exceptions, respectively. These two exceptions derive from
+ <code>xml_schema::parser_exception</code> which, in turn, derives
+ from <code>std::exception</code>. As a result, you can handle
+ any error from these two categories by either catching
+ <code>std::exception</code>, <code>xml_schema::parser_exception</code>,
+ 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:</p>
+
+ <pre class="c++">
+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&amp;
+ operator&lt;&lt; (std::ostream&amp;, const parser_exception&amp;);
+
+
+ typedef &lt;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 &lt;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 ();
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>parser_xml_error</code> and <code>parser_schema_error</code>
+ are implementation-specific error code types. The
+ <code>operator&lt;&lt;</code> defined for the <code>parser_exception</code>
+ class simply prints the error description as returned by the
+ <code>text()</code> function. The following example shows
+ how we can catch these exceptions:</p>
+
+ <pre class="c++">
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ // Parse argv[1].
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cout &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>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.</p>
+
+ <h2><a name="7.3">7.3 Error Codes</a></h2>
+
+ <p>When C++ exceptions are not available, error codes are used to
+ report error conditions. Each parser skeleton and the root
+ <code>document_pimpl</code> parser have the following member
+ function for querying
+ the error status:</p>
+
+ <pre class="c++">
+xml_schema::parser_error
+_error () const;
+ </pre>
+
+ <p>To handle all possible error conditions, you will need to obtain
+ the error status after calls to: the <code>document_pimpl</code>'s
+ constructor (it performs memory allocations which may fail), the
+ root parser <code>pre()</code> callback, each call to the <code>parse()</code>
+ function, and, finally, the call to the root parser
+ <code>post_*()</code> callback. The definition of
+ <code>xml_schema::parser_error</code> class is presented below:</p>
+
+ <pre class="c++">
+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 &lt;implementation-details> parser_xml_error;
+ typedef &lt;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;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>parser_xml_error</code> and <code>parser_schema_error</code>
+ are implementation-specific error code types. The
+ <code>parser_error</code> class incorporates four categories of errors
+ which you can query by calling the <code>type()</code> function.
+ The following example shows how to handle error conditions with
+ error codes. It is based on the person record example presented
+ in <a href="#3">Chapter 3, "Parser Skeletons"</a>.</p>
+
+ <pre class="c++">
+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 &lt;&lt; argv[1] &lt;&lt; ": error: " &lt;&lt; e.sys_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::xml:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.xml_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::schema:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.schema_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::app:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": application error " &lt;&lt; e.app_code () &lt;&lt; endl;
+ break;
+ }
+ }
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The error type for application errors is <code>int</code> with
+ the value <code>0</code> indicated the absence of error. You can
+ set the application error by calling the <code>_app_error()</code>
+ 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: </p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ age (short a)
+ {
+ if (a &lt; 18)
+ _app_error (1);
+ }
+
+ ...
+};
+ </pre>
+
+ <p>You can also set a system error by calling the <code>_sys_error()</code>
+ function inside a parser callback. This function has one argument of type
+ <code>xml_schema::sys_error</code> which was presented above. For
+ example:</p>
+
+ <pre class="c++">
+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_;
+};
+ </pre>
+
+
+ <h2><a name="7.4">7.4 Reusing Parsers after an Error</a></h2>
+
+ <p>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:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ ...
+
+ std::vector&lt;std::string> files = ...
+
+ xml_schema::document_pimpl doc_p (people_p, "people");
+
+ for (size_t i = 0; i &lt; files.size (); ++i)
+ {
+ try
+ {
+ people_p.pre ();
+ doc_p.parse (files[i]);
+ people_p.post_people ();
+ }
+ catch (const xml_schema::parser_exception&amp;)
+ {
+ doc_p.reset ();
+ }
+ }
+}
+ </pre>
+
+ <p>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 <code>--suppress-reset</code>
+ XSD/e compiler option.</p>
+
+ <p>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 <code>_reset()</code>
+ virtual function as shown below. Notice that when you override the
+ <code>_reset()</code> function in your implementation, you should
+ always call the base skeleton version to allow it to reset
+ its state:</p>
+
+<pre class="c++">
+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_;
+};
+ </pre>
+
+ <p>Note also that the <code>_reset()</code> 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 (<code>pre()</code> and <code>_pre()</code>) and
+ finalization (<code>post_*()</code> and <code>_post()</code>)
+ callbacks.</p>
+
+ <!-- Appendix A -->
+
+
+ <h1><a name="A">Appendix A &mdash; Supported XML Schema Constructs</a></h1>
+
+ <p>The Embedded C++/Parser mapping supports validation of the following
+ W3C XML Schema constructs in the generated code.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="features" border="1">
+ <tr><th>Construct</th><th>Notes</th></tr>
+ <tr><th colspan="2">Structure</th></tr>
+
+ <tr><td>element</td><td></td></tr>
+ <tr><td>attribute</td><td></td></tr>
+
+ <tr><td>any</td><td></td></tr>
+ <tr><td>anyAttribute</td><td></td></tr>
+
+ <tr><td>all</td><td></td></tr>
+ <tr><td>sequence</td><td></td></tr>
+ <tr><td>choice</td><td></td></tr>
+
+ <tr><td>complex type, empty content</td><td></td></tr>
+ <tr><td>complex type, mixed content</td><td></td></tr>
+ <tr><td>complex type, simple content extension</td><td></td></tr>
+ <tr><td>complex type, simple content restriction</td>
+ <td>Simple type facets are not validated.</td></tr>
+ <tr><td>complex type, complex content extension</td><td></td></tr>
+ <tr><td>complex type, complex content restriction</td><td></td></tr>
+
+ <tr><td>list</td><td></td></tr>
+
+ <tr><th colspan="2">Datatypes</th></tr>
+
+ <tr><td>byte</td><td></td></tr>
+ <tr><td>unsignedByte</td><td></td></tr>
+ <tr><td>short</td><td></td></tr>
+ <tr><td>unsignedShort</td><td></td></tr>
+ <tr><td>int</td><td></td></tr>
+ <tr><td>unsignedInt</td><td></td></tr>
+ <tr><td>long</td><td></td></tr>
+ <tr><td>unsignedLong</td><td></td></tr>
+ <tr><td>integer</td><td></td></tr>
+ <tr><td>nonPositiveInteger</td><td></td></tr>
+ <tr><td>nonNegativeInteger</td><td></td></tr>
+ <tr><td>positiveInteger</td><td></td></tr>
+ <tr><td>negativeInteger</td><td></td></tr>
+
+ <tr><td>boolean</td><td></td></tr>
+
+ <tr><td>float</td><td></td></tr>
+ <tr><td>double</td><td></td></tr>
+ <tr><td>decimal</td><td></td></tr>
+
+ <tr><td>string</td><td></td></tr>
+ <tr><td>normalizedString</td><td></td></tr>
+ <tr><td>token</td><td></td></tr>
+ <tr><td>Name</td><td></td></tr>
+ <tr><td>NMTOKEN</td><td></td></tr>
+ <tr><td>NCName</td><td></td></tr>
+ <tr><td>language</td><td></td></tr>
+ <tr><td>anyURI</td><td></td></tr>
+
+ <tr><td>ID</td><td>Identity constraint is not enforced.</td></tr>
+ <tr><td>IDREF</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>NMTOKENS</td><td></td></tr>
+ <tr><td>IDREFS</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>QName</td><td></td></tr>
+
+ <tr><td>base64Binary</td><td></td></tr>
+ <tr><td>hexBinary</td><td></td></tr>
+
+ <tr><td>date</td><td></td></tr>
+ <tr><td>dateTime</td><td></td></tr>
+ <tr><td>duration</td><td></td></tr>
+ <tr><td>gDay</td><td></td></tr>
+ <tr><td>gMonth</td><td></td></tr>
+ <tr><td>gMonthDay</td><td></td></tr>
+ <tr><td>gYear</td><td></td></tr>
+ <tr><td>gYearMonth</td><td></td></tr>
+ <tr><td>time</td><td></td></tr>
+ </table>
+
+ </div>
+</div>
+
+
+</body>
+</html>
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
--- /dev/null
+++ b/documentation/cxx/serializer/guide/figure-1.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/boris/tmp"
+ sodipodi:docname="figure-1.svg"
+ inkscape:export-filename="/home/boris/tmp/figure-1.png"
+ inkscape:export-xdpi="76.195885"
+ inkscape:export-ydpi="76.195885"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path2934"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_l"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_l"
+ style="overflow:visible">
+ <path
+ id="path2875"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.8) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path2928"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_m"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_m"
+ style="overflow:visible">
+ <path
+ id="path2872"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path2937"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path2910"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="425.58704"
+ inkscape:cy="699.39127"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="991"
+ inkscape:window-x="140"
+ inkscape:window-y="42"
+ showgrid="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g3902">
+ <rect
+ y="194.64178"
+ x="24.142784"
+ height="106.2678"
+ width="149.70432"
+ id="rect1872"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.29799986;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3038"
+ y="219.99649"
+ x="28.284279"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="219.99649"
+ x="28.284279"
+ id="tspan3064"
+ sodipodi:role="line">class people_simpl</tspan><tspan
+ y="236.24649"
+ x="28.284279"
+ id="tspan3066"
+ sodipodi:role="line">{</tspan><tspan
+ y="252.49649"
+ x="28.284279"
+ id="tspan3068"
+ sodipodi:role="line"> void </tspan><tspan
+ y="268.74649"
+ x="28.284279"
+ id="tspan3070"
+ sodipodi:role="line"> person ();</tspan><tspan
+ y="284.99649"
+ x="28.284279"
+ id="tspan3072"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:8.33343506;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5750"
+ width="149.4976"
+ height="246.47226"
+ x="264.03558"
+ y="124.53955" />
+ <text
+ xml:space="preserve"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ x="269.5889"
+ y="148.27567"
+ id="text5752"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan5900"
+ x="269.5889"
+ y="148.27567">class person_simpl</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5902"
+ x="269.5889"
+ y="161.27567">{</tspan><tspan
+ id="tspan2235"
+ sodipodi:role="line"
+ x="269.5889"
+ y="174.27567"> void</tspan><tspan
+ id="tspan2237"
+ sodipodi:role="line"
+ x="269.5889"
+ y="187.27567"> pre ();</tspan><tspan
+ id="tspan2239"
+ sodipodi:role="line"
+ x="269.5889"
+ y="200.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5904"
+ x="269.5889"
+ y="213.27567"> string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5906"
+ x="269.5889"
+ y="226.27567"> first_name ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5908"
+ x="269.5889"
+ y="239.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5910"
+ x="269.5889"
+ y="252.27567"> string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5912"
+ x="269.5889"
+ y="265.27567"> last_name ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5914"
+ x="269.5889"
+ y="278.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5916"
+ x="269.5889"
+ y="291.27567"> void</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5918"
+ x="269.5889"
+ y="304.27567"> gender ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5920"
+ x="269.5889"
+ y="317.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5922"
+ x="269.5889"
+ y="330.27567"> short</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5930"
+ x="269.5889"
+ y="343.27567"> age ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5932"
+ x="269.5889"
+ y="356.27567">};</tspan></text>
+ <g
+ id="g3845">
+ <rect
+ y="77.741814"
+ x="506.28357"
+ height="99.610825"
+ width="151.1286"
+ id="rect5955"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ transform="translate(-5.050762,12.10153)"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ id="flowRoot5957"
+ xml:space="preserve"><flowRegion
+ id="flowRegion5959"><rect
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ y="74.534515"
+ x="516.18793"
+ height="88.893425"
+ width="143.44167"
+ id="rect5961" /></flowRegion><flowPara
+ id="flowPara5965">class string_simpl</flowPara><flowPara
+ id="flowPara5967">{</flowPara><flowPara
+ id="flowPara5969"> void</flowPara><flowPara
+ id="flowPara5971"> pre (string);</flowPara><flowPara
+ id="flowPara5973">};</flowPara><flowPara
+ id="flowPara5975" /></flowRoot> </g>
+ <g
+ id="g3857">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5977"
+ width="151.1286"
+ height="99.610825"
+ x="506.28357"
+ y="316.15808" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot5979"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.050761,250.5178)"
+ inkscape:export-filename="/tmp/figure-1.png"
+ inkscape:export-xdpi="546.53815"
+ inkscape:export-ydpi="546.53815"><flowRegion
+ id="flowRegion5981"><rect
+ id="rect5983"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara5985">class short_simpl</flowPara><flowPara
+ id="flowPara5987">{</flowPara><flowPara
+ id="flowPara5989"> void</flowPara><flowPara
+ id="flowPara5991"> pre (short);</flowPara><flowPara
+ id="flowPara5993">};</flowPara><flowPara
+ id="flowPara5995" /></flowRoot> </g>
+ <g
+ id="g3869">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6023"
+ width="151.1286"
+ height="99.610825"
+ x="505.7785"
+ y="196.93977" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot6025"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.555838,129.2792)"><flowRegion
+ id="flowRegion6027"><rect
+ id="rect6029"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara6031">class gender_simpl</flowPara><flowPara
+ id="flowPara6033">{</flowPara><flowPara
+ id="flowPara6035"> void</flowPara><flowPara
+ id="flowPara6037"> pre ();</flowPara><flowPara
+ id="flowPara6039">};</flowPara><flowPara
+ id="flowPara6041" /></flowRoot> </g>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 129.28571,265.21932 L 214.28572,264.86218 L 215,185.3979 L 277.85714,184.50504"
+ id="path2267"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-mid:none;marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 400,222.36218 L 461.07144,222.36217 L 460.89286,143.79075 L 520.71429,143.79075"
+ id="path3240"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 370,301.64789 L 481.78571,301.29075 L 481.60714,262.8979 L 520,262.36218"
+ id="path3242"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 345.71429,340.93361 L 461.07143,341.29075 L 461.25,383.25504 L 520.71429,383.07647"
+ id="path3244"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);stroke-opacity:1;display:inline"
+ d="M 393.57143,261.64789 L 461.19314,261.78285 L 461.13464,222.52186"
+ id="path3250"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="ccc" />
+ </g>
+</svg>
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: "
+<div align=center>
+ <h1><big>Embedded C++/Serializer Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ 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 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Serializer Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2009 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,serialize,create,write,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Serializer Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ ol.steps {
+ padding-left : 1.8em;
+ }
+
+ ol.steps li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+
+ /* XML Schema features table. */
+ #features {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #features th, #features td {
+ border: 1px solid;
+ padding : 0.6em 0.6em 0.6em 0.6em;
+ }
+
+ #features th {
+ background : #cde8f6;
+ }
+
+ #features td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Serializer Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2009 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Serializer Skeletons</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Implementing the Gender Serializer</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Implementing the Person Serializer</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">Implementing the People Serializer</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">Connecting the Serializers Together</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Type Maps</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Object Model</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Type Map File Format</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Serializer Implementations</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Serializer Callbacks</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Optional Callback</a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Sequence Callback</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">Choice Callback</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">Element Wildcard Callbacks</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">Attribute Wildcard Callbacks</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1">Standard Template Library</a></td></tr>
+ <tr><th>6.2</th><td><a href="#6.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>6.3</th><td><a href="#6.3">C++ Exceptions</a></td></tr>
+ <tr><th>6.4</th><td><a href="#6.4">XML Schema Validation</a></td></tr>
+ <tr><th>6.5</th><td><a href="#6.5">64-bit Integer Type</a></td></tr>
+ <tr><th>6.6</th><td><a href="#6.6">Serializer Reuse</a></td></tr>
+ <tr><th>6.7</th><td><a href="#6.7">Support for Polymorphism</a></td></tr>
+ <tr><th>6.8</th><td><a href="#6.8">A Minimal Example</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>7</th><td><a href="#7">Built-In XML Schema Type Serializers</a>
+ <table class="toc">
+ <tr><th>7.1</th><td><a href="#7.1">Floating-Point Type Serializers</a></td></tr>
+ <tr><th>7.2</th><td><a href="#7.2">String-Based Type Serializers</a></td></tr>
+ <tr><th>7.3</th><td><a href="#7.3"><code>QName</code> Serializer</a></td></tr>
+ <tr><th>7.4</th><td><a href="#7.4"><code>NMTOKENS</code> and <code>IDREFS</code> Serializers</a></td></tr>
+ <tr><th>7.5</th><td><a href="#7.5"><code>base64Binary</code> and <code>hexBinary</code> Serializers</a></td></tr>
+ <tr><th>7.6</th><td><a href="#7.6">Time Zone Representation</a></td></tr>
+ <tr><th>7.7</th><td><a href="#7.7"><code>date</code> Serializer</a></td></tr>
+ <tr><th>7.8</th><td><a href="#7.8"><code>dateTime</code> Serializer</a></td></tr>
+ <tr><th>7.9</th><td><a href="#7.9"><code>duration</code> Serializer</a></td></tr>
+ <tr><th>7.10</th><td><a href="#7.10"><code>gDay</code> Serializer</a></td></tr>
+ <tr><th>7.11</th><td><a href="#7.11"><code>gMonth</code> Serializer</a></td></tr>
+ <tr><th>7.12</th><td><a href="#7.12"><code>gMonthDay</code> Serializer</a></td></tr>
+ <tr><th>7.13</th><td><a href="#7.13"><code>gYear</code> Serializer</a></td></tr>
+ <tr><th>7.14</th><td><a href="#7.14"><code>gYearMonth</code> Serializer</a></td></tr>
+ <tr><th>7.15</th><td><a href="#7.15"><code>time</code> Serializer</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>8</th><td><a href="#8">Document Serializer and Error Handling</a>
+ <table class="toc">
+ <tr><th>8.1</th><td><a href="#8.1">Document Serializer</a></td></tr>
+ <tr><th>8.2</th><td><a href="#8.2">Exceptions</a></td></tr>
+ <tr><th>8.3</th><td><a href="#8.3">Error Codes</a></td></tr>
+ <tr><th>8.4</th><td><a href="#8.4">Reusing Serializers after an Error</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th></th><td><a href="#A">Appendix A &mdash; Supported XML Schema Constructs</a></td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>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.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/serializer/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Serializer mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>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.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>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.
+ </p>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>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:
+ </p>
+
+ <ul class="list">
+ <li>Text-based representation results in inefficient use of
+ resources.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>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.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>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.</p>
+
+ <p>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:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> 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.</li>
+
+ <li><b>Natural representation.</b> 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.
+ </li>
+
+ <li><b>Concise code.</b> With a separate serializer skeleton for each
+ XML Schema type, the application implementation is simpler
+ and thus easier to read and understand.</li>
+
+ <li><b>Safety.</b> 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.</li>
+
+ <li><b>Maintainability.</b> 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.</li>
+
+ <li><b>Efficiency.</b> 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.</li>
+ </ul>
+
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>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 <code>hello</code>
+ example which can be found in the <code>examples/cxx/serializer/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing Schema</a></h2>
+
+ <p>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:</p>
+
+ <pre class="xml">
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>earth&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with the XML Schema language, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in the sample XML document above. The <code>hello</code>
+ type is defined as a sequence of the nested <code>greeting</code>
+ and <code>name</code> 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 <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounded</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>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.</p>
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++
+ serializer skeletons. To do this we invoke the XSD/e compiler
+ from a terminal (UNIX) or a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer hello.xsd
+ </pre>
+
+ <p>The XSD/e compiler produces two C++ files: <code>hello-sskel.hxx</code>
+ and <code>hello-sskel.cxx</code>. The following code fragment is taken
+ from <code>hello-sskel.hxx</code>; it should give you an idea about what
+ gets generated:
+ </p>
+
+<pre class="c++">
+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&amp;);
+
+ void
+ name_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ serializers (xml_schema::string_sskel&amp; /* greeting */,
+ xml_schema::string_sskel&amp; /* name */);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>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.</p>
+
+ <p>The <code>pre()</code> function is an initialization callback. It is
+ called when a new element of type <code>hello</code> 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.</p>
+
+ <p>The <code>post()</code> 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 <code>pre()</code> or during serialization.
+ The default implementation of the finalization callback also does
+ nothing.
+ </p>
+
+ <p>The <code>greeting()</code> and <code>name()</code> functions are
+ called when the <code>greeting</code> and <code>name</code> elements
+ are about to be serialized and the values for these elements need
+ to be provided. Because the <code>name</code> element can be
+ repeated several times (note the <code>maxOccurs="unbounded"</code>
+ attribute in the schema), the serializer skeleton also has the
+ <code>name_next()</code> function which is called before
+ <code>name()</code> to check if another <code>name</code> element
+ needs to be serialized.</p>
+
+ <p>The last three functions are for connecting serializers to each other.
+ For example, there is a predefined serializer for built-in XML Schema
+ type <code>string</code> in the XSD/e runtime. We will be using it to
+ serialize the values of <code>greeting</code> and <code>name</code>
+ elements, as shown in the next section.</p>
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>At this point we have all the parts we need to create our
+ sample XML document. The first step is to implement the
+ serializer:
+ </p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;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&lt;std::string> names;
+
+ names names_;
+ names::iterator i_;
+};
+ </pre>
+
+ <p>We use the <code>hello_simpl</code>'s constructor to initialize
+ a vector of names. Then, in the <code>pre()</code> initialization
+ callback, we initialize an iterator to point to the beginning of the
+ names vector. The <code>greeting()</code> callback
+ simply returns the string representing our greeting. The
+ <code>name_next()</code> callback checks if we reached the
+ end of the names vector and returns <code>false</code>
+ if that's the case. The <code>name()</code> callback returns
+ the next name from the names vector and advances the iterator.
+ Note that <code>name()</code> is not called if <code>name_next()</code>
+ returned false. Finally, we left <code>post()</code> with the
+ default implementations since we don't have anything to cleanup.</p>
+
+ <p>Now it is time to put this serializer implementation to work:</p>
+
+ <pre class="c++">
+#include &lt;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&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The first part of this code snippet instantiates individual serializers
+ and assembles them into a complete vocabulary serializer.
+ <code>xml_schema::string_simpl</code> is an implementation of a
+ serializer for built-in XML Schema type <code>string</code>. 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
+ <a href="#7">Chapter 7, "Built-In XML Schema Type Serializers"</a>).
+ We use <code>string_simpl</code> to serialize the <code>greeting</code>
+ and <code>name</code> elements as indicated by the calls to
+ <code>greeting_serializer()</code> and <code>name_serializer()</code>.
+ </p>
+
+ <p>Then we instantiate a document serializer (<code>doc_s</code>). The
+ first argument to its constructor is the serializer for the root
+ element (<code>hello_s</code> in our case). The second argument is
+ the root element name.
+ </p>
+
+ <p>The final piece is the calls to <code>pre()</code>,
+ <code>serialize()</code>, and <code>post()</code>. The call to
+ <code>serialize()</code> performs the actual XML serialization
+ with the result written to <code>std::cout</code>. The calls
+ to <code>pre()</code> and <code>post()</code> make sure that
+ the serializer for the root element can perform proper
+ initialization and cleanup.</p>
+
+ <p>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 <code>--generate-empty-impl</code>
+ option. To request the generation of a test driver you can use the
+ <code>--generate-test-driver</code> option. For more information
+ on these options refer to the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.</p>
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving all the parts from the previous section in
+ <code>driver.cxx</code>, we are ready to compile and run
+ our first application. On UNIX this can be done with the
+ following commands:
+ </p>
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx hello-sskel.cxx
+$ c++ -o driver driver.o hello-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+&lt;hello>
+ &lt;greeting>Hello&lt;/greeting>
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.</p>
+
+ <p>
+ We can also test XML Schema validation. We can "forget" to
+ add any names to the vector so that <code>name_next()</code>
+ returns <code>false</code> on the first call:</p>
+
+<pre class="c++">
+struct hello_simpl: hello_sskel
+{
+ hello_simpl ()
+ {
+ /*
+ names_.push_back ("sun");
+ names_.push_back ("moon");
+ names_.push_back ("world");
+ */
+ }
+ ...
+};
+ </pre>
+
+ <p>This will violate our vocabulary specification which requires
+ at least one <code>name</code> element to be present. If we
+ make the above change and recompile our application, we will
+ get the following output:</p>
+
+ <pre class="terminal">
+$ ./driver
+error: expected element not encountered
+ </pre>
+
+
+ <!-- Chapater 3 -->
+
+
+ <h1><a name="3">3 Serializer Skeletons</a></h1>
+
+ <p>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.</p>
+
+ <p>In this and subsequent chapters we will use the following
+ schema that describes a collection of person records. We
+ save it in <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema could look like
+ this:</p>
+
+ <pre class="xml">
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three serializer skeletons being generated: <code>gender_sskel</code>,
+ <code>person_sskel</code>, and <code>people_sskel</code>. We are going
+ to examine and implement each of them in the subsequent sections.</p>
+
+ <p>In the previous chapter we used pre-initialized, static data to
+ create an XML document. In this chapter we will use the standard
+ input (<code>std::cin</code>) 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.</p>
+
+ <h2><a name="3.1">3.1 Implementing the Gender Serializer</a></h2>
+
+ <p>The generated <code>gender_sskel</code> serializer skeleton looks
+ like this:</p>
+
+ <pre class="c++">
+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 ();
+};
+ </pre>
+
+ <p>Notice that <code>gender_sskel</code> inherits from
+ <code>xml_schema::string_sskel</code> which is a serializer
+ skeleton for built-in XML Schema type <code>string</code>
+ 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 <code>gender_sskel</code> class also
+ declares a constructor which expects a pointer to the base
+ serializer skeleton. We will discuss the purpose of this
+ constructor shortly.</p>
+
+ <p>The <code>pre()</code> and <code>post()</code> 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 (<code>std::cin</code>):</p>
+
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;iostream>
+
+using namespace std;
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ string g;
+ cerr &lt;&lt; "gender (male/female): ";
+ getline (cin, g);
+ base_impl_.pre (g);
+ }
+
+private:
+ xml_schema::string_simpl base_impl_;
+};
+ </pre>
+
+ <p>While the code is quite short, there is a lot going on. First,
+ notice that we define a member variable <code>base_impl_</code>
+ of type <code>xml_schema::string_simpl</code> and then pass
+ it to the <code>gender_sskel</code>'s constructor. We have
+ encountered <code>xml_schema::string_simpl</code> already; it is an
+ implementation of the <code>xml_schema::string_sskel</code> serializer
+ skeleton for built-in XML Schema type <code>string</code>. By
+ passing <code>base_impl_</code> to the <code>gender_sskel</code>'s
+ constructor we provide an implementation for the part of the
+ serializer skeleton that is inherited from <code>string_sskel</code>.</p>
+
+ <p>This is another common theme in the C++/Serializer programming model:
+ reusing implementations of the base serializers in the derived ones.
+ In our case, <code>string_simpl</code> will do all the dirty work of
+ serializing the data which we pass to it with the call to
+ <code>base_impl_.pre()</code>. For more information on serializer
+ implementation reuse refer to <a href="#6.6">Section 6.6,
+ "Serializer Reuse"</a>.</p>
+
+ <p>In case you are curious, here are the definitions for
+ <code>xml_schema::string_sskel</code> and
+ <code>xml_schema::string_simpl</code>:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sskel: public serializer_simple_content
+ {
+ public:
+ virtual void
+ pre (const std::string&amp;) = 0;
+ };
+
+ class string_simpl: public string_sskel
+ {
+ public:
+ virtual void
+ pre (const std::string&amp;);
+
+ virtual void
+ _serialize_content ();
+
+ protected:
+ std::string value_;
+ };
+}
+ </pre>
+
+ <p>There are two new pieces in this code that we haven't seen yet.
+ Those are the <code>xml_schema::serializer_simple_content</code>
+ class and the <code>_serialize_content()</code> function.
+ The <code>serializer_simple_content</code> 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&mdash;only
+ text and attributes. There is also the
+ <code>xml_schema::serializer_complex_content</code> class which
+ corresponds to the complex content mode (types with nested elements,
+ for example, <code>person</code> from <code>people.xsd</code>).</p>
+
+ <p>The <code>_serialize_content()</code> 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 <code>_serialize_attributes()</code> 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.</p>
+
+ <p>Another bit of information that is useful to know about is
+ the <code>_pre()</code> and <code>_post()</code> serialization
+ callbacks. Remember we talked about the <code>pre()</code> and
+ <code>post()</code> callbacks in the previous chapter? The
+ <code>_pre()</code> and <code>_post</code> have very
+ similar but somewhat different roles. As a result, each
+ serializer skeleton has four special callbacks:</p>
+
+ <pre class="c++">
+ virtual void
+ pre ();
+
+ virtual void
+ _pre ();
+
+ virtual void
+ _post ();
+
+ virtual void
+ post ();
+ </pre>
+
+ <p><code>pre()</code> and <code>_pre()</code> are initialization
+ callbacks. They get called in that order before a new instance of the type
+ is about to be serialized. The difference between <code>pre()</code> and
+ <code>_pre()</code> is conventional: <code>pre()</code> can
+ be completely overridden by a derived serializer. The derived
+ serializer can also override <code>_pre()</code> but has to always call
+ the original version. This allows you to partition initialization
+ into customizable and required parts.</p>
+
+ <p>Similarly, <code>_post()</code> and <code>post()</code> are
+ finalization callbacks with exactly the same semantics:
+ <code>post()</code> can be completely overridden by the derived
+ serializer while the original <code>_post()</code> should always be
+ called.
+ </p>
+
+ <p>At this point you might be wondering why some <code>pre()</code>
+ callbacks, for example <code>string_sskel::pre()</code>, have an
+ argument with which they receive the data they need to serialize while
+ others, for example <code>gender_sskel::pre()</code>, have no such
+ argument. This is a valid concern and it will be addressed in the
+ next chapter.</p>
+
+ <h2><a name="3.2">3.2 Implementing the Person Serializer</a></h2>
+
+ <p>The generated <code>person_sskel</code> serializer skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ void
+ last_name_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ gender_serializer (gender_sskel&amp;);
+
+ void
+ age_serializer (xml_schema::short_sskel&amp;);
+
+ void
+ serializers (xml_schema::string_sskel&amp; /* first-name */,
+ xml_schema::string_sskel&amp; /* last-name */,
+ gender_sskel&amp; /* gender */,
+ xml_schema::short_sskel&amp; /* age */);
+};
+ </pre>
+
+
+ <p>As you can see, we have a serializer callback for each of the nested
+ elements found in the <code>person</code> XML Schema type.
+ The implementation of this serializer is straightforward:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual string
+ first_name ()
+ {
+ string fn;
+ cerr &lt;&lt; "first name: ";
+ getline (cin, fn);
+ return fn;
+ }
+
+ virtual std::string
+ last_name ()
+ {
+ string ln;
+ cerr &lt;&lt; "last name: ";
+ getline (cin, ln);
+ return ln;
+ }
+
+ virtual short
+ age ()
+ {
+ short a;
+ cerr &lt;&lt; "age: ";
+ cin >> a;
+ return a;
+ }
+};
+ </pre>
+
+ <p>Notice that we didn't need to override the <code>gender()</code>
+ callback because all the work is done by <code>gender_simpl</code>.</p>
+
+ <h2><a name="3.3">3.3 Implementing the People Serializer</a></h2>
+
+ <p>The generated <code>people_sskel</code> serializer skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ void
+ serializers (person_sskel&amp; /* person */);
+};
+ </pre>
+
+ <p>The <code>person_next()</code> callback will be called before serializing
+ each <code>person</code> element. Our implementation of
+ <code>person_next()</code> asks the user whether to serialize
+ another person record:</p>
+
+ <pre class="c++">
+class people_simpl: public people_sskel
+{
+public:
+ virtual bool
+ person_next ()
+ {
+ string s;
+ cerr &lt;&lt; "serialize another person record (y/n): ";
+ cin >> ws; // Skip leading whitespaces.
+ getline (cin, s);
+ return s == "y";
+ }
+};
+ </pre>
+
+ <p>Now it is time to put everything together.</p>
+
+
+ <h2><a name="3.4">3.4 Connecting the Serializers Together</a></h2>
+
+ <p>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:</p>
+
+ <pre class="c++">
+xml_schema::short_simpl short_s;
+xml_schema::string_simpl string_s;
+
+gender_simpl gender_s;
+person_simpl person_s;
+people_simpl people_s;
+ </pre>
+
+ <p>Notice that our schema uses two built-in XML Schema types:
+ <code>string</code> for the <code>first-name</code> and
+ <code>last-name</code> elements as well as <code>short</code>
+ for <code>age</code>. 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 <code>*_serializer()</code> functions:</p>
+
+ <pre class="c++">
+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);
+ </pre>
+
+ <p>You might be wondering what happens if you do not provide
+ a serializer by not calling one of the <code>*_serializer()</code>
+ functions. In that case the corresponding XML fragment will be
+ skipped.</p>
+
+ <p>An alternative, shorter, way to connect the serializers is by using
+ the <code>serializers()</code> functions which connects all the
+ serializers for a given type at once:</p>
+
+ <pre class="c++">
+person_s.serializers (string_s, string_s, gender_s, short_s);
+people_s.serializers (person_s);
+ </pre>
+
+ <p>The following figure illustrates the resulting connections. Notice
+ the correspondence between return types of element callbacks and
+ argument types of the <code>pre()</code> functions that are connected
+ by the arrows.</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>The last step is the construction of the document serializer and
+ invocation of the complete serializer to produce an XML
+ document:</p>
+
+ <pre class="c++">
+xml_schema::document_simpl doc_s (people_s, "people");
+
+std::ostringstream os;
+
+people_s.pre ();
+doc_s.serialize (os);
+people_s.post ();
+
+cout &lt;&lt; os.str ();
+ </pre>
+
+ <p>Note that we first serialize the document into an
+ <code>std::ostringstream</code> 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 <code>std::cout</code> in
+ this example is a great way to observe the moments in the XML
+ document construction process at which serializer callbacks are
+ being called.</p>
+
+ <p>Let's consider <code>xml_schema::document_simpl</code> in
+ more detail. While the exact definition of this class
+ varies depending on the mapping configuration, here is
+ the part relevant to our example:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class document_simpl
+ {
+ public:
+ document_simpl (xml_schema::serializer_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_simpl (xml_schema::serializer_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+ void
+ serialize (std::ostream&amp;);
+ };
+}
+ </pre>
+
+ <p><code>xml_schema::document_simpl</code> is a root serializer for
+ the vocabulary. The first argument to its constructors is the
+ serializer for the type of the root element (<code>people_simpl</code>
+ 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
+ <code>document_simpl</code>'s constructors.</p>
+
+ <p>There is also a number of overloaded <code>serialize()</code>
+ function defined in the <code>document_simpl</code> class.
+ At the moment we are only interested in the version that
+ writes XML to a standard output stream. For more information
+ on the <code>xml_schema::document_simpl</code> class
+ refer to <a href="#8">Chapter 8, "Document Serializer and Error
+ Handling"</a>.</p>
+
+ <p>Let's now consider a step-by-step list of actions that happen
+ as we serialize the following sample XML document:</p>
+
+ <pre class="xml">
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <ol class="steps">
+ <li><code>people_s.pre()</code> is called from
+ <code>main()</code>. We did not provide any implementation
+ for this callback so this call is a no-op.</li>
+
+ <li><code>doc_s.serialize(os)</code> is called from
+ <code>main()</code>. The document serializer
+ writes out the <code>&lt;people></code> opening tag
+ and calls <code>_pre()</code> on the root element
+ type serializer (<code>people_s</code>) which is
+ also a no-op. Serialization is delegated to
+ <code>people_s</code>.</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person_next()</code>
+ to determine if another <code>person</code> element
+ needs to be serialized. Our implementation ask the user
+ (who answers <code>"y"</code>) and returns <code>true</code>.</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person()</code>
+ which is a no-op. It then calls <code>pre()</code> on
+ <code>person_s</code> (no-op), writes out the
+ <code>&lt;person></code> opening tag, and calls <code>_pre()</code>
+ on <code>person_s</code> (no-op). Serialization is delegated to
+ <code>person_s</code>.</li>
+
+ <li>The <code>person_s</code> serializer calls <code>first_name()</code>
+ that returns a first name which it asks the user to enter.
+ <code>person_s</code> then calls <code>pre()</code> on
+ <code>string_s</code> and passes the name returned from
+ <code>first_name()</code> as its argument. It then writes
+ out the <code>&lt;first-name></code> opening tag and calls
+ <code>_pre()</code> on <code>string_s</code>. Serialization
+ is delegated to <code>string_s</code>.</li>
+
+ <li>The <code>_serialize_content()</code> callback is called on
+ <code>string_s</code> which writes out the string passed
+ to it in the <code>pre()</code> call.</li>
+
+ <li>Control is returned to <code>person_s</code> which
+ calls <code>_post()</code> on <code>string_s</code>, writes
+ out the <code>&lt;/first-name></code> closing tag, and calls
+ <code>post()</code> on <code>string_s</code>.</li>
+
+ <li>Steps analogous to 5-7 are performed for the <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements.</li>
+
+ <li>Control is returned to <code>people_s</code>
+ which calls <code>_post()</code> on <code>person_s</code> (no-op),
+ writes out the <code>&lt;/person></code> closing tag, and calls
+ <code>post()</code> on <code>person_s</code> (no-op).</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person_next()</code>
+ to determine if another <code>person</code> element
+ needs to be serialized. Our implementation ask the user
+ (who answers <code>"n"</code>) and returns <code>false</code>.</li>
+
+ <li>Control is returned to <code>doc_s</code> which calls
+ <code>_post()</code> on <code>people_s</code> (no-op) and
+ writes out the <code>&lt;/people></code> closing tag.</li>
+
+ <li>Control is returned to <code>main()</code> which
+ calls <code>post()</code> on <code>people_s</code> (no-op).</li>
+ </ol>
+
+
+ <!-- Chpater 4 -->
+
+
+ <h1><a name="4">4 Type Maps</a></h1>
+
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <h2><a name="4.1">4.1 Object Model</a></h2>
+
+ <p>An object model for our person record example could
+ look like this (saved in the <code>people.hxx</code> file):</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum gender
+{
+ male,
+ female
+};
+
+class person
+{
+public:
+ person (const std::string&amp; first,
+ const std::string&amp; last,
+ ::gender gender,
+ short age)
+ : first_ (first), last_ (last),
+ gender_ (gender), age_ (age)
+ {
+ }
+
+ const std::string&amp;
+ first () const
+ {
+ return first_;
+ }
+
+ const std::string&amp;
+ 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&lt;person> people;
+ </pre>
+
+ <p>While it is clear which serializer is responsible for which part of
+ the object model, it is not exactly clear how, for
+ example, <code>person_simpl</code> will pass <code>gender</code>
+ to <code>gender_simpl</code>. You might have noticed that
+ <code>string_simpl</code> manages to receive its value from the
+ <code>first_name()</code> callback. Let's
+ see how we can utilize the same mechanism to propagate our
+ own data.</p>
+
+ <p>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 <code>pre()</code> 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
+ <code>gender</code> we can specify the argument type for
+ <code>pre()</code> in the <code>gender_sskel</code>
+ skeleton and the return type for the <code>gender()</code> callback
+ in the <code>person_sskel</code> skeleton. As you might have guessed,
+ the generated code will then pass the return value from an
+ element or attribute callback (<code>person_sskel::gender()</code>
+ in our case) to the <code>pre()</code> callback of the corresponding
+ serializer skeleton (<code>gender_sskel::pre()</code> in our case).</p>
+
+ <p>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 <code>gender</code> type from the previous paragraph.</p>
+
+ <pre class="type-map">
+include "people.hxx";
+gender ::gender ::gender;
+ </pre>
+
+ <p>The first line indicates that the generated code must include
+ <code>people.hxx</code> in order to get the definition for the
+ <code>gender</code> type. The second line specifies that both
+ argument and return types for the <code>gender</code>
+ XML Schema type should be the <code>::gender</code> 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 <code>people.map</code> and
+ then translate our schemas with the <code>--type-map</code>
+ option to let the XSD/e compiler know about our type map:</p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer --type-map people.map people.xsd
+ </pre>
+
+ <p>If we now look at the generated <code>people-sskel.hxx</code>,
+ we will see the following changes in the <code>gender_sskel</code> and
+ <code>person_sskel</code> skeletons:</p>
+
+ <pre class="c++">
+#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;
+
+ ...
+};
+ </pre>
+
+ <p>Notice that <code>#include "people.hxx"</code> was added to
+ the generated header file from the type map to provide the
+ definition for the <code>gender</code> enum.</p>
+
+ <h2><a name="4.2">4.2 Type Map File Format</a></h2>
+
+ <p>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 <code>pre()</code>
+ callbacks in serializer skeletons corresponding to XML Schema
+ types as well as return types for callbacks corresponding
+ to elements and attributes of these types.</p>
+
+ <p>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 <code>void</code>.
+ By providing your own type maps you can override these predefined
+ rules. The format of the type map file is presented below:
+ </p>
+
+ <pre class="type-map">
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code>"&nbsp;"</code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the element and attribute callbacks corresponding
+ to this schema type. Optional <code><i>&lt;cxx-arg-type></i></code>
+ is an argument type for the <code>pre()</code> callback in the serializer
+ skeleton for this schema type. If <code><i>&lt;cxx-arg-type></i></code>
+ is not specified, it defaults to <code><i>&lt;cxx-ret-type></i></code>
+ if <code><i>&lt;cxx-ret-type></i></code> ends with <code>*</code> or
+ <code>&amp;</code> (that is, it is a pointer or a reference) and
+ <code>const&nbsp;<i>&lt;cxx-ret-type></i>&amp;</code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code>"&nbsp;"</code> or <code>&lt;&nbsp;></code> format
+ and is added with the <code>#include</code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code>http://www.example.com/xmlns/my#orange</code>
+ XML Schema type, the <code>my::orange_t*</code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>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:</p>
+
+ <pre class="type-map">
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="type-map">
+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;
+}
+ </pre>
+
+ <p>If STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>), the following mapping is used for the string-based
+ XML Schema built-in types:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;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;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre class="type-map">
+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*";
+}
+ </pre>
+
+ <p>For more information about the mapping of the built-in XML Schema types
+ to C++ types refer to <a href="#7">Chapter 7, "Built-In XML Schema Type
+ Serializers"</a>. The last predefined rule maps anything that wasn't
+ mapped by previous rules to <code>void</code>:</p>
+
+ <pre class="type-map">
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+
+ <p>When you provide your own type maps with the
+ <code>--type-map</code> 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 <code>xml_schema</code> namespace. You can include the
+ custom definitions into the generated header file using the
+ <code>--hxx-prologue-*</code> options.</p>
+
+ <h2><a name="4.3">4.3 Serializer Implementations</a></h2>
+
+ <p>With the knowledge from the previous section, we can proceed
+ with creating a type map that maps types in the <code>people.xsd</code>
+ schema to our object model classes in
+ <code>people.hxx</code>. In fact, we already have the beginning
+ of our type map file in <code>people.map</code>. Let's extend
+ it with the rest of the types:</p>
+
+ <pre class="type-map">
+include "people.hxx";
+
+gender ::gender ::gender;
+person "const ::person&amp;";
+people "const ::people&amp;";
+ </pre>
+
+ <p>A few things to note about this type map. We decided to pass
+ the <code>person</code> and <code>people</code> 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
+ <code>string</code> and <code>short</code> 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:</p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer --type-map people.map people.xsd
+ </pre>
+
+ <p>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.</p>
+
+ <pre class="c++">
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;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&amp; p)
+ {
+ p_ = &amp;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&amp; p)
+ {
+ p_ = &amp;p;
+ i_ = p_->begin ();
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ != p_->end ();
+ }
+
+ virtual const ::person&amp;
+ person ()
+ {
+ return *i_++;
+ }
+
+private:
+ const people* p_;
+ people::const_iterator i_;
+};
+ </pre>
+
+ <p>This code fragment should look familiar by now. Just note that
+ all the <code>pre()</code> callbacks now have arguments. Here is the
+ implementation of the test driver for this example:</p>
+
+ <pre class="c++">
+#include &lt;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 ();
+}
+ </pre>
+
+ <p>The serializer creation and assembly part is exactly the same as in
+ the previous chapter. The serialization part is a bit different:
+ <code>people_simpl::pre()</code> 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 <code>driver.cxx</code>
+ and proceed to compile and test our new application:</p>
+
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx people-sskel.cxx
+$ c++ -o driver driver.o people-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <!-- Serializer Callbacks -->
+
+ <h1><a name="5">5 Serializer Callbacks</a></h1>
+
+ <p>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
+ (<code>maxOccurs="unbounded"</code>) have an additional
+ serializer callback in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_next ();
+ </pre>
+
+ <p>Where <code>&lt;name></code> 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 <code>all</code>, <code>choice</code>,
+ and <code>sequence</code> compositors as well as the <code>any</code>
+ and <code>anyAttribute</code> wildcards.</p>
+
+ <p>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: <code>all</code> for the <code>all</code>
+ compositor, <code>sequence</code>, <code>sequence1</code>,
+ etc., for the <code>sequence</code> compositors, <code>choice</code>,
+ <code>choice1</code>, etc., for the <code>choice</code> compositors,
+ <code>any</code>, <code>any1</code>, etc., for the <code>any</code>
+ wildcards, and <code>any_attribute</code>, <code>any_attribute1</code>,
+ etc., for the <code>anyAttribute</code> wildcards. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="coordinates">
+ &lt;xs:sequence maxOccurs="unbounded">
+ &lt;xs:element name="lat" type="xs:float"/>
+ &lt;xs:element name="lon" type="xs:float"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+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 ();
+
+ ...
+};
+ </pre>
+
+
+ <h2><a name="5.1">5.1 Optional Callback</a></h2>
+
+ <p>For elements, compositors, and element wildcards with the minimal
+ occurrence constraint equals <code>0</code> (<code>minOccurs="0"</code>)
+ and the maximum occurrence constraint equals <code>1</code>
+ (<code>maxOccurs="1"</code>) as well as for optional attributes, the
+ optional callback is generated in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_present ();
+ </pre>
+
+ <p>This callback is called before any other callbacks for this schema
+ construct and if it returns <code>false</code> no further callback
+ calls corresponding to this construct are made and the corresponding
+ XML fragment is omitted. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence minOccurs="0">
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="initial" type="xs:string" minOccurs="0"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;xs:attribute name="lang" type="xs:language"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+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 ();
+
+ ...
+};
+ </pre>
+
+ <h2><a name="5.2">5.2 Sequence Callback</a></h2>
+
+ <p>For elements, compositors, and element wildcards with the the maximum
+ occurrence constraint greater than <code>1</code> (for example,
+ <code>maxOccurs="unbounded"</code>) the sequence callback is
+ generated in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_next ();
+ </pre>
+
+ <p>This callback is called before each new item of the sequence is
+ about to be serialized. Returning <code>false</code> from this
+ callback indicates that no more items in the sequence need to
+ be serialized. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="names">
+ &lt;xs:sequence maxOccurs="unbounded">
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;xs:element name="pseudonym" type="xs:string" maxOccurs="3"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+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 ();
+};
+ </pre>
+
+ <h2><a name="5.3">5.3 Choice Callback</a></h2>
+
+ <p>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 <em>choice
+ arms</em> and are identified by the <em>arm tags</em>. For
+ example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:choice>
+ &lt;xs:element name="full-name" type="xs:string"/>
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:choice>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+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 ();
+};
+ </pre>
+
+ <p>The arm tags enum name (<code>choice_arm_tag</code> above) is derived
+ from the choice compositor name (that is, <code>choice</code>,
+ <code>choice1</code>, etc.) by adding the <code>_arm_tag</code>
+ suffix. The tag names themselves are derived from the corresponding
+ elements, compositors, or element wildcards.</p>
+
+ <p>The choice compositor callback has a name in the form
+ <code>choice_tag()</code> (or <code>choice1_tag()</code>, etc., for
+ subsequent <code>choice</code> compositors in the type). It returns
+ the arm tag which identifies the choice arm that should be
+ serialized. For example, if a <code>name_sskel</code> implementation
+ returns <code>full_name_tag</code> from the <code>choice_arm()</code>
+ callback, then the first choice arm is chosen and
+ the <code>full_name()</code> callback is then called. Otherwise
+ the <code>first_name</code> and <code>last_name()</code> callbacks
+ are called.</p>
+
+
+ <h2><a name="5.4">5.4 Element Wildcard Callbacks</a></h2>
+
+ <p>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:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence>
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;xs:any namespace="##other" processContents="skip" minOccurs="0"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+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&amp; ns, std::string&amp; name);
+
+ virtual void
+ serialize_any ();
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>The <code>any()</code> 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 <code>serialize_any()</code>
+ 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 <code>wildcard</code> 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
+ <code>xml_schema::serializer_base</code> base serializer:</p>
+
+ <pre class="c++">
+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 ();
+ };
+}
+ </pre>
+
+ <p>The following example shows how we could implement the
+ <code>name_sskel</code> skeleton using this approach:</p>
+
+ <pre class="c++">
+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&amp; ns, std::string&amp; 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 ();
+ }
+};
+ </pre>
+
+
+ <h2><a name="5.5">5.5 Attribute Wildcard Callbacks</a></h2>
+
+ <p>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 <code>maxOccurs="unbounded"</code>. For
+ example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence>
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;xs:anyAttribute namespace="##any" processContents="skip"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual bool
+ any_attribute_next ();
+
+ virtual void
+ any_attribute (std::string&amp; ns, std::string&amp; name);
+
+ virtual void
+ serialize_any_attribute ();
+
+ virtual std::string
+ first () = 0;
+
+ virtual std::string
+ last () = 0;
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>Every time the <code>any_attribute_next()</code> callback returns
+ <code>true</code>, <code>any_attribute()</code> 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
+ <code>serialize_any_attribute()</code> callback is called to allow
+ you to write the attribute value, for example using one of the
+ serializer implementations (see the <code>wildcard</code> example
+ on how to do it) or the low-level <code>_characters()</code> function
+ (for more information about the low-level XML serialization
+ API see the previous section). The following example show
+ how we could implement the <code>name_sskel</code> skeleton
+ using the latter approach:</p>
+
+ <pre class="c++">
+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&amp; ns, std::string&amp; 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_;
+};
+ </pre>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="6">6 Mapping Configuration</a></h1>
+
+ <p>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.</p>
+
+ <p>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
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>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.</p>
+
+ <h2><a name="6.1">6.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> 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 <code>const char*</code>
+ instead of <code>std::string</code>, as described in
+ <a href="#4.2">Section 4.2, "Type Map File Format"</a>. The
+ following code fragment shows changes in the
+ signatures of the <code>first_name()</code> and <code>last_name()</code>
+ callbacks from the person record example.</p>
+
+ <pre class="c++">
+class person_sskel
+{
+public:
+ virtual const char*
+ first_name ();
+
+ virtual const char*
+ last_name ();
+
+ ...
+};
+ </pre>
+
+ <p>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 <code>delete[]</code>. For more
+ information on how to do this refer to <a href="#7.2">Section 7.2,
+ "String-Based Type Serializers"</a>.
+ </p>
+
+ <h2><a name="6.2">6.2 Input/Output Stream Library</a></h2>
+
+ <p>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 <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, the
+ following <code>serialize()</code> function in the
+ <code>xml_schema::document_simpl</code> class become unavailable:</p>
+
+ <pre class="c++">
+void
+serialize (std::ostream&amp;);
+ </pre>
+
+ <p>See <a href="#8.1">Section 8.1, "Document Serializer"</a>
+ for more information.</p>
+
+ <h2><a name="6.3">6.3 C++ Exceptions</a></h2>
+
+ <p>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 <code>--no-exceptions</code> 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 <a href="#8.3">Section 8.3,
+ "Error Codes"</a>.
+ </p>
+
+ <h2><a name="6.4">6.4 XML Schema Validation</a></h2>
+
+ <p>To disable support for XML Schema validation, you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--suppress-validation</code> 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.
+ </p>
+
+ <h2><a name="6.5">6.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ XML Schema built-in types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> 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 <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="6.6">6.6 Serializer Reuse</a></h2>
+
+ <p>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 <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.</p>
+
+ <p>The compiler can also be instructed not to generate any support
+ for serializer reuse with the <code>--reuse-style-none</code> 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.</p>
+
+
+ <p>To provide concrete examples for each reuse style we will use the
+ following schema fragment:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+
+&lt;xs:complexType name="emplyee">
+ &lt;complexContent>
+ &lt;extension base="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="position" type="xs:string"/>
+ &lt;xs:element name="salary" type="xs:unsignedLong"/>
+ &lt;/xs:sequence>
+ &lt;/extension>
+ &lt;/complexContent>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="c++">
+class person_sskel: public virtual serializer_complex_content
+{
+ ...
+};
+
+class employee_sskel: public virtual person_sskel
+{
+ ...
+};
+ </pre>
+
+
+ <p>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, <em>mixing in</em>
+ the base serializer implementation), for example:</p>
+
+ <pre class="c++">
+class person_simpl: public virtual person_sskel
+{
+ ...
+};
+
+class employee_simpl: public employee_sskel,
+ public person_simpl
+{
+ ...
+};
+ </pre>
+
+
+ <p>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:</p>
+
+ <pre class="c++">
+class person_sskel: public serializer_complex_content
+{
+ ...
+};
+
+class employee_sskel: public person_sskel
+{
+public:
+ employee_sskel (person_sskel* base_impl)
+
+ ...
+};
+ </pre>
+
+ <p>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
+ <code>0</code> 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
+ <code>person</code> and <code>employee</code> serializers
+ using the tiein style:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+ ...
+};
+
+class employee_simpl: public employee_sskel
+{
+public:
+ employee_simpl ()
+ : employee_sskel (&amp;base_impl_)
+ {
+ }
+
+ ...
+
+private:
+ person_simpl base_impl_;
+};
+ </pre>
+
+ <p>Note that you cannot use the <em>tied in</em> base serializer
+ instance (<code>base_impl_</code> in the above code) for
+ serializing anything except the derived type.</p>
+
+ <p>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 <code>age()</code> callback if we didn't
+ like the implementation provided by the base serializer:</p>
+
+ <pre class="c++">
+class employee_simpl: public employee_sskel
+{
+public:
+ employee_simpl ()
+ : employee_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual short
+ age ()
+ {
+ ...
+ }
+
+ ...
+
+private:
+ person_simpl base_impl_;
+};
+ </pre>
+
+ <p>In the above example the <code>age</code> element will be
+ handled by <code>emplyee_simpl</code> while the <code>first-name</code>
+ and <code>last-name</code> callbacks will still go to
+ <code>base_impl_</code>.</p>
+
+ <p>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:</p>
+
+
+ <pre class="c++">
+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&lt;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&lt;employee*> (person_)->position ();
+ }
+
+ virtual unsigned int
+ salary ()
+ {
+ return static_cast&lt;employee*> (person_)->salary ();
+ }
+};
+ </pre>
+
+ <h2><a name="6.7">6.7 Support for Polymorphism</a></h2>
+
+ <p>By default the XSD/e compiler generates non-polymorphic code. If your
+ vocabulary uses XML Schema polymorphism in the form of <code>xsi:type</code>
+ and/or substitution groups, then you will need to configure the XSD/e
+ runtime with support for polymorphism, compile your schemas with the
+ <code>--generate-polymorphic</code> option to produce polymorphism-aware
+ code, as well as pass <code>true</code> as the last argument to the
+ <code>xml_schema::document</code>'s constructors. If some of your
+ schemas do not require support for polymorphism then you can compile
+ them with the <code>--runtime-polymorphic</code> option and still
+ use the XSD/e runtime configured with polymorphism support.
+ </p>
+
+ <p>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:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="person" type="person"/>
+
+ &lt;xs:complexType name="superman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="person">
+ &lt;xs:attribute name="can-fly" type="xs:boolean"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="superman"
+ type="superman"
+ substitutionGroup="person"/>
+
+ &lt;xs:complexType name="batman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="superman">
+ &lt;xs:attribute name="wing-span" type="xs:unsignedInt"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="supermen">
+ &lt;xs:sequence>
+ &lt;xs:element ref="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="supermen" type="supermen"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Conforming XML documents can use the <code>superman</code>
+ and <code>batman</code> types in place of the <code>person</code>
+ type either by specifying the type with the <code>xsi:type</code>
+ attributes or by using the elements from the substitution
+ group, for instance:</p>
+
+ <pre class="xml">
+&lt;supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ &lt;person>
+ &lt;name>John Doe&lt;/name>
+ &lt;/person>
+
+ &lt;superman can-fly="false">
+ &lt;name>James "007" Bond&lt;/name>
+ &lt;/superman>
+
+ &lt;person can-fly="true" wing-span="10" xsi:type="batman">
+ &lt;name>Bruce Wayne&lt;/name>
+ &lt;/person>
+
+&lt;/supermen>
+ </pre>
+
+ <p>The C++ object model for this vocabulary might look as follows:</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum type_id
+{
+ person_type,
+ superman_type,
+ batman_type
+};
+
+class person
+{
+public:
+ virtual
+ ~person () {}
+
+ person (const std::string&amp; name)
+ : name_ (name)
+ {
+ }
+
+ const std::string&amp;
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string&amp; n)
+ {
+ name_ = n;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return person_type;
+ }
+
+private:
+ std::string name_;
+};
+
+class superman: public person
+{
+public:
+ superman (const std::string&amp; 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&amp; 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&lt;person*>
+{
+public:
+ ~supermen ()
+ {
+ for (iterator i = begin (); i != end (); ++i)
+ delete *i;
+ }
+};
+ </pre>
+
+ <p>Here we choose to provide our own type information. We can instead
+ use the standard C++ <code>typeid</code>/<code>type_info</code>
+ mechanism if it is available. The type map corresponding to this
+ object model is presented below. Notice that the <code>superman</code>
+ and <code>batman</code> objects are passed as a reference to
+ <code>person</code>:</p>
+
+ <pre>
+person "const ::person&amp;";
+superman "const ::person&amp;";
+batman "const ::person&amp;";
+supermen "const ::supermen&amp;";
+ </pre>
+
+ <p>The serializer implementations that serialize the above
+ C++ object model to XML are presented next:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (const person&amp; p)
+ {
+ person_ = &amp;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 (&amp;base_impl_)
+ {
+ }
+
+ virtual bool
+ can_fly ()
+ {
+ return superman_ ().can_fly ();
+ }
+
+ const superman&amp;
+ superman_ ()
+ {
+ return *static_cast&lt;const superman*> (base_impl_.person_);
+ }
+
+private:
+ person_simpl base_impl_;
+};
+
+class batman_simpl: public batman_sskel
+{
+public:
+ batman_simpl ()
+ : batman_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual unsigned int
+ wing_span ()
+ {
+ return batman_ ().wing_span ();
+ }
+
+ const batman&amp;
+ batman_ ()
+ {
+ return static_cast&lt;const batman&amp;> (base_impl_.superman_ ());
+ }
+
+private:
+ superman_simpl base_impl_;
+};
+
+class supermen_simpl: public supermen_sskel
+{
+public:
+ virtual void
+ pre (const supermen&amp; s)
+ {
+ supermen_ = &amp;s;
+ i_ = s.begin ();
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ != supermen_->end ();
+ }
+
+ virtual const ::person&amp;
+ person ()
+ {
+ const ::person&amp; p = **i_++;
+ xml_schema::serializer_context&amp; 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_;
+};
+ </pre>
+
+ <p>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 <code>person()</code> callback in the
+ <code>superman_simpl</code> 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 <code>_static_type()</code> function shortly).
+ The <code>type_id()</code> function from
+ <code>xml_schema::serializer_context</code> allows you to
+ specify optional type information which is used to look up
+ the corresponding serializer. Its argument is of type
+ <code>const void*</code> which allows you to pass
+ application-specific type information as an opaque pointer.</p>
+
+ <p>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 <code>person</code> element in the
+ <code>instance_s</code> serializer we specify a serializer map
+ instead of a specific serializer and we pass <code>true</code> as
+ the last argument to the document serializer constructor to indicate
+ that we are serializing potentially-polymorphic XML documents:</p>
+
+ <pre class="c++">
+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 ();
+}
+ </pre>
+
+ <p>When polymorphism-aware code is generated, each element's
+ <code>*_serializer()</code> function is overloaded to also accept
+ an object of the <code>xml_schema::serializer_map</code> type.
+ For example, the <code>supermen_sskel</code> class from the
+ above example looks like this:</p>
+
+ <pre class="c++">
+class supermen_sskel: public xml_schema::serializer_complex_content
+{
+public:
+
+ ...
+
+ // Serializer construction API.
+ //
+ void
+ serializers (person_sskel&amp;);
+
+ // Individual element serializers.
+ //
+ void
+ person_serializer (person_sskel&amp;);
+
+ void
+ person_serializer (xml_schema::serializer_map&amp;);
+
+ ...
+};
+ </pre>
+
+ <p>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 <code>type_id()</code> function
+ hasn't been called or the type information pointer is set to
+ <code>0</code>. 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:</p>
+
+ <pre class="c++">
+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);
+
+ ...
+}
+ </pre>
+
+
+ <p>The <code>xml_schema::serializer_map</code> interface and its
+ default implementation, <code>xml_schema::serializer_map_impl</code>,
+ are presented below:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ // This version of insert is a shortcut that uses the string
+ // returned by the serializer's _dynamic_type() function.
+ //
+ void
+ insert (serializer_base&amp;);
+
+ virtual serializer_base*
+ find (const void* type_id) const;
+
+ virtual void
+ reset () const;
+
+ private:
+ serializer_map_impl (const serializer_map_impl&amp;);
+
+ serializer_map_impl&amp;
+ operator= (const serializer_map_impl&amp;);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>type_id</code> argument in the <code>find()</code> virtual
+ function is the application-specific type information for the object
+ being serialized that is specified using the <code>type_id()</code>
+ function in the element callback. It is passed as an opaque
+ <code>const void*</code>. The <code>reset()</code> 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 <a href="#8.4">Section 8.4, "Reusing Serializers
+ after an Error"</a>.</p>
+
+ <p>The XSD/e runtime provided the default implementation for the
+ <code>xml_schema::serializer_map</code> interface,
+ <code>xml_schema::serializer_map_impl</code>, which uses a C string
+ (<code>const char*</code>) as type information. One way to
+ obtain a serializer's dynamic type in the form
+ <code>"&lt;name>&nbsp;&lt;namespace>"</code> with the space and the
+ namespace part absent if the type does not have a namespace
+ is to call the <code>_dynamic_type()</code> function on this
+ serializer. The static type can be obtained by calling the static
+ <code>_static_type()</code> function, for example
+ <code>person_sskel::_static_type()</code>. Both functions return
+ a C string (<code>const char*</code>) which is valid for as long
+ as the application is running.</p>
+
+ <p>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.
+ </p>
+
+ <p>If C++ exceptions are disabled (<a href="#5.3">Section 5.3,
+ "C++ Exceptions"</a>), the <code>xml_schema::serializer_map_impl</code>
+ class has the following additional error querying API. It can be used
+ to detect the out of memory errors after calls to the
+ <code>serializer_map_impl</code>'s constructor and <code>insert()</code>
+ functions.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_map_impl: public serializer_map
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ error
+ _error () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>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:</p>
+
+ <pre class="c++">
+#include &lt;map>
+
+class person_serializer_map: public xml_schema::serializer_map
+{
+public:
+ void
+ insert (person_sskel&amp; 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] = &amp;p;
+ }
+
+ virtual xml_schema::serializer_base*
+ find (const char* x) const
+ {
+ const person* p = static_cast&lt;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&lt;type_id, person_sskel*> map;
+ map map_;
+};
+ </pre>
+
+ <p>Our custom implementation of the serializer map expects that
+ we pass the actual object to the <code>find()</code> function.
+ To account for this will need to change the
+ <code>supermen_simpl::person()</code> callback as follows:</p>
+
+ <pre class="c++">
+ virtual const ::person&amp;
+ person ()
+ {
+ const ::person&amp; p = **i_++;
+ _context ().type_id (&amp;p);
+ return p;
+ }
+ </pre>
+
+
+ <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 (<a href="#5.4">Section 5.4,
+ "XML Schema Validation"</a>), 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:</p>
+
+ <pre class="c++">
+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 &lt;&lt; "substitution hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::serializer_smap_bucket_elements ();
+ load /= xml_schema::serializer_smap_bucket_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "substitution inner hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::serializer_imap_elements ();
+ load /= xml_schema::serializer_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "inheritance hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" &lt;&lt; endl;
+ }
+#endif
+
+ ...
+}
+ </pre>
+
+ <p>Most of the code presented in this section is taken from the
+ <code>polymorphism</code> example which can be found in the
+ <code>examples/cxx/serializer/</code> directory of the XSD/e distribution.
+ Handling of <code>xsi:type</code> and substitution groups when used
+ on root elements requires a number of special actions as shown in
+ the <code>polyroot</code> example.</p>
+
+ <h2><a name="6.8">6.8 A Minimal Example</a></h2>
+
+ <p>The following example is a re-implementation of the person
+ records example presented in <a href="#4">Chapter 4,
+ "Type Maps"</a>. It is intended to work without STL,
+ iostream, and C++ exceptions. It can be found in the
+ <code>examples/cxx/serializer/minimal/</code> directory of the
+ XSD/e distribution. The <code>people.xsd</code> schema is
+ compiled with the <code>--no-stl</code>, <code>--no-iostream</code>,
+ and <code>--no-exceptions</code> options. The object model
+ types in <code>people.hxx</code> have also been reimplemented
+ in order not to use STL types:</p>
+
+ <pre class="c++">
+#include &lt;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_;
+};
+ </pre>
+
+
+ <p>The following listing presents the implementation of serializer
+ skeletons and the test driver in full:</p>
+
+ <pre class="c++">
+#include &lt;stdio.h>
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;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&amp; p)
+ {
+ person_ = &amp;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&amp; p)
+ {
+ i_ = 0;
+ people_ = &amp;p;
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ &lt; people_->size_;
+ }
+
+ virtual const ::person&amp;
+ 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;
+}
+ </pre>
+
+
+ <!-- Built-in XML Schema Type Serializers -->
+
+
+ <h1><a name="7">7 Built-In XML Schema Type Serializers</a></h1>
+
+ <p>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.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Serializer implementation in the <code>xml_schema</code> namespace</th>
+ <th>Serializer argument type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">anyType and anySimpleType types</th>
+ </tr>
+ <tr>
+ <td><code>anyType</code></td>
+ <td><code>any_type_simpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+ <tr>
+ <td><code>anySimpleType</code></td>
+ <td><code>any_simple_type_simpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte_simpl</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte_simpl</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_simpl</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short_simpl</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_simpl</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int_simpl</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_simpl</code></td>
+ <td><code>long&nbsp;long</code> or <code>long</code><br/>
+ <a href="#6.5">Section 6.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long_simpl</code></td>
+ <td><code>unsigned&nbsp;long&nbsp;long</code> or
+ <code>unsigned&nbsp;long</code><br/>
+ <a href="#6.5">Section 6.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer_simpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer_simpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean_simpl</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_simpl</code></td>
+ <td><code>float</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_simpl</code></td>
+ <td><code>double</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal_simpl</code></td>
+ <td><code>double</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string-based types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname_simpl</code></td>
+ <td><code>const xml_schema::qname&amp;</code> or<br/>
+ <code>const xml_schema::qname*</code><br/>
+ <a href="#7.3">Section 7.3, "<code>QName</code> Serializer"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">list types</th>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens_simpl</code></td>
+ <td><code>const xml_schema::string_sequence*</code><br/><a href="#7.4">Section
+ 7.4, "<code>NMTOKENS</code> and <code>IDREFS</code> Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs_simpl</code></td>
+ <td><code>const xml_schema::string_sequence*</code><br/><a href="#7.4">Section
+ 7.4, "<code>NMTOKENS</code> and <code>IDREFS</code> Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary_simpl</code></td>
+ <td><code>const xml_schema::buffer*</code><br/>
+ <a href="#7.5">Section 7.5, "<code>base64Binary</code> and
+ <code>hexBinary</code> Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary_simpl</code></td>
+ <td><code>const xml_schema::buffer*</code><br/>
+ <a href="#7.5">Section 7.5, "<code>base64Binary</code> and
+ <code>hexBinary</code> Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date_simpl</code></td>
+ <td><code>const xml_schema::date&amp;</code><br/>
+ <a href="#7.7">Section 7.7, "<code>date</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time_simpl</code></td>
+ <td><code>const xml_schema::date_time&amp;</code><br/>
+ <a href="#7.8">Section 7.8, "<code>dateTime</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration_simpl</code></td>
+ <td><code>const xml_schema::duration&amp;</code><br/>
+ <a href="#7.9">Section 7.9, "<code>duration</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday_simpl</code></td>
+ <td><code>const xml_schema::gday&amp;</code><br/>
+ <a href="#7.10">Section 7.10, "<code>gDay</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth_simpl</code></td>
+ <td><code>const xml_schema::gmonth&amp;</code><br/>
+ <a href="#7.11">Section 7.11, "<code>gMonth</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day_simpl</code></td>
+ <td><code>const xml_schema::gmonth_day&amp;</code><br/>
+ <a href="#7.12">Section 7.12, "<code>gMonthDay</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear_simpl</code></td>
+ <td><code>const xml_schema::gyear&amp;</code><br/>
+ <a href="#7.13">Section 7.13, "<code>gYear</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month_simpl</code></td>
+ <td><code>const xml_schema::gyear_month&amp;</code><br/>
+ <a href="#7.14">Section 7.14, "<code>gYearMonth</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time_simpl</code></td>
+ <td><code>const xml_schema::time&amp;</code><br/>
+ <a href="#7.15">Section 7.15, "<code>time</code> Serializer"</a></td>
+ </tr>
+
+ </table>
+
+ <h2><a name="7.1">7.1 Floating-Point Type Serializers</a></h2>
+
+ <p>The serializer implementations for the <code>float</code>,
+ <code>double</code>, and <code>decimal</code> 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:</p>
+
+ <pre class="c++">
+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);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>By default the notation for the <code>float</code> and <code>double</code>
+ types is automatically selected to produce the shortest representation.
+ Note that the <code>decimal</code> values are always serialized in
+ the fixed-point notation.</p>
+
+ <h2><a name="7.2">7.2 String-Based Type Serializers</a></h2>
+
+ <p>When STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>), the serializer argument type for the <code>string</code>,
+ <code>normalizedString</code>, <code>token</code>,
+ <code>Name</code>, <code>NMTOKEN</code>, <code>NCName</code>,
+ <code>ID</code>, <code>IDREF</code>, <code>language</code>,
+ and <code>anyURI</code> built-in XML Schema types is
+ <code>const std::string&amp;</code>. When STL is disabled, the value
+ is passed as a constant C-string: <code>const char*</code>.
+ In this case, you can also instruct the serializer
+ implementations for string-based types to release the
+ string with operator <code>delete[]</code> by passing
+ <code>true</code> to their constructors. For instance,
+ using the person records example from the previous chapter:</p>
+
+ <pre class="c++">
+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);
+
+ ...
+}
+ </pre>
+
+ <h2><a name="7.3">7.3 <code>QName</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>qname_simpl</code> serializer
+ implementation is either <code>const xml_schema::qname&amp;</code>
+ when STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>) or <code>const xml_schema::qname*</code> when STL
+ is disabled. The <code>qname</code> class represents an XML
+ qualified name. When the argument type is <code>const
+ xml_schema::qname*</code>, you can optionally instruct the
+ serializer to release the <code>qname</code> object with operator
+ <code>delete</code> by passing <code>true</code> to its
+ constructor.</p>
+
+ <p>With STL enabled, the <code>qname</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#6.3">Section 6.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ 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&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="7.4">7.4 <code>NMTOKENS</code> and <code>IDREFS</code> Serializers</a></h2>
+
+ <p>The argument type of the <code>nmtokens_simpl</code> and
+ <code>idrefs_simpl</code> serializer implementations is
+ <code>const xml_schema::string_sequence*</code>. You can
+ optionally instruct these serializers to release the
+ <code>string_sequence</code> object with operator <code>delete</code>
+ by passing <code>true</code> to their constructors. With STL and C++ exceptions enabled
+ (<a href="#6.1">Section 6.1, "Standard Template Library"</a>,
+ <a href="#6.3">Section 6.3, "C++ Exceptions"</a>), the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp; reference;
+ typedef const std::string&amp; 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&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ std::string&amp;
+ front ();
+
+ const std::string&amp;
+ front () const;
+
+ std::string&amp;
+ back ();
+
+ const std::string&amp;
+ back () const;
+
+ std::string&amp;
+ operator[] (size_t);
+
+ const std::string&amp;
+ 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&amp;);
+
+ iterator
+ insert (iterator, const std::string&amp;);
+
+ void
+ reserve (size_t);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>When STL is enabled and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>insert()</code>, and
+ <code>reserve()</code> functions change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled, the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ 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&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new char[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. These two functions free the passed object if the reallocation
+ of the underlying sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ If you detach the underlying element string, then it should
+ eventually be deallocated with operator <code>delete[]</code>.</p>
+
+ <p>When both STL and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions change
+ as follows:</p>
+
+ <pre class="c++">
+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&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+
+ <h2><a name="7.5">7.5 <code>base64Binary</code> and <code>hexBinary</code> Serializers</a></h2>
+
+ <p>The argument type of the <code>base64_binary_simpl</code> and
+ <code>hex_binary_simpl</code> serializer implementations is
+ <code>const xml_schema::buffer*</code>. You can optionally
+ instruct these serializers to release the <code>buffer</code>
+ object with operator <code>delete</code> by passing <code>true</code>
+ to their constructors. With C++ exceptions enabled (<a href="#6.3">Section
+ 6.3, "C++ Exceptions"</a>), the <code>buffer</code> type has the
+ following interface:</p>
+
+ <pre class="c++">
+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&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ 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&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> type has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="7.6">7.6 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>xml_schema::time_zone</code> base class is used to represent
+ this information:</p>
+
+ <pre class="c++">
+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&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> modifier
+ function resets the time zone object to the <em>not specified</em>
+ state. If the time zone offset is negative then both hours and
+ minutes components are represented as negative integers.</p>
+
+ <h2><a name="7.7">7.7 <code>date</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>date_simpl</code> serializer implementation
+ is <code>const xml_schema::date&amp;</code>. The <code>date</code> 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
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="7.8">7.8 <code>dateTime</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>date_time_simpl</code> serializer
+ implementation is <code>const xml_schema::date_time&amp;</code>.
+ The <code>date_time</code> 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
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="7.9">7.9 <code>duration</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>duration_simpl</code> serializer
+ implementation is <code>const xml_schema::duration&amp;</code>.
+ The <code>duration</code> class represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+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&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="7.10">7.10 <code>gDay</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gday_simpl</code> serializer
+ implementation is <code>const xml_schema::gday&amp;</code> The
+ <code>gday</code> class represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="7.11">7.11 <code>gMonth</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gmonth_simpl</code> serializer
+ implementation is <code>const xml_schema::gmonth&amp;</code>. The
+ <code>gmonth</code> class represents a month of the year with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="7.12">7.12 <code>gMonthDay</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gmonth_day_simpl</code> serializer
+ implementation is <code>const xml_schema::gmonth_day&amp;</code>.
+ The <code>gmonth_day</code> 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 <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="7.13">7.13 <code>gYear</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gyear_simpl</code> serializer
+ implementation is <code>const xml_schema::gyear&amp;</code>. The
+ <code>gyear</code> class represents a year with an optional
+ time zone. Its interface is presented below. For more information
+ on the base <code>xml_schema::time_zone</code> class refer to
+ <a href="#7.6">Section 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="7.14">7.14 <code>gYearMonth</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gyear_month_simpl</code> serializer
+ implementation is <code>const xml_schema::gyear_month&amp;</code>.
+ The <code>gyear_month</code> class represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="7.15">7.15 <code>time</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>time_simpl</code> serializer implementation
+ is <code>const xml_schema::time&amp;</code>. The <code>time</code> class
+ represents hours, minutes, and seconds with an optional time zone. Its
+ interface is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+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&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+
+ <!-- Error Handling -->
+
+
+ <h1><a name="8">8 Document Serializer and Error Handling</a></h1>
+
+ <p>In this chapter we will discuss the <code>xml_schema::document_simpl</code>
+ type, the error handling mechanisms provided by the mapping, as well as
+ how to reuse a serializer after an error has occurred.</p>
+
+ <p>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.
+ </p>
+
+ <p>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 <a href="#6.3">Section 6.3, "C++ Exceptions"</a>.</p>
+
+ <h2><a name="8.1">8.1 Document Serializer</a></h2>
+
+ <p>The <code>xml_schema::document_simpl</code> serializer is a root
+ serializer for the vocabulary. As mentioned in <a href="#3.4">Section
+ 3.4, "Connecting the Serializer Together"</a>, its interface varies
+ depending on the mapping configuration (<a href="#6">Chapter 6, "Mapping
+ Configuration"</a>). When STL, C++ exceptions, and the iostream library
+ are enabled, the <code>xml_schema::document_simpl</code> class has the
+ following interface:</p>
+
+ <pre class="c++">
+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&amp;,
+ const char* root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const char* root_element_namespace,
+ const char* root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; 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&amp; prefix,
+ const std::string&amp; namespace_);
+
+ void
+ add_default_prefix (const std::string&amp; namespace_);
+
+ void
+ add_schema (const std::string&amp; namespace_,
+ const std::string&amp; location);
+
+ void
+ add_no_namespace_schema (const std::string&amp; 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&amp;);
+
+ public:
+ // Serialize by calling writer::write() and writer::flush() to
+ // output XML.
+ //
+ void
+ serialize (writer&amp;);
+
+ // 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);
+ };
+}
+ </pre>
+
+ <p>When the use of STL is disabled, the constructors, as well as
+ the <code>add_prefix()</code> and <code>add_schema()</code>
+ functions that use <code>std::string</code> in their signatures
+ are not available. When the use of iostream is disabled, the
+ <code>serialize()</code> functions that serializes to
+ <code>std::ostream</code> is not available.</p>
+
+ <p>When C++ exceptions are disabled, the <code>write()</code> and
+ <code>flush()</code> virtual functions in the <code>writer</code>
+ interface as well as <code>write_func</code>,
+ <code>write_bound_func</code>, and <code>flush_func</code>
+ function pointers use <code>bool</code> return type
+ for error reporting. These functions should return <code>true</code>
+ if the operation was successful and <code>false</code> otherwise.
+ The relevant parts in the <code>writer</code> and
+ <code>document_simpl</code> interfaces change as follows:</p>
+
+ <pre class="c++">
+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&amp;
+ _error () const;
+ };
+}
+ </pre>
+
+ <p>For more information on error handling with C++ exceptions and
+ error codes see <a href="#8.2">Section 8.2, "Exceptions"</a>
+ and <a href="#8.3">Section 8.3, "Error Codes"</a> below.</p>
+
+ <p>When support for XML Schema polymorphism is enabled, the
+ overloaded <code>document_simpl</code> constructors have
+ additional arguments which control polymorphic serialization.
+ For more information refer to <a href="#6.7">Section 6.7,
+ "Support for Polymorphism"</a>.
+ </p>
+
+ <p>The first argument to all overloaded constructors is the
+ serializer for the type of the root element. The
+ <code>serializer_base</code> class is the base type for all
+ serializer skeletons. The second and third arguments to the
+ <code>document_simpl</code>'s constructors are the root element's
+ name and namespace.</p>
+
+ <p>The <code>add_prefix()</code> and <code>add_default_prefix()</code>
+ 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:</p>
+
+ <pre class="c++">
+xml_schema::document_simpl doc_s (
+ root_s,
+ "http://www.example.com/example",
+ "root");
+
+doc_s.add_prefix ("ex", "http://www.example.com/example");
+ </pre>
+
+ <p>The resulting XML will have the following namespace declaration:</p>
+
+ <pre class="xml">
+&lt;ex:root xmlns:ex="http://www.example.com/example" ...>
+ ...
+&lt;/ex:root>
+ </pre>
+
+ <p>Similarly, the <code>add_schema()</code> and
+ <code>add_no_namespace_schema()</code> functions allow you to embed
+ schema location information for a particular namespace into resulting
+ XML. The schema location information is placed into the
+ <code>xsi:schemaLocation</code> and
+ <code>xsi:noNamespaceSchemaLocation</code> attributes. For example:</p>
+
+ <pre class="c++">
+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");
+ </pre>
+
+ <p>The resulting XML will have the following namespace declaration:</p>
+
+ <pre class="xml">
+&lt;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" ...>
+ ...
+&lt;/ex:root>
+ </pre>
+
+ <h2><a name="8.2">8.2 Exceptions</a></h2>
+
+ <p>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 <code>std::bad_alloc</code>. The stream operation errors
+ are reported by throwing an instance of
+ <code>std::ios_base::failure</code>.</p>
+
+ <p>The xml and schema errors are reported by throwing the
+ <code>xml_schema::serializer_xml</code> and
+ <code>xml_schema::serializer_schema</code>
+ exceptions, respectively. These two exceptions derive from
+ <code>xml_schema::serializer_exception</code> which, in turn, derives
+ from <code>std::exception</code>. As a result, you can handle
+ any error from these two categories by either catching
+ <code>std::exception</code>, <code>xml_schema::serializer_exception</code>,
+ 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:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_exception: public std::exception
+ {
+ public:
+ virtual const char*
+ text () const = 0;
+
+ ...
+ };
+
+ std::ostream&amp;
+ operator&lt;&lt; (std::ostream&amp;, const serializer_exception&amp;);
+
+
+ typedef &lt;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 &lt;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 ();
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>serializer_xml_error</code> and
+ <code>serializer_schema_error</code> are implementation-specific error
+ code types. The <code>operator&lt;&lt;</code> defined for the
+ <code>serializer_exception</code> class simply prints the error
+ description as returned by the <code>text()</code> function. The
+ following example shows how we can catch these exceptions:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ try
+ {
+ // Serialize.
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cout &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>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.</p>
+
+ <h2><a name="8.3">8.3 Error Codes</a></h2>
+
+ <p>When C++ exceptions are not available, error codes are used to
+ report error conditions. Each serializer skeleton and the root
+ <code>document_simpl</code> serializer have the following member
+ function for querying the error status:</p>
+
+ <pre class="c++">
+xml_schema::serializer_error
+_error () const;
+ </pre>
+
+ <p>To handle all possible error conditions, you will need to obtain
+ the error status after calls to: the <code>document_simpl</code>'s
+ constructor (it performs memory allocations which may fail),
+ calls to <code>add_prefix()</code> and <code>add_schema()</code>
+ functions if any, the call to the root serializer <code>pre()</code>
+ callback, the call to the <code>serialize()</code> function, and,
+ finally, the call to the root serializer <code>post()</code> callback.
+ The definition of <code>xml_schema::serializer_error</code> class
+ is presented below:</p>
+
+ <pre class="c++">
+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 &lt;implementation-details> serializer_xml_error;
+ typedef &lt;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;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>serializer_xml_error</code> and
+ <code>serializer_schema_error</code> are implementation-specific
+ error code types. The <code>serializer_error</code> class incorporates
+ four categories of errors which you can query by calling the
+ <code>type()</code> function. The following example shows how to
+ handle error conditions with error codes. It is based on the
+ person record example presented in <a href="#3">Chapter 3, "Serializer
+ Skeletons"</a>.</p>
+
+ <pre class="c++">
+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 &lt;&lt; "system error: " &lt;&lt; e.sys_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::xml:
+ {
+ cerr &lt;&lt; "xml error: " &lt;&lt; e.xml_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::schema:
+ {
+ cerr &lt;&lt; "schema error: " &lt;&lt; e.schema_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::app:
+ {
+ cerr &lt;&lt; "application error: " &lt;&lt; e.app_code () &lt;&lt; endl;
+ break;
+ }
+ }
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The error type for application errors is <code>int</code> with
+ the value <code>0</code> indicated the absence of error. You can
+ set the application error by calling the <code>_app_error()</code>
+ 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: </p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual short
+ age ()
+ {
+ short a = ...;
+
+ if (a &lt; 18)
+ _app_error (1);
+
+ return a;
+ }
+};
+ </pre>
+
+ <p>You can also set a system error by calling the <code>_sys_error()</code>
+ function inside a serializer callback. This function has one argument of
+ type <code>xml_schema::sys_error</code> which was presented above.
+ For example:</p>
+
+ <pre class="c++">
+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;
+ }
+};
+ </pre>
+
+ <h2><a name="8.4">8.4 Reusing Serializers after an Error</a></h2>
+
+ <p>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:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ ...
+
+ xml_schema::document_simpl doc_s (people_s, "people");
+
+ for (size_t i = 0; i &lt; 4; ++i)
+ {
+ try
+ {
+ people_s.pre ();
+ doc_s.serialize (cout);
+ people_s.post ();
+ }
+ catch (const xml_schema::serializer_exception&amp;)
+ {
+ doc_s.reset ();
+ }
+ }
+}
+ </pre>
+
+ <p>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 <code>--suppress-reset</code>
+ XSD/e compiler option.</p>
+
+ <p>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 <code>_reset()</code>
+ virtual function as shown below. Notice that when you override the
+ <code>_reset()</code> function in your implementation, you should
+ always call the base skeleton version to allow it to reset
+ its state:</p>
+
+<pre class="c++">
+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_;
+};
+ </pre>
+
+ <p>Note also that the <code>_reset()</code> 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 (<code>pre()</code> and <code>_pre()</code>) and
+ finalization (<code>post_*()</code> and <code>_post()</code>)
+ callbacks.</p>
+
+
+ <!-- Appendix A -->
+
+
+ <h1><a name="A">Appendix A &mdash; Supported XML Schema Constructs</a></h1>
+
+ <p>The Embedded C++/Serializer mapping supports validation of the following
+ W3C XML Schema constructs in the generated code.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="features" border="1">
+ <tr><th>Construct</th><th>Notes</th></tr>
+ <tr><th colspan="2">Structure</th></tr>
+
+ <tr><td>element</td><td></td></tr>
+ <tr><td>attribute</td><td></td></tr>
+
+ <tr><td>any</td><td></td></tr>
+ <tr><td>anyAttribute</td><td></td></tr>
+
+ <tr><td>all</td><td></td></tr>
+ <tr><td>sequence</td><td></td></tr>
+ <tr><td>choice</td><td></td></tr>
+
+ <tr><td>complex type, empty content</td><td></td></tr>
+ <tr><td>complex type, mixed content</td><td></td></tr>
+ <tr><td>complex type, simple content extension</td><td></td></tr>
+ <tr><td>complex type, simple content restriction</td>
+ <td>Simple type facets are not validated.</td></tr>
+ <tr><td>complex type, complex content extension</td><td></td></tr>
+ <tr><td>complex type, complex content restriction</td><td></td></tr>
+
+ <tr><td>list</td><td></td></tr>
+
+ <tr><th colspan="2">Datatypes</th></tr>
+
+ <tr><td>byte</td><td></td></tr>
+ <tr><td>unsignedByte</td><td></td></tr>
+ <tr><td>short</td><td></td></tr>
+ <tr><td>unsignedShort</td><td></td></tr>
+ <tr><td>int</td><td></td></tr>
+ <tr><td>unsignedInt</td><td></td></tr>
+ <tr><td>long</td><td></td></tr>
+ <tr><td>unsignedLong</td><td></td></tr>
+ <tr><td>integer</td><td></td></tr>
+ <tr><td>nonPositiveInteger</td><td></td></tr>
+ <tr><td>nonNegativeInteger</td><td></td></tr>
+ <tr><td>positiveInteger</td><td></td></tr>
+ <tr><td>negativeInteger</td><td></td></tr>
+
+ <tr><td>boolean</td><td></td></tr>
+
+ <tr><td>float</td><td></td></tr>
+ <tr><td>double</td><td></td></tr>
+ <tr><td>decimal</td><td></td></tr>
+
+ <tr><td>string</td><td></td></tr>
+ <tr><td>normalizedString</td><td></td></tr>
+ <tr><td>token</td><td></td></tr>
+ <tr><td>Name</td><td></td></tr>
+ <tr><td>NMTOKEN</td><td></td></tr>
+ <tr><td>NCName</td><td></td></tr>
+ <tr><td>language</td><td></td></tr>
+ <tr><td>anyURI</td><td></td></tr>
+
+ <tr><td>ID</td><td>Identity constraint is not enforced.</td></tr>
+ <tr><td>IDREF</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>NMTOKENS</td><td></td></tr>
+ <tr><td>IDREFS</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>QName</td><td></td></tr>
+
+ <tr><td>base64Binary</td><td></td></tr>
+ <tr><td>hexBinary</td><td></td></tr>
+
+ <tr><td>date</td><td></td></tr>
+ <tr><td>dateTime</td><td></td></tr>
+ <tr><td>duration</td><td></td></tr>
+ <tr><td>gDay</td><td></td></tr>
+ <tr><td>gMonth</td><td></td></tr>
+ <tr><td>gMonthDay</td><td></td></tr>
+ <tr><td>gYear</td><td></td></tr>
+ <tr><td>gYearMonth</td><td></td></tr>
+ <tr><td>time</td><td></td></tr>
+ </table>
+
+ </div>
+</div>
+
+
+</body>
+</html>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+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 <import namespace="..." schemaLocation="base.xsd"/>
+
+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 <string>;
+.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 <string>;
+.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 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>XSD/e 3.0.0 Compiler Command Line Manual</title>
+
+ <meta name="copyright" content="&copy; 2005-2009 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,code,generator,manual,man,page"/>
+ <meta name="description" content="XSD/e Compiler Command Line Manual"/>
+
+ <link rel="stylesheet" type="text/css" href="default.css" />
+
+<style type="text/css">
+
+ #synopsis {
+ list-style-type: none;
+ }
+
+ #synopsis li {
+ padding-top : 0.0em;
+ padding-bottom : 0.0em;
+ }
+
+ #commands dt {
+ padding-top : 0.4em;
+ }
+
+ #commands dd {
+ padding-bottom : 0.4em;
+ padding-left : 2em;
+ }
+
+ .options dt {
+ padding-top : 0.4em;
+ }
+
+ .options dd {
+ padding-top : 0.1em;
+ padding-bottom : 0.4em;
+ padding-left : 1.4em;
+ }
+
+</style>
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <h1>NAME</h1>
+
+ <p>xsde - W3C XML Schema to C++ Compiler for Embedded Systems</p>
+
+ <h1>SYNOPSIS</h1>
+
+ <dl id="synopsis">
+ <dt><code><b>xsde</b> <i>command</i> [<i>options</i>] <i>file</i> [<i>file</i> ...]</code></dt>
+ <dt><code><b>xsde help</b> [<i>command</i>]</code></dt>
+ <dt><code><b>xsde version</b></code></dt>
+ </dl>
+
+ <h1>DESCRIPTION</h1>
+
+ <p><code><b>xsde</b></code> generates vocabulary-specific, statically-typed
+ C++ mapping from W3C XML Schema definitions. Particular mapping to
+ produce is selected by a <code><i>command</i></code>. Each mapping has
+ a number of mapping-specific <code><i>options</i></code> that should
+ appear, if any, after the <code><i>command</i></code>. Input files should
+ be W3C XML Schema definitions. The exact set of the generated files
+ depends on the selected mapping and options.</p>
+
+ <h1>COMMANDS</h1>
+
+ <dl id="commands">
+ <dt><code><b>cxx-hybrid</b></code></dt>
+ <dd>Generate the Embedded C++/Hybrid mapping. For each input file in the
+ form <code><b>name.xsd</b></code> the following C++ files are generated:
+ <code><b>name.hxx</b></code> (object model header file),
+ <code><b>name.ixx</b></code> (object model inline file, generated only
+ if the <code><b>--generate-inline</b></code> option is specified),
+ <code><b>name.cxx</b></code> (object model source file), and
+ <code><b>name-fwd.hxx</b></code> (object model forward declaration
+ file, generated only if the <code><b>--generate-forward</b></code>
+ option is specified).
+
+ <p>If the <code><b>--generate-parser</b></code> option is specified,
+ the Embedded C++/Parser mapping is invoked and the
+ <code><b>name-pskel.hxx</b></code>,
+ <code><b>name-pskel.ixx</b></code>, and
+ <code><b>name-pskel.cxx</b></code> parser skeleton files are
+ generated, as described below. Additionally, the following parser
+ implementation files are generated:
+ <code><b>name-pimpl.hxx</b></code> (parser implementation header
+ file) and
+ <code><b>name-pimpl.cxx</b></code> (parser implementation source
+ file).</p>
+
+ <p>If the <code><b>--generate-serializer</b></code> option is
+ specified, the Embedded C++/Serializer mapping is invoked and the
+ <code><b>name-sskel.hxx</b></code>,
+ <code><b>name-sskel.ixx</b></code>, and
+ <code><b>name-sskel.cxx</b></code> serializer skeleton files are
+ generated, as described below. Additionally, the following serializer
+ implementation files are generated:
+ <code><b>name-simpl.hxx</b></code> (serializer implementation header
+ file) and
+ <code><b>name-simpl.cxx</b></code> (serializer implementation source
+ file).</p>
+ </dd>
+
+ <dt><code><b>cxx-parser</b></code></dt>
+ <dd>Generate the Embedded C++/Parser mapping. For each input file in the
+ form <code><b>name.xsd</b></code> the following C++ files are generated:
+ <code><b>name-pskel.hxx</b></code> (parser skeleton header file),
+ <code><b>name-pskel.ixx</b></code> (parser skeleton inline file,
+ generated only if the <code><b>--generate-inline</b></code>
+ option is specified), and
+ <code><b>name-pskel.cxx</b></code> (parser skeleton source file).
+ If the <code><b>--generate-noop-impl</b></code> or
+ <code><b>--generate-print-impl</b></code> option is specified,
+ the following additional sample implementation files are generated:
+ <code><b>name-pimpl.hxx</b></code> (parser implementation header
+ file) and
+ <code><b>name-pimpl.cxx</b></code> (parser implementation source
+ file). If the <code><b>--generate-test-driver</b></code> option
+ is specified, the additional <code><b>name-pdriver.cxx</b></code>
+ test driver file is generated.</dd>
+
+ <dt><code><b>cxx-serializer</b></code></dt>
+ <dd>Generate the Embedded C++/Serializer mapping. For each input file
+ in the form <code><b>name.xsd</b></code> the following C++ files
+ are generated: <code><b>name-sskel.hxx</b></code> (serializer
+ skeleton header file), <code><b>name-sskel.ixx</b></code> (serializer
+ skeleton inline file, generated only if the
+ <code><b>--generate-inline</b></code> option is specified), and
+ <code><b>name-sskel.cxx</b></code> (serializer skeleton source file).
+ If the <code><b>--generate-empty-impl</b></code> option is specified,
+ the following additional sample implementation files are generated:
+ <code><b>name-simpl.hxx</b></code> (serializer implementation header
+ file) and <code><b>name-simpl.cxx</b></code> (serializer
+ implementation source file). If the <code><b>--generate-test-driver</b></code>
+ option is specified, the additional <code><b>name-sdriver.cxx</b></code>
+ test driver file is generated.
+ </dd>
+
+ <dt><code><b>help</b></code></dt>
+ <dd>Print usage information and exit. Use
+ <p><code><b>xsde help</b> <i>command</i></code></p>
+ for command-specific help.
+ </dd>
+
+ <dt><code><b>version</b></code></dt>
+ <dd>Print version and exit.</dd>
+ </dl>
+
+ <h1>OPTIONS</h1>
+
+ <p>Command-specific <code><i>options</i></code>, if any, should appear
+ after the corresponding <code><i>command</i></code>.</p>
+
+ <h2>COMMON OPTIONS</h2>
+
+ <dl class="options">
+ <dt><code><b>--output-dir</b> <i>dir</i></code></dt>
+ <dd>Write generated files to <code><i>dir</i></code> instead of
+ the current directory.</dd>
+
+ <dt><code><b>--no-stl</b></code></dt>
+ <dd>Generate code that does not use the Standard Template Library
+ (STL).</dd>
+
+ <dt><code><b>--no-iostream</b></code></dt>
+ <dd>Generate code that does not use the standard input/output
+ stream library (iostream).</dd>
+
+ <dt><code><b>--no-exceptions</b></code></dt>
+ <dd>Generate code that does not use C++ exceptions.</dd>
+
+ <dt><code><b>--no-long-long</b></code></dt>
+ <dd>Generate code that does not use the <code><b>long long</b></code>
+ and <code><b>unsigned long long</b></code> types. The
+ 64 bit <code><b>long</b></code> and <code><b>unsignedLong</b></code>
+ built-in XML Schema types are then mapped to <code><b>long</b></code>
+ and <code><b>unsigned long</b></code>.</dd>
+
+ <dt><code><b>--generate-inline</b></code></dt>
+ <dd>Generate simple functions inline. This option triggers creation
+ of the inline file.</dd>
+
+ <dt><code><b>--namespace-map</b> <i>xns</i><b>=</b><i>cns</i></code></dt>
+ <dd>Map XML Schema namespace <i>xns</i> to C++ namespace <i>cns</i>.
+ Repeat this option to specify mapping for more than one XML Schema
+ namespace. For example, the following option:
+
+ <p><code><b>--namespace-map http://example.com/foo/bar=foo::bar</b></code></p>
+
+ <p>will map the <code><b>http://example.com/foo/bar</b></code>
+ XML Schema namespace to the <code><b>foo::bar</b></code> C++
+ namespace.</p>
+ </dd>
+
+ <dt><code><b>--namespace-regex</b> <i>regex</i></code></dt>
+ <dd>Add <code><i>regex</i></code> to the list of regular expressions
+ used to translate XML Schema namespace names to C++ namespace
+ names. <code><i>regex</i></code> is a perl-like regular expression in
+ the form <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ Any character can be used as a delimiter instead of <code><b>/</b></code>.
+ Escaping of the delimiter character in <code><i>pattern</i></code> or
+ <code><i>replacement</i></code> is not supported.
+
+ <p>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</p>
+
+ <p><code><i>filename</i> <i>namespace</i></code></p>
+
+ <p>For example,</p>
+
+ <p><code><b>XMLSchema.xsd http://www.w3.org/2001/XMLSchema</b></code></p>
+
+ <p>The <code><i>filename</i></code> for the current translation unit
+ is empty. For example, if you have file <code><b>hello.xsd</b></code>
+ with namespace <code><b>http://example.com/hello</b></code> and you run
+ <code><b>xsde</b></code> on this file, then the string in question
+ would be:</p>
+
+ <p><code>&nbsp;<b>http://example.com/hello</b></code></p>
+
+ <p>Note the leading space.</p>
+
+ <p>The following three steps are performed for each regular expression
+ until the match is found:</p>
+
+ <ol>
+ <li>The expression is applied and if the result is empty the
+ next expression is considered.</li>
+
+ <li>All <code><b>/</b></code> are replaced with
+ <code><b>::</b></code>.</li>
+
+ <li>The result is verified to be a valid C++ scope name (e.g.,
+ <code><b>foo::bar</b></code>). If this test succeeds, the
+ result is used as a C++ namespace name.</li>
+ </ol>
+
+ <p>As an example, the following expression maps XML Schema
+ namespaces in the form
+ <code><b>http://example.com/foo/bar</b></code> to C++
+ namespaces in the form <code><b>foo::bar</b></code>:</p>
+
+ <p><code><b>%.* http://example.com/(.+)%$1%</b></code></p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--namespace-regex-trace</b></code></dt>
+ <dd>Trace the process of applying regular expressions specified with
+ the <code><b>--namespace-regex</b></code> option. Use this option
+ to find out why your regular expressions don't do what you expected
+ them to do.
+ </dd>
+
+ <!-- Reserved names -->
+
+ <dt><code><b>--reserved-name</b> <i>name</i>[<b>=</b><i>rep</i>]</code></dt>
+ <dd>Add <code><i>name</i></code> to the list of names that should not
+ be used as identifiers. The name can optionally be followed by
+ <code><b>=</b></code> and the replacement name that should be
+ used instead. All C++ keywords are already in this list.
+ </dd>
+
+ <dt><code><b>--include-with-brackets</b></code></dt>
+ <dd>Use angle brackets (&lt;&gt;) instead of quotes ("") in
+ generated <code><b>#include</b></code> directives.
+ </dd>
+
+ <dt><code><b>--include-prefix</b> <i>prefix</i></code></dt>
+ <dd>Add <code><i>prefix</i></code> to generated <code><b>#include</b></code>
+ directive paths.
+
+ <p>For example, if you had the following import element in your
+ schema</p>
+
+ <p><code><b>&lt;import namespace="..." schemaLocation="base.xsd"/&gt;</b></code></p>
+
+ <p>and compiled this fragment with <code><b>--include-prefix schemas/</b></code>,
+ then the include directive in the generated code would be:</p>
+
+ <p><code><b>#include "schemas/base.hxx"</b></code></p>
+ </dd>
+
+ <dt><code><b>--include-regex</b> <i>regex</i></code></dt>
+ <dd>Add <code><i>regex</i></code> to the list of regular expressions
+ used to transform <code><b>#include</b></code> directive paths.
+ <code><i>regex</i></code> is a perl-like regular expression in
+ the form <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ Any character can be used as a delimiter instead of <code><b>/</b></code>.
+ Escaping of the delimiter character in <code><i>pattern</i></code> or
+ <code><i>replacement</i></code> is not supported.
+
+ <p>All regular expressions are pushed into a stack with the last
+ specified expression considered first. The first match that
+ succeeds is used.</p>
+
+ <p>As an example, the following expression transforms paths
+ in the form <code><b>schemas/foo/bar</b></code> to paths
+ in the form <code><b>generated/foo/bar</b></code>:</p>
+
+ <p><code><b>%schemas/(.+)%generated/$1%</b></code></p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--include-regex-trace</b></code></dt>
+ <dd>Trace the process of applying regular expressions specified with
+ the <code><b>--include-regex</b></code> option. Use this option
+ to find out why your regular expressions don't do what you expected
+ them to do.
+ </dd>
+
+ <dt><code><b>--guard-prefix</b> <i>prefix</i></code></dt>
+ <dd>Add <code><i>prefix</i></code> 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.
+ </dd>
+
+ <dt><code><b>--hxx-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the default
+ <code><b>.hxx</b></code> to construct the name of the header file.
+ Note that this suffix is also used to construct names for
+ included/imported schemas.
+ </dd>
+
+ <dt><code><b>--ixx-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the default
+ <code><b>.ixx</b></code> to construct the name of the inline file.
+ </dd>
+
+ <dt><code><b>--cxx-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the default
+ <code><b>.cxx</b></code> to construct the name of the source file.
+ </dd>
+
+ <dt><code><b>--fwd-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the default
+ <code><b>-fwd.hxx</b></code> to construct the name of the forward
+ declaration file (C++/Hybrid mapping only).
+ </dd>
+
+ <dt><code><b>--hxx-regex</b> <i>regex</i></code></dt>
+ <dd>Use the provided expression to construct the name of the header
+ file. <code><i>regex</i></code> is a perl-like regular expression
+ in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ This expression is also used to construct names for included/imported
+ schemas.
+
+ <p>
+ For the C++/Hybrid mapping, the <code><i>regex</i></code> argument
+ can be optionally prefixed with a file key in the form
+ <code><i>key</i>=<i>regex</i></code>. The valid values for
+ <code><i>key</i></code> are <code><b>pskel</b></code> (parser
+ skeleton files), <code><b>pimpl</b></code> (parser implementation
+ files), <code><b>sskel</b></code> (serializer skeleton files),
+ <code><b>simpl</b></code> (serializer implementation files),
+ and <code><b>*</b></code> (all files). If <code><i>key</i></code>
+ is empty or not present then the expression is used for the
+ object model files only.
+ </p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--ixx-regex</b> <i>regex</i></code></dt>
+ <dd>Use the provided expression to construct the name of the inline
+ file. <code><i>regex</i></code> is a perl-like regular expression
+ in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ For the C++/Hybrid mapping, the <code><i>regex</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-regex</b></code> option for details.
+ See also the REGEX AND SHELL QUOTING section below.
+ </dd>
+
+ <dt><code><b>--cxx-regex</b> <i>regex</i></code></dt>
+ <dd>Use the provided expression to construct the name of the source
+ file. <code><i>regex</i></code> is a perl-like regular expression
+ in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ For the C++/Hybrid mapping, the <code><i>regex</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-regex</b></code> option for details.
+ See also the REGEX AND SHELL QUOTING section below.
+ </dd>
+
+ <dt><code><b>--fwd-regex</b> <i>regex</i></code></dt>
+ <dd>Use the provided expression to construct the name of the forward
+ declaration file (C++/Hybrid mapping only). <code><i>regex</i></code>
+ is a perl-like regular expression in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ See also the REGEX AND SHELL QUOTING section below.
+ </dd>
+
+ <!-- prologue options -->
+
+ <dt><code><b>--hxx-prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of the header file.
+
+ <p>
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key in the form
+ <code><i>key</i>=<i>text</i></code>. The valid values for
+ <code><i>key</i></code> are <code><b>pskel</b></code> (parser
+ skeleton files), <code><b>pimpl</b></code> (parser implementation
+ files), <code><b>sskel</b></code> (serializer skeleton files),
+ <code><b>simpl</b></code> (serializer implementation files),
+ and <code><b>*</b></code> (all files). If <code><i>key</i></code>
+ is empty or not present then the text is used for the
+ object model files only.
+ </p>
+
+ </dd>
+
+ <dt><code><b>--ixx-prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of the inline file.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--cxx-prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of the source file.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--fwd-prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of the forward
+ declaration file (C++/Hybrid mapping only).
+ </dd>
+
+ <dt><code><b>--prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of each generated
+ file for which there is no file-specific prologue.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <!-- epilogue options -->
+
+ <dt><code><b>--hxx-epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of the header file.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--ixx-epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of the inline file.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--cxx-epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of the source file.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--fwd-epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of the forward
+ declaration file (C++/Hybrid mapping only).
+ </dd>
+
+ <dt><code><b>--epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of each generated
+ file for which there is no file-specific epilogue.
+ For the C++/Hybrid mapping, the <code><i>text</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue</b></code> option for details.
+ </dd>
+
+ <!-- prologue file options -->
+
+ <dt><code><b>--hxx-prologue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the beginning
+ of the header file.
+
+ <p>
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key in the form
+ <code><i>key</i>=<i>file</i></code>. The valid values for
+ <code><i>key</i></code> are <code><b>pskel</b></code> (parser
+ skeleton files), <code><b>pimpl</b></code> (parser implementation
+ files), <code><b>sskel</b></code> (serializer skeleton files),
+ <code><b>simpl</b></code> (serializer implementation files),
+ and <code><b>*</b></code> (all files). If <code><i>key</i></code>
+ is empty or not present then the file is used for the
+ object model files only.
+ </p>
+ </dd>
+
+ <dt><code><b>--ixx-prologue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the beginning
+ of the inline file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--cxx-prologue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the beginning
+ of the source file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--fwd-prologue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the beginning
+ of the forward declaration file (C++/Hybrid mapping only).
+ </dd>
+
+ <dt><code><b>--prologue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the beginning
+ of each generated file for which there is no file-specific prologue
+ file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <!-- epilogue file options -->
+
+ <dt><code><b>--hxx-epilogue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the end of the
+ header file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--ixx-epilogue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the end of the
+ inline file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--cxx-epilogue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the end of the
+ source file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+ <dt><code><b>--fwd-epilogue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the end of the
+ forward declaration file (C++/Hybrid mapping only).
+ </dd>
+
+ <dt><code><b>--epilogue-file</b> <i>file</i></code></dt>
+ <dd>Insert the content of the <code><i>file</i></code> at the end of each
+ generated file for which there is no file-specific epilogue file.
+ For the C++/Hybrid mapping, the <code><i>file</i></code> argument
+ can be optionally prefixed with a file key. See the
+ <code><b>--hxx-prologue-file</b></code> option for details.
+ </dd>
+
+
+ <dt><code><b>--disable-warning</b> <i>warn</i></code></dt>
+ <dd>Disable printing warning with id <i>warn</i>. If <code><b>all</b></code>
+ is specified for the warning id then all warnings are disabled.
+ </dd>
+
+ <!-- misc options -->
+
+ <dt><code><b>--show-sloc</b></code></dt>
+ <dd>Show the number of generated physical source lines of code (SLOC).
+ </dd>
+
+ <dt><code><b>--sloc-limit</b> <i>num</i></code></dt>
+ <dd>Check that the number of generated physical source lines of code
+ (SLOC) does not exceed <code><i>num</i></code>.
+ </dd>
+
+ <dt><code><b>--options-file</b> <i>file</i></code></dt>
+ <dd>Read additional options from <code><i>file</i></code>. Each option
+ should appear on a separate line optionally followed by space and
+ an argument. Empty lines and lines starting with <code><b>#</b></code>
+ 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
+ <code><b>--options-file</b></code> option is specified
+ except that shell escaping and quoting is not required.
+ Repeat this option to specify more than one options files.
+ </dd>
+
+ <dt><code><b>--proprietary-license</b></code></dt>
+ <dd>Indicate that the generated code is licensed under a proprietary
+ license instead of the GPL.
+ </dd>
+
+ <!-- Anonymous options. -->
+
+ <dt><code><b>--preserve-anonymous</b></code></dt>
+ <dd>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.
+ </dd>
+
+ <dt><code><b>--show-anonymous</b></code></dt>
+ <dd>Show elements and attributes that are of anonymous types.
+ This option only makes sense together with the
+ <code><b>--preserve-anonymous</b></code> option.
+ </dd>
+
+ <dt><code><b>--anonymous-regex</b> <i>regex</i></code></dt>
+ <dd>Add <code><i>regex</i></code> to the list of regular expressions
+ used to derive names for anonymous types from the enclosing
+ attributes/elements. <code><i>regex</i></code> is a perl-like regular
+ expression in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ Any character can be used as a delimiter instead of <code><b>/</b></code>.
+ Escaping of the delimiter character in <code><i>pattern</i></code> or
+ <code><i>replacement</i></code> is not supported.
+
+ <p>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</p>
+
+ <p><code><i>filename</i> <i>namespace</i> <i>xpath</i></code></p>
+
+ <p>For example,</p>
+
+ <p><code><b>hello.xsd http://example.com/hello element</b></code></p>
+ <p><code><b>hello.xsd http://example.com/hello type/element</b></code></p>
+
+ <p>The <code><i>filename</i></code> for the current translation unit
+ is empty. For example, if you have file <code><b>hello.xsd</b></code>
+ with namespace <code><b>http://example.com/hello</b></code> and you run
+ <code><b>xsde</b></code> on this file, then the string in question
+ would be:</p>
+
+ <p><code>&nbsp;<b>http://example.com/hello element</b></code></p>
+
+ <p>Note the leading space.</p>
+
+ <p>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:</p>
+
+ <p><code><b>%.* .* (.+/)*(.+)%\u$2%</b></code></p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--anonymous-regex-trace</b></code></dt>
+ <dd>Trace the process of applying regular expressions specified with
+ the <code><b>--anonymous-regex</b></code> option. Use this option
+ to find out why your regular expressions don't do what you expected
+ them to do.
+ </dd>
+
+ <!-- Location mapping options. -->
+
+ <dt><code><b>--location-map</b> <i>ol</i><b>=</b><i>nl</i></code></dt>
+ <dd>Map the original schema location <i>ol</i> that is specified in
+ the XML Schema include or import elements to new schema
+ location <i>nl</i>. Repeat this option to map more than one
+ schema location. For example, the following option maps the
+ <code><b>http://example.com/foo.xsd</b></code> URL to the
+ <code><b>foo.xsd</b></code> local file.
+
+ <p><code><b>--location-map http://example.com/foo.xsd=foo.xsd</b></code></p>
+ </dd>
+
+ <dt><code><b>--location-regex</b> <i>regex</i></code></dt>
+ <dd>Add <code><i>regex</i></code> to the list of regular expressions
+ used to map schema locations that are specified in the XML Schema
+ include or import elements. <code><i>regex</i></code> is a perl-like
+ regular expression in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ Any character can be used as a delimiter instead of <code><b>/</b></code>.
+ Escaping of the delimiter character in <code><i>pattern</i></code> or
+ <code><i>replacement</i></code> 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.
+
+ <p>For example, the following expression maps URL locations in the form
+ <code><b>http://example.com/foo/bar.xsd</b></code> to local files
+ in the form <code><b>bar.xsd</b></code>:</p>
+
+ <p><code><b>%http://.+/(.+)%$1%</b></code></p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--location-regex-trace</b></code></dt>
+ <dd>Trace the process of applying regular expressions specified with
+ the <code><b>--location-regex</b></code> option. Use this option
+ to find out why your regular expressions don't do what you expected
+ them to do.
+ </dd>
+
+ <!-- File-per-type compilation mode options. -->
+
+ <dt><code><b>--file-per-type</b></code></dt>
+ <dd>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.
+ </dd>
+
+
+ <dt><code><b>--type-file-regex</b> <i>regex</i></code></dt>
+ <dd>Add <code><i>regex</i></code> to the list of regular expressions
+ used to translate type names to file names when the
+ <code><b>--type-per-file</b></code> option is specified.
+ <code><i>regex</i></code> is a perl-like regular expression in the form
+ <code><b>/</b><i>pattern</i><b>/</b><i>replacement</i><b>/</b></code>.
+ Any character can be used as a delimiter instead of <code><b>/</b></code>.
+ Escaping of the delimiter character in <code><i>pattern</i></code> or
+ <code><i>replacement</i></code> 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
+
+ <p><code><i>namespace</i> <i>type-name</i></code></p>
+
+ <p>For example, the following expression maps type <code><b>foo</b></code>
+ that is defined in the <code><b>http://example.com/bar</b></code>
+ namespace to file name <code><b>bar-foo</b></code>:</p>
+
+ <p><code><b>%http://example.com/(.+) (.+)%$1-$2%</b></code></p>
+
+ <p>See also the REGEX AND SHELL QUOTING section below.</p>
+ </dd>
+
+ <dt><code><b>--type-file-regex-trace</b></code></dt>
+ <dd>Trace the process of applying regular expressions specified with
+ the <code><b>--type-file-regex</b></code> option. Use this option
+ to find out why your regular expressions don't do what you expected
+ them to do.
+ </dd>
+
+ <!-- File list options. -->
+
+ <dt><code><b>--file-list</b> <i>file</i></code></dt>
+ <dd>Write a list of generated C++ files to <code><i>file</i></code>.
+ This option is primarily useful in the file-per-type compilation
+ mode (<code><b>--file-per-type</b></code>) to create a list of
+ generated C++ files, for example, as a makefile fragment.
+ </dd>
+
+ <dt><code><b>--file-list-prologue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the beginning of the file list.
+ As a convenience, all occurrences of the \n character sequence in
+ <code><i>text</i></code> are replaced with new lines. This option
+ can, for example, be used to assign the generated file list to a
+ makefile variable.
+ </dd>
+
+ <dt><code><b>--file-list-epilogue</b> <i>text</i></code></dt>
+ <dd>Insert <code><i>text</i></code> at the end of the file list.
+ As a convenience, all occurrences of the \n character sequence in
+ <code><i>text</i></code> are replaced with new lines.
+ </dd>
+
+ <dt><code><b>--file-list-delim</b> <i>text</i></code></dt>
+ <dd>Delimit file names written to the file list with
+ <code><i>text</i></code> instead of new lines. As a convenience,
+ all occurrences of the \n character sequence in
+ <code><i>text</i></code> are replaced with new lines.
+ </dd>
+
+ </dl>
+
+ <h2>CXX-HYBRID COMMAND OPTIONS</h2>
+
+ <dl class="options">
+ <dt><code><b>--generate-parser</b></code></dt>
+ <dd>Generate XML parsing code.</dd>
+
+ <dt><code><b>--generate-serializer</b></code></dt>
+ <dd>Generate XML serialization code.</dd>
+
+ <dt><code><b>--generate-aggregate</b></code></dt>
+ <dd>Generate parser/serializer aggregates for root elements and/or
+ types. See also the <code><b>--root-element-*</b></code> and
+ <code><b>--root-type</b></code> options.</dd>
+
+ <dt><code><b>--suppress-validation</b></code></dt>
+ <dd>Suppress the generation of validation code in parser and serializer.</dd>
+
+ <dt><code><b>--suppress-parser-val</b></code></dt>
+ <dd>Suppress the generation of validation code in parser.</dd>
+
+ <dt><code><b>--suppress-serializer-val</b></code></dt>
+ <dd>Suppress the generation of validation code in serializer.</dd>
+
+ <dt><code><b>--generate-forward</b></code></dt>
+ <dd>Generate forward declaration file.</dd>
+
+ <dt><code><b>--generate-xml-schema</b></code></dt>
+ <dd>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
+ <code><b>--extern-xml-schema</b></code> option to include these file
+ in the generated files for other schemas.</dd>
+
+ <dt><code><b>--extern-xml-schema</b> <i>file</i></code></dt>
+ <dd>Include header files derived from <i>file</i> 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 <code><b>--generate-xml-schema</b></code>
+ option to generate these header files.</dd>
+
+ <dt><code><b>--suppress-reset</b></code></dt>
+ <dd>Suppress the generation of parser and serializer reset code.
+ Reset support allows you to reuse parsers and serializers
+ after an error.</dd>
+
+ <dt><code><b>--reuse-style-mixin</b></code></dt>
+ <dd>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.</dd>
+
+
+ <dt><code><b>--custom-data</b></code> <i>type</i></dt>
+ <dd>Add the ability to store custom data to the C++ class generated
+ for XML Schema type <code><i>type</i></code>. To add custom
+ data to a nested compositor class use the qualified name
+ starting from the XML Schema type containing the compositor,
+ for example, <code><b>foo::sequence::choise1</b></code>.</dd>
+
+ <dt><code><b>--custom-parser</b>
+ <i>type</i>[<b>=</b><i>base</i>[<b>/</b><i>include</i>]]</code></dt>
+ <dd>Use a custom parser implementation instead of the generated version.
+ The <code><i>type</i></code> component is the XML Schema type name
+ being customized. Optional <code><i>base</i></code> is a C++ name
+ that should be given to the generated version. It is normally used
+ as a base for the custom implementation. Optional
+ <code><i>include</i></code> is the header file that defines the
+ custom implementation. It is <code><b>#include</b></code>'ed
+ into the generated code immediately after (if <code><i>base</i></code>
+ is specified) or instead of the generated version.</dd>
+
+ <dt><code><b>--custom-serializer</b>
+ <i>type</i>[<b>=</b><i>base</i>[<b>/</b><i>include</i>]]</code></dt>
+ <dd>Use a custom serializer implementation instead of the generated version.
+ The <code><i>type</i></code> component is the XML Schema type name
+ being customized. Optional <code><i>base</i></code> is a C++ name
+ that should be given to the generated version. It is normally used
+ as a base for the custom implementation. Optional
+ <code><i>include</i></code> is the header file that defines the
+ custom implementation. It is <code><b>#include</b></code>'ed
+ into the generated code immediately after (if <code><i>base</i></code>
+ is specified) or instead of the generated version.</dd>
+
+ <!-- Root element/type. -->
+
+ <dt><code><b>--root-element-first</b></code></dt>
+ <dd>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 <code><b>--generate-aggregate</b></code>
+ option.
+ </dd>
+
+ <dt><code><b>--root-element-last</b></code></dt>
+ <dd>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 <code><b>--generate-aggregate</b></code>
+ option.
+ </dd>
+
+ <dt><code><b>--root-element-all</b></code></dt>
+ <dd>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
+ <code><b>--generate-aggregate</b></code> option.
+ </dd>
+
+ <dt><code><b>--root-element-none</b></code></dt>
+ <dd>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 <code><b>--generate-aggregate</b></code>
+ option.
+ </dd>
+
+ <dt><code><b>--root-element</b> <i>element</i></code></dt>
+ <dd>Treat only <code><i>element</i></code> 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 <code><b>--generate-aggregate</b></code> option.
+ </dd>
+
+ <dt><code><b>--root-type</b> <i>type</i></code></dt>
+ <dd>Generate parser/serializer aggregate for <code><i>type</i></code>.
+ Repeat this option to specify more than one type. See also the
+ <code><b>--generate-aggregate</b></code> option.</dd>
+
+ <dt><code><b>--pskel-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_pskel</b></code> to construct the names of generated parser
+ skeletons.</dd>
+
+ <dt><code><b>--sskel-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_sskel</b></code> to construct the names of generated
+ serializer skeletons.</dd>
+
+ <dt><code><b>--pskel-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>-pskel</b></code> to construct the names of generated
+ parser skeleton files.</dd>
+
+ <dt><code><b>--sskel-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>-sskel</b></code> to construct the names of generated
+ serializer skeleton files.</dd>
+
+ <dt><code><b>--pimpl-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_pimpl</b></code> to construct the names of generated
+ parser implementations.</dd>
+
+ <dt><code><b>--simpl-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_simpl</b></code> to construct the names of generated
+ serializer implementations.</dd>
+
+ <dt><code><b>--pimpl-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>-pimpl</b></code> to construct the names of generated
+ parser implementation files.</dd>
+
+ <dt><code><b>--simpl-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>-simpl</b></code> to construct the names of generated
+ serializer implementation files.</dd>
+
+ <dt><code><b>--paggr-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_paggs</b></code> to construct the names of generated
+ parser aggregates.</dd>
+
+ <dt><code><b>--saggr-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use <code><i>suffix</i></code> instead of the default
+ <code><b>_saggr</b></code> to construct the names of generated
+ serializer aggregates.</dd>
+ </dl>
+
+ <h2>CXX-PARSER COMMAND OPTIONS</h2>
+
+ <dl class="options">
+ <dt><code><b>--type-map</b> <i>mapfile</i></code></dt>
+ <dd>Read XML Schema to C++ type mapping information from
+ <code><i>mapfile</i></code>. 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 <code><b>void</b></code>.
+ See the TYPE MAP section below for more information.</dd>
+
+ <dt><code><b>--reuse-style-mixin</b></code></dt>
+ <dd>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.</dd>
+
+ <dt><code><b>--reuse-style-none</b></code></dt>
+ <dd>Do not generate any support for base parser implementation
+ reuse. By default support for the tiein style is generated.</dd>
+
+ <dt><code><b>--suppress-validation</b></code></dt>
+ <dd>Suppress the generation of validation code.</dd>
+
+ <dt><code><b>--generate-polymorphic</b></code></dt>
+ <dd>Generate polymorphism-aware code. Specify this option if you use
+ substitution groups or <code><b>xsi:type</b></code>.</dd>
+
+ <dt><code><b>--runtime-polymorphic</b></code></dt>
+ <dd>Generate non-polymorphic code that uses the runtime library
+ configured with polymorphism support.</dd>
+
+ <dt><code><b>--suppress-reset</b></code></dt>
+ <dd>Suppress the generation of parser reset code. Reset
+ support allows you to reuse parsers after an error.</dd>
+
+ <dt><code><b>--generate-noop-impl</b></code></dt>
+ <dd>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
+ <code><b>name.xsd</b></code> this option triggers the generation
+ of the two additional C++ files in the form:
+ <code><b>name-pimpl.hxx</b></code> (parser implementation header
+ file) and <code><b>name-pimpl.cxx</b></code> (parser implementation
+ source file).</dd>
+
+ <dt><code><b>--generate-print-impl</b></code></dt>
+ <dd>Generate a sample parser implementation that prints the XML data
+ to STDOUT. For an input file in the form <code><b>name.xsd</b></code>
+ this option triggers the generation of the two additional C++ files
+ in the form: <code><b>name-pimpl.hxx</b></code> (parser implementation
+ header file) and <code><b>name-pimpl.cxx</b></code> (parser
+ implementation source file).</dd>
+
+ <dt><code><b>--generate-test-driver</b></code></dt>
+ <dd>Generate a test driver for the sample parser implementation. For an
+ input file in the form <code><b>name.xsd</b></code> this option
+ triggers the generation of an additional C++ file in the form
+ <code><b>name-pdriver.cxx</b></code>.</dd>
+
+ <dt><code><b>--force-overwrite</b></code></dt>
+ <dd>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.</dd>
+
+ <dt><code><b>--root-element-first</b></code></dt>
+ <dd>Indicate that the first global element is the document root. This
+ information is used to generate the test driver for the sample
+ implementation.</dd>
+
+ <dt><code><b>--root-element-last</b></code></dt>
+ <dd>Indicate that the last global element is the document root. This
+ information is used to generate the test driver for the sample
+ implementation.</dd>
+
+ <dt><code><b>--root-element <i>element</i></b></code></dt>
+ <dd>Indicate that <code><i>element</i></code> is the document root.
+ This information is used to generate the test driver for the
+ sample implementation.</dd>
+
+ <dt><code><b>--generate-xml-schema</b></code></dt>
+ <dd>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
+ <code><b>--extern-xml-schema</b></code> option to include this file
+ in the generated files for other schemas.</dd>
+
+ <dt><code><b>--extern-xml-schema</b> <i>file</i></code></dt>
+ <dd>Include a header file derived from <i>file</i> 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 <code><b>--generate-xml-schema</b></code>
+ option to generate this header file.</dd>
+
+ <dt><code><b>--skel-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>_pskel</b></code> to construct the names
+ of generated parser skeletons.</dd>
+
+ <dt><code><b>--skel-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>-pskel</b></code> to construct the names of
+ generated parser skeleton files.</dd>
+
+ <dt><code><b>--impl-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>_pimpl</b></code> to construct the names of
+ parser implementations for the built-in XML Schema types
+ and sample parser implementations.</dd>
+
+ <dt><code><b>--impl-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>-pimpl</b></code> to construct the names of
+ generated sample parser implementation files.</dd>
+ </dl>
+
+ <h2>CXX-SERIALIZER COMMAND OPTIONS</h2>
+
+ <dl class="options">
+ <dt><code><b>--type-map</b> <i>mapfile</i></code></dt>
+ <dd>Read XML Schema to C++ type mapping information from
+ <code><i>mapfile</i></code>. 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 <code><b>void</b></code>.
+ See the TYPE MAP section below for more information.</dd>
+
+ <dt><code><b>--reuse-style-mixin</b></code></dt>
+ <dd>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.</dd>
+
+ <dt><code><b>--reuse-style-none</b></code></dt>
+ <dd>Do not generate any support for base serializer implementation
+ reuse. By default support for the tiein style is generated.</dd>
+
+ <dt><code><b>--suppress-validation</b></code></dt>
+ <dd>Suppress the generation of validation code.</dd>
+
+ <dt><code><b>--generate-polymorphic</b></code></dt>
+ <dd>Generate polymorphism-aware code. Specify this option if you use
+ substitution groups or <code><b>xsi:type</b></code>.</dd>
+
+ <dt><code><b>--runtime-polymorphic</b></code></dt>
+ <dd>Generate non-polymorphic code that uses the runtime library
+ configured with polymorphism support.</dd>
+
+ <dt><code><b>--suppress-reset</b></code></dt>
+ <dd>Suppress the generation of serializer reset code. Reset
+ support allows you to reuse serializers after an error.</dd>
+
+ <dt><code><b>--generate-empty-impl</b></code></dt>
+ <dd>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 <code><b>name.xsd</b></code> this
+ option triggers the generation of the two additional C++ files in the
+ form: <code><b>name-simpl.hxx</b></code> (serializer implementation
+ header file) and <code><b>name-simpl.cxx</b></code> (serializer
+ implementation source file).</dd>
+
+ <dt><code><b>--generate-test-driver</b></code></dt>
+ <dd>Generate a test driver for the sample serializer implementation. For
+ an input file in the form <code><b>name.xsd</b></code> this option
+ triggers the generation of an additional C++ file in the form
+ <code><b>name-sdriver.cxx</b></code>.</dd>
+
+ <dt><code><b>--force-overwrite</b></code></dt>
+ <dd>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.</dd>
+
+ <dt><code><b>--root-element-first</b></code></dt>
+ <dd>Indicate that the first global element is the document root. This
+ information is used to generate the test driver for the sample
+ implementation.</dd>
+
+ <dt><code><b>--root-element-last</b></code></dt>
+ <dd>Indicate that the last global element is the document root. This
+ information is used to generate the test driver for the sample
+ implementation.</dd>
+
+ <dt><code><b>--root-element <i>element</i></b></code></dt>
+ <dd>Indicate that <code><i>element</i></code> is the document root.
+ This information is used to generate the test driver for the
+ sample implementation.</dd>
+
+ <dt><code><b>--generate-xml-schema</b></code></dt>
+ <dd>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
+ <code><b>--extern-xml-schema</b></code> option to include this file
+ in the generated files for other schemas.</dd>
+
+ <dt><code><b>--extern-xml-schema</b> <i>file</i></code></dt>
+ <dd>Include a header file derived from <i>file</i> 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 <code><b>--generate-xml-schema</b></code>
+ option to generate this header file.</dd>
+
+ <dt><code><b>--skel-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>_sskel</b></code> to construct the names
+ of generated serializer skeletons.</dd>
+
+ <dt><code><b>--skel-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>-sskel</b></code> to construct the names of
+ generated serializer skeleton files.</dd>
+
+ <dt><code><b>--impl-type-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>_simpl</b></code> to construct the names of
+ serializer implementations for the built-in XML Schema types
+ and sample serializer implementations.</dd>
+
+ <dt><code><b>--impl-file-suffix</b> <i>suffix</i></code></dt>
+ <dd>Use the provided <code><i>suffix</i></code> instead of the
+ default <code><b>-simpl</b></code> to construct the names of
+ generated sample serializer implementation files.</dd>
+ </dl>
+
+
+ <h1>TYPE MAP</h1>
+
+ <p>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
+ <code><b>post_*</b></code> 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 <code><b>pre</b></code> functions in
+ serializer skeletons corresponding to XML Schema types as
+ well as return types for callbacks corresponding to elements
+ and attributes of these types.</p>
+
+ <p>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
+ <code><b>void</b></code>. By providing your own type maps you
+ can override these predefined rules. The format of the type map
+ file is presented below:
+ </p>
+
+ <pre>
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code><b>"&nbsp;"</b></code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the <code><b>post_*</b></code> function
+ in C++/Parser or for element/attribute callbacks in C++/Serializer.
+ Optional <code><i>&lt;cxx-arg-type></i></code> is an argument type
+ for element/attribute callbacks in C++/Parser or for the
+ <code><b>pre</b></code> function in C++/Serializer. If
+ <code><i>&lt;cxx-arg-type></i></code> is not specified, it defaults
+ to <code><i>&lt;cxx-ret-type></i></code> if <code><i>&lt;cxx-ret-type></i></code>
+ ends with <code><b>*</b></code> or <code><b>&amp;</b></code> (that is,
+ it is a pointer or a reference) and
+ <code><b>const</b>&nbsp;<i>&lt;cxx-ret-type></i><b>&amp;</b></code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code><b>"&nbsp;"</b></code> or <code><b>&lt;&nbsp;></b></code> format
+ and is added with the <code><b>#include</b></code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code><b>http://www.example.com/xmlns/my#orange</b></code>
+ XML Schema type, the <code><b>my::orange_t*</b></code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>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:</p>
+
+ <pre>
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>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
+ <code><b>void</b></code>:</p>
+
+ <pre>
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+ <p>When you provide your own type maps with the
+ <code><b>--type-map</b></code> option, they are evaluated first.
+ This allows you to selectively override predefined rules.</p>
+
+
+ <h2>Predefined C++/Parser Type Maps</h2>
+
+ <p>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:</p>
+
+ <pre>
+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;
+}
+ </pre>
+
+ <p>If the <code><b>--no-stl</b></code> option is not specified,
+ the following mapping is used for the string-based XML Schema
+ built-in types:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;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;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre>
+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*;
+}
+ </pre>
+
+ <h2>Predefined C++/Serializer Type Maps</h2>
+
+ <p>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:</p>
+
+ <pre>
+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;
+}
+ </pre>
+
+ <p>If the <code><b>--no-stl</b></code> option is not specified,
+ the following mapping is used for the string-based XML Schema
+ built-in types:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;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;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre>
+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*";
+}
+ </pre>
+
+ <h1>REGEX AND SHELL QUOTING</h1>
+
+ <p>When entering a regular expression argument in the shell
+ command line it is often necessary to use quoting (enclosing
+ the argument in <code><b>"&nbsp;"</b></code> or
+ <code><b>'&nbsp;'</b></code>) in order to prevent the shell
+ from interpreting certain characters, for example, spaces as
+ argument separators and <code><b>$</b></code> as variable
+ expansions.</p>
+
+ <p>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 <code><b>"&nbsp;"</b></code> for quoting you will get a
+ wrong result with POSIX shells if your expression contains
+ <code><b>$</b></code>. The standard way of dealing with this
+ on POSIX systems is to use <code><b>'&nbsp;'</b></code> instead.
+ Unfortunately, Windows shell does not remove <code><b>'&nbsp;'</b></code>
+ from arguments when they are passed to applications. As a result you
+ may have to use <code><b>'&nbsp;'</b></code> for POSIX and
+ <code><b>"&nbsp;"</b></code> for Windows (<code><b>$</b></code> is
+ not treated as a special character on Windows).</p>
+
+ <p>Alternatively, you can save regular expression options into
+ a file, one option per line, and use this file with the
+ <code><b>--options-file</b></code> option. With this approach
+ you don't need to worry about shell quoting.</p>
+
+ <h1>DIAGNOSTICS</h1>
+
+ <p>If the input file is not a valid W3C XML Schema definition,
+ <code><b>xsde</b></code> will issue diagnostic messages to STDERR
+ and exit with non-zero exit code.</p>
+
+ <h1>BUGS</h1>
+
+ <p>Send bug reports to the
+ <a href="mailto:xsd-users@codesynthesis.com">xsde-users@codesynthesis.com</a> mailing list.</p>
+
+ </div>
+ <div id="footer">
+ &copy;2005-2009 <a href="http://codesynthesis.com">CODE SYNTHESIS TOOLS CC</a>
+
+ <div id="terms">
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </div>
+ </div>
+</div>
+</body>
+</html>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/compositors/compositors.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="simple_choice">
+ <xsd:choice>
+ <xsd:element name="a" type="xsd:int"/>
+ <xsd:element name="b" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="c" type="xsd:boolean" maxOccurs="unbounded"/>
+ </xsd:choice>
+ </xsd:complexType>
+
+ <xsd:complexType name="nested_choice">
+ <xsd:sequence>
+ <xsd:choice minOccurs="0">
+ <xsd:element name="a" type="xsd:int"/>
+ <xsd:sequence>
+ <xsd:element name="b" type="xsd:int"/>
+ <xsd:element name="c" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:choice>
+ <xsd:element name="d" type="xsd:int"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="nested_sequence">
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element name="a" type="xsd:int"/>
+ <xsd:sequence minOccurs="0">
+ <xsd:element name="b" type="xsd:int"/>
+ <xsd:element name="c" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:sequence>
+ </xsd:complexType>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <people.xml
diff --git a/examples/cxx/hybrid/filter/driver.cxx b/examples/cxx/hybrid/filter/driver.cxx
new file mode 100644
index 0000000..9bc9f64
--- /dev/null
+++ b/examples/cxx/hybrid/filter/driver.cxx
@@ -0,0 +1,98 @@
+// file : examples/cxx/hybrid/filter/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#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<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 ();
+ }
+ 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/filter/people.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="people.xsd">
+
+ <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>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/filter/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:simpleType name="gender">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="male"/>
+ <xsd:enumeration value="female"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="first-name" type="xsd:string"/>
+ <xsd:element name="last-name" type="xsd:string"/>
+ <xsd:element name="gender" type="gender"/>
+ <xsd:element name="age" type="xsd:unsignedShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="people">
+ <xsd:sequence>
+ <xsd:element name="person" type="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="people" type="people"/>
+
+</xsd:schema>
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 <hello.xml
diff --git a/examples/cxx/hybrid/hello/driver.cxx b/examples/cxx/hybrid/hello/driver.cxx
new file mode 100644
index 0000000..ac99149
--- /dev/null
+++ b/examples/cxx/hybrid/hello/driver.cxx
@@ -0,0 +1,66 @@
+// file : examples/cxx/hybrid/hello/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/hello/hello.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="hello.xsd">
+
+ <greeting>Hello</greeting>
+
+ <name>sun</name>
+ <name>moon</name>
+ <name>world</name>
+
+</hello>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/hello/hello.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="hello">
+ <xsd:sequence>
+ <xsd:element name="greeting" type="xsd:string"/>
+ <xsd:element name="name" type="xsd:string" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="hello" type="hello"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <library.xml
diff --git a/examples/cxx/hybrid/library/driver.cxx b/examples/cxx/hybrid/library/driver.cxx
new file mode 100644
index 0000000..2bde50d
--- /dev/null
+++ b/examples/cxx/hybrid/library/driver.cxx
@@ -0,0 +1,159 @@
+// file : examples/cxx/hybrid/library/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#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<catalog> 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<book> 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/library/library.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd">
+
+ <book available="false">
+ <isbn>0679760806</isbn>
+ <title>The Master and Margarita</title>
+ <genre>fiction</genre>
+
+ <author>
+ <name>Mikhail Bulgakov</name>
+ <born>1891-05-15</born>
+ <died>1940-03-10</died>
+ </author>
+ </book>
+
+
+ <book available="true" >
+ <isbn>0679600841</isbn>
+ <title>War and Peace</title>
+ <genre>history</genre>
+
+ <author>
+ <name>Leo Tolstoy</name>
+ <born>1828-09-09</born>
+ <died>1910-11-20</died>
+ </author>
+ </book>
+
+
+ <book available="false">
+ <isbn>0679420290</isbn>
+ <title>Crime and Punishment</title>
+ <genre>philosophy</genre>
+
+ <author>
+ <name>Fyodor Dostoevsky</name>
+ <born>1821-11-11</born>
+ <died>1881-02-09</died>
+ </author>
+ </book>
+
+</lib:catalog>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/library/library.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:lib="http://www.codesynthesis.com/library"
+ targetNamespace="http://www.codesynthesis.com/library">
+
+ <xsd:simpleType name="isbn">
+ <xsd:restriction base="xsd:unsignedInt"/>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="title">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="lang" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="genre">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="romance"/>
+ <xsd:enumeration value="fiction"/>
+ <xsd:enumeration value="horror"/>
+ <xsd:enumeration value="history"/>
+ <xsd:enumeration value="philosophy"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="author">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="born" type="xsd:date"/>
+ <xsd:element name="died" type="xsd:date" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="book">
+ <xsd:sequence>
+ <xsd:element name="isbn" type="lib:isbn"/>
+ <xsd:element name="title" type="lib:title"/>
+ <xsd:element name="genre" type="lib:genre"/>
+ <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="available" type="xsd:boolean" use="required"/>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:element name="catalog" type="lib:catalog"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+# 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 <people.xml
diff --git a/examples/cxx/hybrid/minimal/driver.cxx b/examples/cxx/hybrid/minimal/driver.cxx
new file mode 100644
index 0000000..e876b6f
--- /dev/null
+++ b/examples/cxx/hybrid/minimal/driver.cxx
@@ -0,0 +1,265 @@
+// file : examples/cxx/hybrid/minimal/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <stdio.h>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/minimal/people.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="people.xsd">
+
+ <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>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/minimal/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:simpleType name="gender">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="male"/>
+ <xsd:enumeration value="female"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="first-name" type="xsd:string"/>
+ <xsd:element name="last-name" type="xsd:string"/>
+ <xsd:element name="gender" type="gender"/>
+ <xsd:element name="age" type="xsd:unsignedShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="people">
+ <xsd:sequence>
+ <xsd:element name="person" type="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="people" type="people"/>
+
+</xsd:schema>
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 <balance.xml
+$ ./driver <withdraw.xml
+$ ./driver <deposit.xml
diff --git a/examples/cxx/hybrid/multiroot/balance.xml b/examples/cxx/hybrid/multiroot/balance.xml
new file mode 100644
index 0000000..9cffa83
--- /dev/null
+++ b/examples/cxx/hybrid/multiroot/balance.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/multiroot/balance.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:balance xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+
+</p:balance>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/multiroot/deposit.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:deposit xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+ <amount>1000000</amount>
+
+</p:deposit>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/multiroot/protocol.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:p="http://www.codesynthesis.com/protocol"
+ targetNamespace="http://www.codesynthesis.com/protocol">
+
+ <xsd:complexType name="request">
+ <xsd:sequence>
+ <xsd:element name="account" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="balance">
+ <xsd:complexContent>
+ <xsd:extension base="p:request"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="withdraw">
+ <xsd:complexContent>
+ <xsd:extension base="p:request">
+ <xsd:sequence>
+ <xsd:element name="amount" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="deposit">
+ <xsd:complexContent>
+ <xsd:extension base="p:request">
+ <xsd:sequence>
+ <xsd:element name="amount" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="balance" type="p:balance"/>
+ <xsd:element name="withdraw" type="p:withdraw"/>
+ <xsd:element name="deposit" type="p:deposit"/>
+
+</xsd:schema>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/multiroot/withdraw.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:withdraw xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+ <amount>1000000</amount>
+
+</p:withdraw>
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 <position.xml
diff --git a/examples/cxx/hybrid/streaming/driver.cxx b/examples/cxx/hybrid/streaming/driver.cxx
new file mode 100644
index 0000000..ab2cd3a
--- /dev/null
+++ b/examples/cxx/hybrid/streaming/driver.cxx
@@ -0,0 +1,83 @@
+// file : examples/cxx/hybrid/streaming/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/streaming/position.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<object id="123">
+
+ <position lat="-33.8569" lon="18.5083"/>
+ <position lat="-33.8568" lon="18.5083"/>
+ <position lat="-33.8568" lon="18.5082"/>
+ <position lat="-33.8570" lon="18.5083"/>
+ <position lat="-33.8569" lon="18.5084"/>
+ <position lat="-33.8570" lon="18.5084"/>
+ <position lat="-33.8570" lon="18.5082"/>
+ <position lat="-33.8569" lon="18.5082"/>
+
+</object>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/streaming/position.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+
+ <xsd:complexType name="position">
+ <xsd:attribute name="lat" type="xsd:float" use="required"/>
+ <xsd:attribute name="lon" type="xsd:float" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="object">
+ <xsd:sequence>
+ <xsd:element name="position" type="position" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/>
+ </xsd:complexType>
+
+ <xsd:element name="object" type="object"/>
+
+</xsd:schema>
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 <email.xml
diff --git a/examples/cxx/hybrid/wildcard/body.cxx b/examples/cxx/hybrid/wildcard/body.cxx
new file mode 100644
index 0000000..e6bd164
--- /dev/null
+++ b/examples/cxx/hybrid/wildcard/body.cxx
@@ -0,0 +1,26 @@
+// file : examples/cxx/hybrid/wildcard/body.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// 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<body*> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string> // memcpy
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#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<envelope> 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<body*> (*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<envelope> 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<body> 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<binary> pic (new binary);
+ pic->name ("pic.jpg");
+ pic->mime ("image/jpeg");
+ pic->size (3);
+ memcpy (pic->data (), "123", 3);
+
+ b = auto_ptr<body> (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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/wildcard/email.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<eml:message xmlns:eml="http://www.codesynthesis.com/email"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/email email.xsd">
+
+ <to>Jane Doe &lt;jane@doe.com></to>
+ <from>John Doe &lt;john@doe.com></from>
+ <subject>Surfing pictures</subject>
+
+ <eml:text>
+Hi Jane,
+
+Here are cool pictures of me surfing.
+
+Cheers,
+John
+ </eml:text>
+
+ <eml:binary name="pic1.jpg" mime="image/jpeg">YmFzZTY0IGJpbmFyeQ==</eml:binary>
+ <eml:binary name="pic2.jpg" mime="image/jpeg">YmFzZTY0IGJpbmFyeQ==</eml:binary>
+
+</eml:message>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/wildcard/email.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:eml="http://www.codesynthesis.com/email"
+ targetNamespace="http://www.codesynthesis.com/email">
+
+ <!-- Predefined envolop body types. -->
+
+ <xsd:element name="text" type="xsd:string"/>
+
+ <xsd:complexType name="binary">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:base64Binary">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:element name="binary" type="eml:binary"/>
+
+ <xsd:complexType name="envelope">
+ <xsd:sequence>
+ <xsd:element name="to" type="xsd:string"/>
+ <xsd:element name="from" type="xsd:string"/>
+ <xsd:element name="subject" type="xsd:string"/>
+
+ <!-- Extensible envelope body. -->
+
+ <xsd:any namespace="##targetNamespace" processContents="strict"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="message" type="eml:envelope"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // 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<body> b (new body);
+ b->text (text_p_->post_string ());
+ env->custom_data ().push_back (b.release ());
+ }
+ else if (name == "binary")
+ {
+ std::auto_ptr<body> 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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<const body*> (*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<const body*> (*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<const body*> (*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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := email.xsd
+cxx := driver.cxx 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 <boris@codesynthesis.com>
+# 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 <library.xml
diff --git a/examples/cxx/parser/generated/library.xml b/examples/cxx/parser/generated/library.xml
new file mode 100644
index 0000000..2d9069c
--- /dev/null
+++ b/examples/cxx/parser/generated/library.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/library/library.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd">
+
+ <book id="MM" available="false">
+ <isbn>0679760806</isbn>
+ <title>The Master and Margarita</title>
+ <genre>fiction</genre>
+
+ <author recommends="WP">
+ <name>Mikhail Bulgakov</name>
+ <born>1891-05-15</born>
+ <died>1940-03-10</died>
+ </author>
+ </book>
+
+
+ <book id="WP" available="true" >
+ <isbn>0679600841</isbn>
+ <title>War and Peace</title>
+ <genre>history</genre>
+
+ <author recommends="CP">
+ <name>Leo Tolstoy</name>
+ <born>1828-09-09</born>
+ <died>1910-11-20</died>
+ </author>
+ </book>
+
+
+ <book id="CP" available="false">
+ <isbn>0679420290</isbn>
+ <title>Crime and Punishment</title>
+ <genre>philosophy</genre>
+
+ <author>
+ <name>Fyodor Dostoevsky</name>
+ <born>1821-11-11</born>
+ <died>1881-02-09</died>
+ </author>
+ </book>
+
+</lib:catalog>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/library/library.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:lib="http://www.codesynthesis.com/library"
+ targetNamespace="http://www.codesynthesis.com/library">
+
+ <xsd:simpleType name="isbn">
+ <xsd:restriction base="xsd:unsignedInt"/>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="title">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="lang" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="genre">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="romance"/>
+ <xsd:enumeration value="fiction"/>
+ <xsd:enumeration value="horror"/>
+ <xsd:enumeration value="history"/>
+ <xsd:enumeration value="philosophy"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="born" type="xsd:string"/>
+ <xsd:element name="died" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="author">
+ <xsd:complexContent>
+ <xsd:extension base="lib:person">
+ <xsd:attribute name="recommends" type="xsd:IDREF"/> <!-- Book -->
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="book">
+ <xsd:sequence>
+ <xsd:element name="isbn" type="lib:isbn"/>
+ <xsd:element name="title" type="lib:title"/>
+ <xsd:element name="genre" type="lib:genre"/>
+ <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="available" type="xsd:boolean" use="required"/>
+ <xsd:attribute name="id" type="xsd:ID" use="required"/>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:element name="catalog" type="lib:catalog"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# 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 <hello.xml
diff --git a/examples/cxx/parser/hello/driver.cxx b/examples/cxx/parser/hello/driver.cxx
new file mode 100644
index 0000000..2326445
--- /dev/null
+++ b/examples/cxx/parser/hello/driver.cxx
@@ -0,0 +1,82 @@
+// file : examples/cxx/parser/hello/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string>
+#include <iostream>
+
+#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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/hello/hello.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<hello xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="hello.xsd">
+
+ <greeting>Hello</greeting>
+
+ <name>sun</name>
+ <name>moon</name>
+ <name>world</name>
+
+</hello>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/hello/hello.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="hello">
+ <xsd:sequence>
+ <xsd:element name="greeting" type="xsd:string"/>
+ <xsd:element name="name" type="xsd:string" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="hello" type="hello"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <library.xml
diff --git a/examples/cxx/parser/library/driver.cxx b/examples/cxx/parser/library/driver.cxx
new file mode 100644
index 0000000..902499a
--- /dev/null
+++ b/examples/cxx/parser/library/driver.cxx
@@ -0,0 +1,131 @@
+// file : examples/cxx/parser/library/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef LIBRARY_HXX
+#define LIBRARY_HXX
+
+#include <string>
+#include <vector>
+
+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<library::author> 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<book> 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/library/library.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/library library.xsd">
+
+ <book id="MM" available="false">
+ <isbn>0679760806</isbn>
+ <title>The Master and Margarita</title>
+ <genre>fiction</genre>
+
+ <author recommends="WP">
+ <name>Mikhail Bulgakov</name>
+ <born>1891-05-15</born>
+ <died>1940-03-10</died>
+ </author>
+ </book>
+
+
+ <book id="WP" available="true" >
+ <isbn>0679600841</isbn>
+ <title>War and Peace</title>
+ <genre>history</genre>
+
+ <author recommends="CP">
+ <name>Leo Tolstoy</name>
+ <born>1828-09-09</born>
+ <died>1910-11-20</died>
+ </author>
+ </book>
+
+
+ <book id="CP" available="false">
+ <isbn>0679420290</isbn>
+ <title>Crime and Punishment</title>
+ <genre>philosophy</genre>
+
+ <author>
+ <name>Fyodor Dostoevsky</name>
+ <born>1821-11-11</born>
+ <died>1881-02-09</died>
+ </author>
+ </book>
+
+</lib:catalog>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/library/library.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:lib="http://www.codesynthesis.com/library"
+ targetNamespace="http://www.codesynthesis.com/library">
+
+ <xsd:simpleType name="isbn">
+ <xsd:restriction base="xsd:unsignedInt"/>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="title">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="lang" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="genre">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="romance"/>
+ <xsd:enumeration value="fiction"/>
+ <xsd:enumeration value="horror"/>
+ <xsd:enumeration value="history"/>
+ <xsd:enumeration value="philosophy"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="born" type="xsd:string"/>
+ <xsd:element name="died" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="author">
+ <xsd:complexContent>
+ <xsd:extension base="lib:person">
+ <xsd:attribute name="recommends" type="xsd:IDREF"/> <!-- Book -->
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="book">
+ <xsd:sequence>
+ <xsd:element name="isbn" type="lib:isbn"/>
+ <xsd:element name="title" type="lib:title"/>
+ <xsd:element name="genre" type="lib:genre"/>
+ <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="available" type="xsd:boolean" use="required"/>
+ <xsd:attribute name="id" type="xsd:ID" use="required"/>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:element name="catalog" type="lib:catalog"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+# 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 <people.xml
diff --git a/examples/cxx/parser/minimal/driver.cxx b/examples/cxx/parser/minimal/driver.cxx
new file mode 100644
index 0000000..e526358
--- /dev/null
+++ b/examples/cxx/parser/minimal/driver.cxx
@@ -0,0 +1,145 @@
+// file : examples/cxx/parser/minimal/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <stdio.h>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/minimal/people.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="people.xsd">
+
+ <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>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/minimal/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:simpleType name="gender">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="male"/>
+ <xsd:enumeration value="female"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="first-name" type="xsd:string"/>
+ <xsd:element name="last-name" type="xsd:string"/>
+ <xsd:element name="gender" type="gender"/>
+ <xsd:element name="age" type="xsd:unsignedShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="people">
+ <xsd:sequence>
+ <xsd:element name="person" type="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="people" type="people"/>
+
+</xsd:schema>
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 <a href="uri">time</a>.
+
+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 <text.xml
diff --git a/examples/cxx/parser/mixed/anchor.hxx b/examples/cxx/parser/mixed/anchor.hxx
new file mode 100644
index 0000000..bc1b54d
--- /dev/null
+++ b/examples/cxx/parser/mixed/anchor.hxx
@@ -0,0 +1,34 @@
+// file : examples/cxx/parser/mixed/anchor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef ANCHOR_HXX
+#define ANCHOR_HXX
+
+#include <string>
+
+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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#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<anchor> 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/text/text.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<text xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="text.xsd">
+
+The first paragraph of this text talks about <a href="http://en.wikipedia.org/wiki/time">time</a>.
+
+And this paragraph talks about <a href="http://en.wikipedia.org/wiki/space">space</a>.
+
+</text>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/mixed/text.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="anchor">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="href" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="text" mixed="true">
+ <xsd:sequence>
+ <xsd:element name="a" type="anchor" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="text" type="text"/>
+
+</xsd:schema>
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 <balance.xml
+$ ./driver <withdraw.xml
+$ ./driver <deposit.xml
diff --git a/examples/cxx/parser/multiroot/balance.xml b/examples/cxx/parser/multiroot/balance.xml
new file mode 100644
index 0000000..df0a6e9
--- /dev/null
+++ b/examples/cxx/parser/multiroot/balance.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/multiroot/balance.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:balance xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+
+</p:balance>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/multiroot/deposit.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:deposit xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+ <amount>1000000</amount>
+
+</p:deposit>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#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<request> 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<request> 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<balance*> (r.get ());
+ cerr << "balance request for acc# " << b->account () << endl;
+ break;
+ }
+ case withdraw_type:
+ {
+ withdraw* w = static_cast<withdraw*> (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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/multiroot/protocol.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:p="http://www.codesynthesis.com/protocol"
+ targetNamespace="http://www.codesynthesis.com/protocol">
+
+ <xsd:complexType name="request">
+ <xsd:sequence>
+ <xsd:element name="account" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="balance">
+ <xsd:complexContent>
+ <xsd:extension base="p:request"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="withdraw">
+ <xsd:complexContent>
+ <xsd:extension base="p:request">
+ <xsd:sequence>
+ <xsd:element name="amount" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="deposit">
+ <xsd:complexContent>
+ <xsd:extension base="p:request">
+ <xsd:sequence>
+ <xsd:element name="amount" type="xsd:unsignedInt"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="balance" type="p:balance"/>
+ <xsd:element name="withdraw" type="p:withdraw"/>
+ <xsd:element name="deposit" type="p:deposit"/>
+
+</xsd:schema>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/multiroot/withdraw.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<p:withdraw xmlns:p="http://www.codesynthesis.com/protocol"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/protocol protocol.xsd">
+
+ <account>123456789</account>
+ <amount>1000000</amount>
+
+</p:withdraw>
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 <supermen.xml
diff --git a/examples/cxx/parser/polymorphism/driver.cxx b/examples/cxx/parser/polymorphism/driver.cxx
new file mode 100644
index 0000000..907be5d
--- /dev/null
+++ b/examples/cxx/parser/polymorphism/driver.cxx
@@ -0,0 +1,115 @@
+// file : examples/cxx/parser/polymorphism/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polymorphism/supermen.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd">
+
+ <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>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polymorphism/supermen.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="supermen">
+ <xsd:sequence>
+ <xsd:element ref="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="supermen" type="supermen"/>
+
+</xsd:schema>
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 <person.xml
+$ ./driver <superman.xml
+$ ./driver <batman.xml
diff --git a/examples/cxx/parser/polyroot/batman.xml b/examples/cxx/parser/polyroot/batman.xml
new file mode 100644
index 0000000..70abdf7
--- /dev/null
+++ b/examples/cxx/parser/polyroot/batman.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polyroot/batman.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd"
+ xsi:type="batman" can-fly="true" wing-span="10">
+
+ <name>Bruce Wayne</name>
+
+</person>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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<person_pskel*> (p);
+#else
+ parser_used_ = static_cast<person_pskel*> (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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polyroot/person.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd">
+
+ <name>John Doe</name>
+
+</person>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polyroot/superman.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<superman xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd"
+ can-fly="false">
+
+ <name>James "007" Bond</name>
+
+</superman>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/polyroot/supermen.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
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 <email.xml
diff --git a/examples/cxx/parser/wildcard/driver.cxx b/examples/cxx/parser/wildcard/driver.cxx
new file mode 100644
index 0000000..aed2560
--- /dev/null
+++ b/examples/cxx/parser/wildcard/driver.cxx
@@ -0,0 +1,359 @@
+// file : examples/cxx/parser/wildcard/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string>
+#include <memory>
+#include <iostream>
+
+#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<xml_schema::buffer> 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/wildcard/email.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<eml:message xmlns:eml="http://www.codesynthesis.com/email"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/email email.xsd"
+ eml:thread-id="123456789">
+
+ <to>Jane Doe &lt;jane@doe.com></to>
+ <from>John Doe &lt;john@doe.com></from>
+ <subject>Surfing pictures</subject>
+
+ <eml:text>
+Hi Jane,
+
+Here are cool pictures of me surfing.
+
+Cheers,
+John
+ </eml:text>
+
+ <eml:binary name="pic1.jpg" mime="image/jpeg">YmFzZTY0IGJpbmFyeQ==</eml:binary>
+ <eml:binary name="pic2.jpg" mime="image/jpeg">YmFzZTY0IGJpbmFyeQ==</eml:binary>
+
+</eml:message>
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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/parser/wildcard/email.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:eml="http://www.codesynthesis.com/email"
+ targetNamespace="http://www.codesynthesis.com/email">
+
+ <!-- Predefined envolop body types. -->
+
+ <xsd:element name="text" type="xsd:string"/>
+
+ <xsd:complexType name="binary">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:base64Binary">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:element name="binary" type="eml:binary"/>
+
+ <!-- Predefined envelop attributes. -->
+
+ <xsd:attribute name="thread-id" type="xsd:unsignedInt"/>
+
+
+ <xsd:complexType name="envelope">
+ <xsd:sequence>
+ <xsd:element name="to" type="xsd:string"/>
+ <xsd:element name="from" type="xsd:string"/>
+ <xsd:element name="subject" type="xsd:string"/>
+
+ <!-- Extensible envelope body. -->
+
+ <xsd:any namespace="##targetNamespace" processContents="strict"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##targetNamespace" processContents="strict"/>
+ </xsd:complexType>
+
+ <xsd:element name="message" type="eml:envelope"/>
+
+</xsd:schema>
diff --git a/examples/cxx/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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := email.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#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<string> 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/hello/hello.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="hello">
+ <xsd:sequence>
+ <xsd:element name="greeting" type="xsd:string"/>
+ <xsd:element name="name" type="xsd:string" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="hello" type="hello"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef LIBRARY_HXX
+#define LIBRARY_HXX
+
+#include <string>
+#include <vector>
+
+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<library::author> 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<book> 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/library/library.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:lib="http://www.codesynthesis.com/library"
+ targetNamespace="http://www.codesynthesis.com/library">
+
+ <xsd:simpleType name="isbn">
+ <xsd:restriction base="xsd:unsignedInt"/>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="title">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="lang" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="genre">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="romance"/>
+ <xsd:enumeration value="fiction"/>
+ <xsd:enumeration value="horror"/>
+ <xsd:enumeration value="history"/>
+ <xsd:enumeration value="philosophy"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ <xsd:element name="born" type="xsd:string"/>
+ <xsd:element name="died" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="author">
+ <xsd:complexContent>
+ <xsd:extension base="lib:person">
+ <xsd:attribute name="recommends" type="xsd:IDREF"/> <!-- Book -->
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="book">
+ <xsd:sequence>
+ <xsd:element name="isbn" type="lib:isbn"/>
+ <xsd:element name="title" type="lib:title"/>
+ <xsd:element name="genre" type="lib:genre"/>
+ <xsd:element name="author" type="lib:author" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="available" type="xsd:boolean" use="required"/>
+ <xsd:attribute name="id" type="xsd:ID" use="required"/>
+ </xsd:complexType>
+
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="book" type="lib:book" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <xsd:element name="catalog" type="lib:catalog"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <stdio.h>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef PEOPLE_HXX
+#define PEOPLE_HXX
+
+#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_;
+};
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/minimal/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:simpleType name="gender">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="male"/>
+ <xsd:enumeration value="female"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="first-name" type="xsd:string"/>
+ <xsd:element name="last-name" type="xsd:string"/>
+ <xsd:element name="gender" type="gender"/>
+ <xsd:element name="age" type="xsd:unsignedShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="people">
+ <xsd:sequence>
+ <xsd:element name="person" type="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="people" type="people"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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<const superman*> (person_)->can_fly ();
+}
+
+//
+//
+unsigned int batman_simpl::
+wing_span ()
+{
+ return static_cast<const batman*> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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<const superman*> (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<const batman&> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_HXX
+#define SUPERMEN_HXX
+
+#include <string>
+#include <vector>
+
+// 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<person*>
+{
+ ~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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/polymorphism/schema.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="supermen">
+ <xsd:sequence>
+ <xsd:element ref="person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="supermen" type="supermen"/>
+
+</xsd:schema>
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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := 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 <boris@codesynthesis.com>
+// 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<const superman*> (person_)->can_fly ();
+}
+
+//
+//
+unsigned int batman_simpl::
+wing_span ()
+{
+ return static_cast<const batman*> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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<const superman*> (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<const batman&> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_HXX
+#define SUPERMEN_HXX
+
+#include <string>
+#include <vector>
+
+// 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<person*>
+{
+ ~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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/polyroot/schema.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <!-- substitution group root -->
+ <xsd:element name="person" type="person"/>
+
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="superman" type="superman" substitutionGroup="person"/>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/wildcard/README b/examples/cxx/serializer/wildcard/README
new file mode 100644
index 0000000..831a2d4
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/README
@@ -0,0 +1,37 @@
+This example shows how to serialize XML data matched by XML Schema
+wildcards (any and anyAttribute) using the Embedded C++/Serializer
+mapping.
+
+The example consists of the following files:
+
+email.xsd
+ XML Schema which describes a simple email format with the
+ extensible envelope type.
+
+email.hxx
+ C++ types that describe the email format defined in email.xsd.
+ These are hand-written.
+
+email.map
+ Type map. It maps XML Schema types defined in email.xsd to C++
+ types defined in email.hxx.
+
+email-sskel.hxx
+email-sskel.cxx
+ Serializer skeletons generated by XSD/e from email.xsd and
+ email.map.
+
+driver.cxx
+ Serializer implementations and a driver for the example. The
+ serializer implementations serialize the in-memory object model
+ defined in email.hxx to XML. The driver first constructs a sample
+ email object using the types from email.hxx. It then creates a
+ serializer instance using the serializer implementations mentioned
+ above and a couple of predefined serializers for the XML Schema
+ built-in types. Finally, it invokes this serializer instance to
+ serialize the sample email object to an XML document which is
+ printed to STDOUT.
+
+To run the example simply execute:
+
+$ ./driver
diff --git a/examples/cxx/serializer/wildcard/driver.cxx b/examples/cxx/serializer/wildcard/driver.cxx
new file mode 100644
index 0000000..7feb13a
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/driver.cxx
@@ -0,0 +1,410 @@
+// file : examples/cxx/serializer/wildcard/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <iostream>
+
+#include "email-sskel.hxx"
+
+#ifndef XSDE_REUSE_STYLE_TIEIN
+# error this example requires the tiein serializer reuse support
+#endif
+
+using namespace std;
+
+namespace email
+{
+ struct binary_simpl: binary_sskel
+ {
+ // Indicate to base64_binary_simpl that we want it to release
+ // the buffer passed via pre().
+ //
+ binary_simpl ()
+ : binary_sskel (&base_impl_), base_impl_ (true)
+ {
+ }
+
+ virtual void
+ pre (const binary* bin)
+ {
+ using namespace xml_schema;
+
+ bin_ = bin;
+ buffer* buf = new buffer (bin->data (), bin->size ());
+ base_impl_.pre (buf);
+ }
+
+ virtual std::string
+ name ()
+ {
+ return bin_->name ();
+ }
+
+ virtual std::string
+ mime ()
+ {
+ return bin_->mime ();
+ }
+
+ private:
+ xml_schema::base64_binary_simpl base_impl_;
+ const binary* bin_;
+ };
+
+ struct envelope_simpl: envelope_sskel
+ {
+ envelope_simpl (xml_schema::string_simpl& text_s,
+ binary_sskel& bin_s,
+ xml_schema::unsigned_int_simpl& uint_s)
+ : text_s_ (text_s), bin_s_ (bin_s), uint_s_ (uint_s)
+ {
+ }
+
+ virtual void
+ pre (const envelope& env)
+ {
+ env_ = &env;
+ tid_set_ = false;
+ i_ = env_->begin_body ();
+ }
+
+ // Attributes.
+ //
+ virtual bool
+ any_attribute_next ()
+ {
+ return !tid_set_;
+ }
+
+ virtual void
+ any_attribute (std::string& ns, std::string& name)
+ {
+ ns = "http://www.codesynthesis.com/email";
+ name = "thread-id";
+ }
+
+ virtual void
+ serialize_any_attribute ()
+ {
+ // This function is where we perform the actual wildcard
+ // serialization.
+ //
+ xml_schema::serializer_context& ctx = _context ();
+
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+
+ uint_s_.pre (env_->thread_id ());
+ uint_s_._pre_impl (ctx);
+ uint_s_._serialize_content ();
+ uint_s_._post_impl ();
+ uint_s_.post ();
+#else
+ // If we are not using exceptions or XML Schema validation
+ // is enabled then we need to check for the error condition
+ // and, if the (user) error was set in pre() or post(),
+ // also copy the error code to the context. The _error_type()
+ // function returns non-0 value if there an error pending.
+ // The _copy_error() functions copies the error state to
+ // the context.
+
+ uint_s_.pre (env_->thread_id ());
+
+#ifndef XSDE_EXCEPTIONS
+ if (uint_s_._error_type ())
+ uint_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ uint_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ uint_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (uint_s_._error_type ())
+ uint_s_._copy_error (ctx);
+
+ if (_error_type ())
+ return;
+#endif
+#endif
+
+ tid_set_ = true;
+ }
+
+ // Elements.
+ //
+ virtual std::string
+ to ()
+ {
+ return env_->to ();
+ }
+
+ virtual std::string
+ from ()
+ {
+ return env_->from ();
+ }
+
+ virtual std::string
+ subject ()
+ {
+ return env_->subject ();
+ }
+
+ virtual bool
+ any_next ()
+ {
+ // See if there is a body that we know how to serialize.
+ //
+ for (; i_ != env_->end_body (); ++i_)
+ {
+ body_type t = (*i_)->type ();
+
+ if (t == email::text_body || t == email::binary_body)
+ break;
+ }
+
+ return i_ != env_->end_body ();
+ }
+
+ virtual void
+ any (std::string& ns, std::string& name)
+ {
+ ns = "http://www.codesynthesis.com/email";
+
+ switch ((*i_)->type ())
+ {
+ case email::text_body:
+ {
+ name = "text";
+ break;
+ }
+ case email::binary_body:
+ {
+ name = "binary";
+ break;
+ }
+ }
+ }
+
+ virtual void
+ serialize_any ()
+ {
+ const body* b = *i_++;
+ xml_schema::serializer_context& ctx = _context ();
+
+ switch (b->type ())
+ {
+ case email::text_body:
+ {
+ // For more information on what's going here, see the
+ // serialize_any_attribute() function above.
+ //
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+
+ text_s_.pre (static_cast<const text*> (b)->content ());
+ text_s_._pre_impl (ctx);
+ text_s_._serialize_content ();
+ text_s_._post_impl ();
+ text_s_.post ();
+#else
+
+ text_s_.pre (static_cast<const text*> (b)->content ());
+
+#ifndef XSDE_EXCEPTIONS
+ if (text_s_._error_type ())
+ text_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ text_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ text_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (text_s_._error_type ())
+ text_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+#endif
+ break;
+ }
+ case email::binary_body:
+ {
+ // For more information on what's going here, see the
+ // serialize_any_attribute() function above. Note also
+ // that in this case we also call _serialize_attributes
+ // since binary is a complex type.
+ //
+
+#if defined(XSDE_EXCEPTIONS) && !defined(XSDE_SERIALIZER_VALIDATION)
+ bin_s_.pre (static_cast<const binary*> (b));
+ bin_s_._pre_impl (ctx);
+ bin_s_._serialize_attributes ();
+ bin_s_._serialize_content ();
+ bin_s_._post_impl ();
+ bin_s_.post ();
+#else
+ bin_s_.pre (static_cast<const binary*> (b));
+
+#ifndef XSDE_EXCEPTIONS
+ if (bin_s_._error_type ())
+ bin_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+ bin_s_._pre_impl (ctx);
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._serialize_attributes ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._serialize_content ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_._post_impl ();
+
+ if (ctx.error_type ())
+ return;
+
+ bin_s_.post ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (bin_s_._error_type ())
+ bin_s_._copy_error (ctx);
+
+ if (ctx.error_type ())
+ return;
+#endif
+#endif
+ break;
+ }
+ }
+ }
+
+ // If we need to be able to reset and reuse the serializer
+ // after an error then we also need to override _reset() and
+ // reset the serializers that are used to handle wildcards.
+ // Note that you always need to call _reset() from the base.
+ //
+ virtual void
+ _reset ()
+ {
+ envelope_sskel::_reset ();
+
+ text_s_._reset ();
+ bin_s_._reset ();
+ uint_s_._reset ();
+ }
+
+ private:
+ // Serializers used in wildcard content serialization.
+ //
+ xml_schema::string_simpl& text_s_;
+ binary_sskel& bin_s_;
+ xml_schema::unsigned_int_simpl& uint_s_;
+
+ const envelope* env_;
+ bool tid_set_;
+ envelope::body_iterator i_;
+ };
+}
+
+int
+main ()
+{
+ try
+ {
+ using namespace email;
+
+ // Create a sample email with a text body and two (fake) pictures.
+ //
+ envelope env ("Jane Doe <jane@doe.com>",
+ "John Doe <john@doe.com>",
+ "Surfing pictures",
+ 123); // thread id
+
+ env.add_body (new text ("Hi Jane,\n"
+ "Here are cool pictures of me surfing.\n\n"
+ "Cheers,\n"
+ "John"));
+
+ env.add_body (new binary ("pic1.jpg", "image/jpeg", "abc123", 6));
+ env.add_body (new binary ("pic2.jpg", "image/jpeg", "123abc", 6));
+
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::unsigned_int_simpl uint_s;
+
+ binary_simpl binary_s;
+ envelope_simpl envelope_s (string_s, binary_s, uint_s);
+
+ binary_s.serializers (string_s, string_s);
+ envelope_s.serializers (string_s, string_s, string_s);
+
+ // Serialize the sample email to XML document.
+ //
+ xml_schema::document_simpl doc_s (
+ envelope_s,
+ "http://www.codesynthesis.com/email",
+ "message");
+
+ doc_s.add_prefix ("eml", "http://www.codesynthesis.com/email");
+ doc_s.add_schema ("http://www.codesynthesis.com/email", "email.xsd");
+
+ envelope_s.pre (env);
+ doc_s.serialize (cout);
+ envelope_s.post ();
+ }
+ catch (const xml_schema::serializer_exception& e)
+ {
+ cerr << "error: " << e.text () << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << "error: write failure" << endl;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/examples/cxx/serializer/wildcard/email.hxx b/examples/cxx/serializer/wildcard/email.hxx
new file mode 100644
index 0000000..6cf76da
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.hxx
@@ -0,0 +1,194 @@
+// file : examples/cxx/serializer/wildcard/email.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#ifndef EMAIL_HXX
+#define EMAIL_HXX
+
+#include <string>
+#include <vector>
+#include <cstddef> // std::size_t
+#include <cstring> // std::memcpy
+
+namespace email
+{
+ //
+ //
+ enum body_type
+ {
+ text_body,
+ binary_body
+ };
+
+ struct body
+ {
+ virtual body_type
+ type () const = 0;
+
+ virtual
+ ~body ()
+ {
+ }
+ };
+
+ //
+ //
+ struct text: body
+ {
+ text (const std::string& content)
+ : content_ (content)
+ {
+ }
+
+ virtual body_type
+ type () const
+ {
+ return text_body;
+ }
+
+ const std::string&
+ content () const
+ {
+ return content_;
+ }
+
+ private:
+ std::string content_;
+ };
+
+ //
+ //
+ struct binary: body
+ {
+ binary (const std::string& name,
+ const std::string& mime,
+ const char* data,
+ std::size_t size)
+ : name_ (name), mime_ (mime), data_ (0), size_ (size)
+ {
+ if (size_ != 0)
+ {
+ data_ = new char[size_];
+ std::memcpy (data_, data, size_);
+ }
+ }
+
+ virtual
+ ~binary ()
+ {
+ delete[] data_;
+ }
+
+ virtual body_type
+ type () const
+ {
+ return binary_body;
+ }
+
+ const std::string&
+ name () const
+ {
+ return name_;
+ }
+
+ const std::string&
+ mime () const
+ {
+ return mime_;
+ }
+
+ const char*
+ data () const
+ {
+ return data_;
+ }
+
+ std::size_t
+ size () const
+ {
+ return size_;
+ }
+
+ private:
+ std::string name_;
+ std::string mime_;
+ char* data_;
+ std::size_t size_;
+ };
+
+ //
+ //
+ struct envelope
+ {
+ envelope (const std::string& to,
+ const std::string& from,
+ const std::string& subject,
+ unsigned int thread_id)
+ : to_ (to), from_ (from), subject_ (subject), thread_id_ (thread_id)
+ {
+ }
+
+ const std::string&
+ to () const
+ {
+ return to_;
+ }
+
+ const std::string&
+ from () const
+ {
+ return from_;
+ }
+
+ const std::string&
+ subject () const
+ {
+ return subject_;
+ }
+
+ unsigned int
+ thread_id () const
+ {
+ return thread_id_;
+ }
+
+ // Assumes ownership of the passed object.
+ //
+ void
+ add_body (body* b)
+ {
+ bodies_.push_back (b);
+ }
+
+ typedef std::vector<body*> bodies;
+ typedef bodies::const_iterator body_iterator;
+
+ body_iterator
+ begin_body () const
+ {
+ return bodies_.begin ();
+ }
+
+ body_iterator
+ end_body () const
+ {
+ return bodies_.end ();
+ }
+
+ ~envelope ()
+ {
+ for (body_iterator i = begin_body (); i != end_body (); ++i)
+ delete *i;
+ }
+
+ private:
+ const std::string to_;
+ const std::string from_;
+ const std::string subject_;
+ unsigned int thread_id_;
+
+ bodies bodies_;
+ };
+}
+
+#endif // EMAIL_HXX
diff --git a/examples/cxx/serializer/wildcard/email.map b/examples/cxx/serializer/wildcard/email.map
new file mode 100644
index 0000000..fadafb2
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.map
@@ -0,0 +1,12 @@
+# file : examples/cxx/serializer/wildcard/email.map
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : not copyrighted - public domain
+
+namespace http://www.codesynthesis.com/email
+{
+ include "email.hxx";
+
+ text "const text*";
+ binary "const binary*";
+ envelope "const envelope&";
+}
diff --git a/examples/cxx/serializer/wildcard/email.xsd b/examples/cxx/serializer/wildcard/email.xsd
new file mode 100644
index 0000000..bf61589
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/email.xsd
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/serializer/wildcard/email.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:eml="http://www.codesynthesis.com/email"
+ targetNamespace="http://www.codesynthesis.com/email">
+
+ <!-- Predefined envolop body types. -->
+
+ <xsd:element name="text" type="xsd:string"/>
+
+ <xsd:complexType name="binary">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:base64Binary">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:element name="binary" type="eml:binary"/>
+
+ <!-- Predefined envelop attributes. -->
+
+ <xsd:attribute name="thread-id" type="xsd:unsignedInt"/>
+
+
+ <xsd:complexType name="envelope">
+ <xsd:sequence>
+ <xsd:element name="to" type="xsd:string"/>
+ <xsd:element name="from" type="xsd:string"/>
+ <xsd:element name="subject" type="xsd:string"/>
+
+ <!-- Extensible envelope body. -->
+
+ <xsd:any namespace="##targetNamespace" processContents="strict"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##targetNamespace" processContents="strict"/>
+ </xsd:complexType>
+
+ <xsd:element name="message" type="eml:envelope"/>
+
+</xsd:schema>
diff --git a/examples/cxx/serializer/wildcard/makefile b/examples/cxx/serializer/wildcard/makefile
new file mode 100644
index 0000000..a6f881b
--- /dev/null
+++ b/examples/cxx/serializer/wildcard/makefile
@@ -0,0 +1,66 @@
+# file : examples/cxx/serializer/wildcard/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := email.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=-sskel.o))
+dep := $(obj:.o=.o.d)
+
+xsde.l := $(out_root)/libxsde/xsde/xsde.l
+xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options
+
+driver := $(out_base)/driver
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(driver): $(obj) $(xsde.l)
+
+$(obj) $(dep): cpp_options := -I$(out_base) -I$(src_base)
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+skel := $(out_base)/$(xsd:.xsd=-sskel.hxx) \
+ $(out_base)/$(xsd:.xsd=-sskel.ixx) \
+ $(out_base)/$(xsd:.xsd=-sskel.cxx)
+
+$(skel): xsde := $(out_root)/xsde/xsde
+$(skel): xsde_options += --type-map $(src_base)/email.map
+
+$(skel): $(out_root)/xsde/xsde $(src_base)/email.map
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=-sskel.cxx.xsd.clean))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(scf_root)/xsde/serializer/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+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 <xsde/config.h>
+
+
+#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 <windows.h>
+#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 <stdlib.h>
+#include <xsde/c/expat/expat_external.h>
+
+#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 (<!ENTITY foo "bar">), 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 <stddef.h>
+#include <string.h> /* memset(), memcpy() */
+#include <assert.h>
+
+#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 <stddef.h>
+
+#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 <stddef.h>
+
+#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 <e/> */
+#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 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#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_COND_SECT_CLOSE 34 /* ]]> */
+#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 "<!-" */
+
+static int PTRCALL
+PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static int PTRCALL
+PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ /* don't allow <!ENTITY% foo "whatever"> */
+ 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 "<?" */
+
+static int PTRCALL
+PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ 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_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A,
+ ASCII_T, ASCII_A, ASCII_LSQB };
+ int i;
+
+ UNUSED(enc);
+
+ /* CDATA[ */
+ if (end - ptr < 6 * MINBPC(enc))
+ return XML_TOK_PARTIAL;
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static int PTRCALL
+PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ 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_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 "</" */
+
+static int PTRCALL
+PREFIX(scanEndTag)(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_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here,
+ since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static int PTRCALL
+PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static int PTRCALL
+PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (CHAR_MATCHES(enc, ptr, ASCII_x))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static int PTRCALL
+PREFIX(scanRef)(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)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), 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_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static int PTRCALL
+PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ 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;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int open;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ open = BYTE_TYPE(enc, ptr);
+ if (open == BT_QUOT || open == BT_APOS)
+ break;
+ switch (open) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == open)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static int PTRCALL
+PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ 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;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ 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_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 <stddef.h>
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 <stdlib.h>
+#include <string.h>
+
+#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 "&quot;"
+ */
+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, "&#x9;", 5);
+ break;
+ case 0xa:
+ collectPiece(w, value, "&#xA;", 5);
+ break;
+ case 0xd:
+ collectPiece(w, value, "&#xD;", 5);
+ break;
+ case '"':
+ collectPiece(w, value, "&quot;", 6);
+ break;
+ case '<':
+ collectPiece(w, value, "&lt;", 4);
+ break;
+ case '&':
+ collectPiece(w, value, "&amp;", 5);
+ break;
+ /*
+ case '>':
+ collectPiece(w, value, "&gt;", 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, "</");
+ if (e->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) "&#xD;");
+ break;
+ case '<':
+ if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
+ return w->status;
+ *breakerP = next;
+ sendx(w, (utf8) "&lt;");
+ break;
+ case '&':
+ if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
+ return w->status;
+ *breakerP = next;
+ sendx(w, (utf8) "&amp;");
+ break;
+ case '>':
+ if ((w->status = sendxBounded(w, *breakerP, *lastsP)) != GENX_SUCCESS)
+ return w->status;
+ *breakerP = next;
+ sendx(w, (utf8) "&gt;");
+ 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, "&#x9;", 5);
+ break;
+ case 0xa:
+ collectPiece(w, value, "&#xA;", 5);
+ break;
+ case 0xd:
+ collectPiece(w, value, "&#xD;", 5);
+ break;
+ case '"':
+ collectPiece(w, value, "&quot;", 6);
+ break;
+ case '<':
+ collectPiece(w, value, "&lt;", 4);
+ break;
+ case '&':
+ collectPiece(w, value, "&amp;", 5);
+ break;
+ /*
+ case '>':
+ collectPiece(w, value, "&gt;", 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->status = sendx(w, (utf8) 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;
+}
+
+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) "<?")) != GENX_SUCCESS)
+ return w->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 <stdio.h>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy
+
+#include <xsde/cxx/buffer.hxx>
+
+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<char*> (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<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <xsde/cxx/buffer.ixx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // 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<char*> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/config.h>
+
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/config.h>
+
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/config.h>
+
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/config.h>
+
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/date-time.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/errno.ixx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#ifdef XSDE_PLATFORM_WINCE
+# include <winbase.h> // Get/SetLastError
+#else
+# include <errno.h>
+#endif
+
+namespace xsde
+{
+ namespace cxx
+ {
+#ifdef XSDE_PLATFORM_WINCE
+ inline int
+ get_errno ()
+ {
+ return static_cast<int> (GetLastError ());
+ }
+
+ inline void
+ set_errno (int e)
+ {
+ SetLastError (static_cast<DWORD> (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 <boris@codesynthesis.com>
+// 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 <exception> // 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memset, memcpy, strlen, strcmp, strncmp
+
+#include <xsde/cxx/hashmap.hxx>
+
+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<const char*> (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<bucket*> (
+ 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<bucket*> (
+ 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<char*> (p) + sizeof (bucket);
+ char* dst = reinterpret_cast<char*> (n) + sizeof (bucket);
+
+ memcpy (dst, src, p->size_ * (sizeof (element) + esize_));
+
+ operator delete (p);
+ p = n;
+ }
+
+ char* data = reinterpret_cast<char*> (p) + sizeof (bucket) +
+ p->size_ * (sizeof (element) + esize_);
+
+ element* e = reinterpret_cast<element*> (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<const char*> (p) + sizeof (bucket);
+ const char* e = b + p->size_ * (sizeof (element) + esize_);
+
+ for (; b < e; b += sizeof (element) + esize_)
+ {
+ const element* e = reinterpret_cast<const element*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <xsde/cxx/hashmap.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<size_t> (2166136261UL);
+ for (; *s != 0; ++s)
+ {
+ r ^= static_cast<size_t> (*s);
+ r *= static_cast<size_t> (16777619UL);
+ }
+ return r;
+ }
+
+ inline size_t hashmap::
+ hash (const char* s, size_t n)
+ {
+ size_t r = static_cast<size_t> (2166136261UL);
+ for (; n > 0; --n)
+ {
+ r ^= static_cast<size_t> (*s++);
+ r *= static_cast<size_t> (16777619UL);
+ }
+ return r;
+ }
+
+ inline size_t hashmap::
+ hash (size_t h, const char* s)
+ {
+ for (; *s != 0; ++s)
+ {
+ h ^= static_cast<size_t> (*s);
+ h *= static_cast<size_t> (16777619UL);
+ }
+ return h;
+ }
+
+ inline size_t hashmap::
+ hash (size_t h, const char* s, size_t n)
+ {
+ for (; n > 0; --n)
+ {
+ h ^= static_cast<size_t> (*s++);
+ h *= static_cast<size_t> (16777619UL);
+ }
+ return h;
+ }
+
+#elif XSDE_ARCH_WIDTH == 64
+
+ inline size_t hashmap::
+ hash (const char* s)
+ {
+ size_t r = static_cast<size_t> (14695981039346656037ULL);
+ for (; *s != 0; ++s)
+ {
+ r ^= static_cast<size_t> (*s);
+ r *= static_cast<size_t> (1099511628211ULL);
+ }
+ return r;
+ }
+
+ inline size_t hashmap::
+ hash (const char* s, size_t n)
+ {
+ size_t r = static_cast<size_t> (14695981039346656037ULL);
+ for (; n > 0; --n)
+ {
+ r ^= static_cast<size_t> (*s++);
+ r *= static_cast<size_t> (1099511628211ULL);
+ }
+ return r;
+ }
+
+ inline size_t hashmap::
+ hash (size_t h, const char* s)
+ {
+ for (; *s != 0; ++s)
+ {
+ h ^= static_cast<size_t> (*s);
+ h *= static_cast<size_t> (1099511628211ULL);
+ }
+ return h;
+ }
+
+ inline size_t hashmap::
+ hash (size_t h, const char* s, size_t n)
+ {
+ for (; n > 0; --n)
+ {
+ h ^= static_cast<size_t> (*s++);
+ h *= static_cast<size_t> (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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/hybrid/sequence.hxx>
+
+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<void**> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t, ptrdiff_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/sequence-base.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/string-sequence.hxx>
+#endif
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ // Sequence with fixed-length POD elements.
+ //
+ template <typename T>
+ 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 <typename T>
+ 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 <typename T>
+ 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 <typename T>
+ 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<T> j)
+ : i_ (const_cast<const T**> (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<T> j)
+ {
+ i_ = const_cast<const T**> (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 <typename T>
+ inline bool
+ operator== (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ == j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator== (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ == j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator== (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ // eVC++ 4.0 needs the cast.
+ //
+ return const_cast<const T**> (i.i_) == j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator== (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ == const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline bool
+ operator!= (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ != j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator!= (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ != j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator!= (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) != j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator!= (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ != const_cast<const T**> (j.i_);
+ }
+
+ // Random access iterator requirements
+ //
+ template <typename T>
+ inline bool
+ operator< (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ < j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator< (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ < j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator< (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) < j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator< (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ < const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline bool
+ operator> (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ > j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator> (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ > j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator> (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) > j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator> (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ > const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline bool
+ operator<= (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ <= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator<= (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ <= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator<= (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) <= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator<= (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ <= const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline bool
+ operator>= (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ >= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator>= (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ >= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator>= (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) >= j.i_;
+ }
+
+ template <typename T>
+ inline bool
+ operator>= (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ >= const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline ptrdiff_t
+ operator- (var_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ - j.i_;
+ }
+
+ template <typename T>
+ inline ptrdiff_t
+ operator- (var_const_iterator<T> i, var_const_iterator<T> j)
+ {
+ return i.i_ - j.i_;
+ }
+
+ template <typename T>
+ inline ptrdiff_t
+ operator- (var_iterator<T> i, var_const_iterator<T> j)
+ {
+ return const_cast<const T**> (i.i_) - j.i_;
+ }
+
+ template <typename T>
+ inline ptrdiff_t
+ operator- (var_const_iterator<T> i, var_iterator<T> j)
+ {
+ return i.i_ - const_cast<const T**> (j.i_);
+ }
+
+ template <typename T>
+ inline var_iterator<T>
+ operator+ (ptrdiff_t n, var_iterator<T> i)
+ {
+ return var_iterator<T> (i.i_ + n);
+ }
+
+ template <typename T>
+ inline var_iterator<T>
+ operator+ (ptrdiff_t n, var_const_iterator<T> i)
+ {
+ return var_const_iterator<T> (i.i_ + n);
+ }
+
+ //
+ //
+ template <typename T>
+ 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<T> iterator;
+ typedef var_const_iterator<T> 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 <xsde/cxx/hybrid/sequence.ixx>
+#include <xsde/cxx/hybrid/sequence.txx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <new> // placement new
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ //
+ // pod_seq
+ //
+
+ template <typename T>
+ inline size_t pod_seq<T>::
+ max_size () const
+ {
+ return size_t (-1) / sizeof (T);
+ }
+
+ template <typename T>
+ inline void pod_seq<T>::
+ swap (pod_seq& x)
+ {
+ swap_ (x);
+ }
+
+ template <typename T>
+ inline T* pod_seq<T>::
+ begin ()
+ {
+ return static_cast<T*> (data_);
+ }
+
+ template <typename T>
+ inline const T* pod_seq<T>::
+ begin () const
+ {
+ // g++ 2.95 does not like static_cast here.
+ //
+ return (const T*) (data_);
+ }
+
+ template <typename T>
+ inline T* pod_seq<T>::
+ end ()
+ {
+ return static_cast<T*> (data_) + size_;
+ }
+
+ template <typename T>
+ inline const T* pod_seq<T>::
+ end () const
+ {
+ return ((const T*) (data_)) + size_;
+ }
+
+ template <typename T>
+ inline T& pod_seq<T>::
+ front ()
+ {
+ return *static_cast<T*> (data_);
+ }
+
+ template <typename T>
+ inline const T& pod_seq<T>::
+ front () const
+ {
+ return *((const T*) (data_));
+ }
+
+ template <typename T>
+ inline T& pod_seq<T>::
+ back ()
+ {
+ return static_cast<T*> (data_)[size_ - 1];
+ }
+
+ template <typename T>
+ inline const T& pod_seq<T>::
+ back () const
+ {
+ return ((const T*) (data_))[size_ - 1];
+ }
+
+ template <typename T>
+ inline T& pod_seq<T>::
+ operator[] (size_t i)
+ {
+ return static_cast<T*> (data_)[i];
+ }
+
+ template <typename T>
+ inline const T& pod_seq<T>::
+ operator[] (size_t i) const
+ {
+ return ((const T*) (data_))[i];
+ }
+
+ template <typename T>
+ inline void pod_seq<T>::
+ clear ()
+ {
+ size_ = 0;
+ }
+
+ template <typename T>
+ inline void pod_seq<T>::
+ pop_back ()
+ {
+ --size_;
+ }
+
+ template <typename T>
+ inline T* pod_seq<T>::
+ erase (T* i)
+ {
+ if (i != static_cast<T*> (data_) + (size_ - 1))
+ erase_ (i, sizeof (T), 0);
+ else
+ --size_;
+
+ return i;
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ template <typename T>
+ inline void pod_seq<T>::
+ push_back (const T& x)
+ {
+ if (capacity_ < size_ + 1)
+ grow_ (0, sizeof (T), 0);
+
+ static_cast<T*> (data_)[size_++] = x;
+ }
+
+ template <typename T>
+ inline T* pod_seq<T>::
+ insert (T* i, const T& x)
+ {
+ T* p = static_cast<T*> (insert_ (i, sizeof (T), 0, 0));
+ *p = x;
+ return p;
+ }
+
+ template <typename T>
+ inline void pod_seq<T>::
+ reserve (size_t n)
+ {
+ if (capacity_ < n)
+ grow_ (n, sizeof (T), 0);
+ }
+#else
+ template <typename T>
+ inline sequence_base::error pod_seq<T>::
+ 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<T*> (data_)[size_++] = x;
+
+ return r;
+ }
+
+ template <typename T>
+ inline sequence_base::error pod_seq<T>::
+ insert (T* i, const T& x)
+ {
+ T* p = static_cast<T*> (insert_ (i, sizeof (T), 0, 0));
+
+ if (p)
+ {
+ *p = x;
+ return error_none;
+ }
+ else
+ return error_no_memory;
+ }
+
+ template <typename T>
+ inline sequence_base::error pod_seq<T>::
+ insert (T* i, const T& x, T*& r)
+ {
+ T* p = static_cast<T*> (insert_ (i, sizeof (T), 0, 0));
+
+ if (p)
+ {
+ *p = x;
+ r = p;
+ return error_none;
+ }
+ else
+ return error_no_memory;
+ }
+
+ template <typename T>
+ inline sequence_base::error pod_seq<T>::
+ reserve (size_t n)
+ {
+ error r = error_none;
+ if (capacity_ < n)
+ r = grow_ (n, sizeof (T), 0);
+ return r;
+ }
+#endif
+
+ //
+ // fix_seq
+ //
+
+ template <typename T>
+ inline fix_seq<T>::
+ ~fix_seq ()
+ {
+ clear ();
+ }
+
+ template <typename T>
+ inline size_t fix_seq<T>::
+ max_size () const
+ {
+ return size_t (-1) / sizeof (T);
+ }
+
+ template <typename T>
+ inline void fix_seq<T>::
+ swap (fix_seq& x)
+ {
+ swap_ (x);
+ }
+
+ template <typename T>
+ inline T* fix_seq<T>::
+ begin ()
+ {
+ return static_cast<T*> (data_);
+ }
+
+ template <typename T>
+ inline const T* fix_seq<T>::
+ begin () const
+ {
+ return (const T*) (data_);
+ }
+
+ template <typename T>
+ inline T* fix_seq<T>::
+ end ()
+ {
+ return static_cast<T*> (data_) + size_;
+ }
+
+ template <typename T>
+ inline const T* fix_seq<T>::
+ end () const
+ {
+ return ((const T*) (data_)) + size_;
+ }
+
+ template <typename T>
+ inline T& fix_seq<T>::
+ front ()
+ {
+ return *static_cast<T*> (data_);
+ }
+
+ template <typename T>
+ inline const T& fix_seq<T>::
+ front () const
+ {
+ return *((const T*) (data_));
+ }
+
+ template <typename T>
+ inline T& fix_seq<T>::
+ back ()
+ {
+ return static_cast<T*> (data_)[size_ - 1];
+ }
+
+ template <typename T>
+ inline const T& fix_seq<T>::
+ back () const
+ {
+ return ((const T*) (data_))[size_ - 1];
+ }
+
+ template <typename T>
+ inline T& fix_seq<T>::
+ operator[] (size_t i)
+ {
+ return static_cast<T*> (data_)[i];
+ }
+
+ template <typename T>
+ inline const T& fix_seq<T>::
+ operator[] (size_t i) const
+ {
+ return ((const T*) (data_))[i];
+ }
+
+ template <typename T>
+ inline void fix_seq<T>::
+ pop_back ()
+ {
+ static_cast<T*> (data_)[size_ - 1].~T ();
+ --size_;
+ }
+
+ template <typename T>
+ inline T* fix_seq<T>::
+ erase (T* i)
+ {
+ if (i != static_cast<T*> (data_) + (size_ - 1))
+ erase_ (i, sizeof (T), &move_forward_);
+ else
+ {
+ static_cast<T*> (data_)[size_ - 1].~T ();
+ --size_;
+ }
+
+ return i;
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ template <typename T>
+ inline void fix_seq<T>::
+ push_back (const T& x)
+ {
+ if (capacity_ < size_ + 1)
+ grow_ (0, sizeof (T), &move_);
+
+ new (static_cast<T*> (data_) + size_) T (x);
+ size_++;
+ }
+
+ template <typename T>
+ inline T* fix_seq<T>::
+ insert (T* i, const T& x)
+ {
+ T* p = static_cast<T*> (
+ insert_ (i, sizeof (T), &move_, &move_backward_));
+ *p = x;
+ return p;
+ }
+
+ template <typename T>
+ inline void fix_seq<T>::
+ reserve (size_t n)
+ {
+ if (capacity_ < n)
+ grow_ (n, sizeof (T), &move_);
+ }
+#else
+ template <typename T>
+ inline sequence_base::error fix_seq<T>::
+ 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<T*> (data_) + size_) T (x);
+ size_++;
+ }
+
+ return r;
+ }
+
+ template <typename T>
+ inline sequence_base::error fix_seq<T>::
+ insert (T* i, const T& x)
+ {
+ T* p = static_cast<T*> (
+ insert_ (i, sizeof (T), &move_, &move_backward_));
+
+ if (p)
+ {
+ *p = x;
+ return error_none;
+ }
+ else
+ return error_no_memory;
+ }
+
+ template <typename T>
+ inline sequence_base::error fix_seq<T>::
+ insert (T* i, const T& x, T*& r)
+ {
+ T* p = static_cast<T*> (
+ insert_ (i, sizeof (T), &move_, &move_backward_));
+
+ if (p)
+ {
+ *p = x;
+ r = p;
+ return error_none;
+ }
+ else
+ return error_no_memory;
+ }
+
+ template <typename T>
+ inline sequence_base::error fix_seq<T>::
+ reserve (size_t n)
+ {
+ error r = error_none;
+ if (capacity_ < n)
+ r = grow_ (n, sizeof (T), &move_);
+ return r;
+ }
+#endif
+
+ //
+ // var_seq
+ //
+
+ template <typename T>
+ inline var_seq<T>::
+ ~var_seq ()
+ {
+ clear ();
+ }
+
+ template <typename T>
+ inline size_t var_seq<T>::
+ max_size () const
+ {
+ return size_t (-1) / sizeof (T*);
+ }
+
+ template <typename T>
+ inline void var_seq<T>::
+ swap (var_seq& x)
+ {
+ swap_ (x);
+ }
+
+ template <typename T>
+ inline var_iterator<T> var_seq<T>::
+ begin ()
+ {
+ return iterator (static_cast<T**> (data_));
+ }
+
+ template <typename T>
+ inline var_const_iterator<T> var_seq<T>::
+ begin () const
+ {
+ return const_iterator ((const T**) (data_));
+ }
+
+ template <typename T>
+ inline var_iterator<T> var_seq<T>::
+ end ()
+ {
+ return iterator (static_cast<T**> (data_) + size_);
+ }
+
+ template <typename T>
+ inline var_const_iterator<T> var_seq<T>::
+ end () const
+ {
+ return const_iterator (((const T**) (data_)) + size_);
+ }
+
+ template <typename T>
+ inline T& var_seq<T>::
+ front ()
+ {
+ return **static_cast<T**> (data_);
+ }
+
+ template <typename T>
+ inline const T& var_seq<T>::
+ front () const
+ {
+ // g++ 2.95 does not like static_cast here.
+ //
+ return **((const T* const*) (data_));
+ }
+
+ template <typename T>
+ inline T& var_seq<T>::
+ back ()
+ {
+ return *(static_cast<T**> (data_)[size_ - 1]);
+ }
+
+ template <typename T>
+ inline const T& var_seq<T>::
+ back () const
+ {
+ return *(((const T* const*) (data_))[size_ - 1]);
+ }
+
+ template <typename T>
+ inline T& var_seq<T>::
+ operator[] (size_t i)
+ {
+ return *(static_cast<T**> (data_)[i]);
+ }
+
+ template <typename T>
+ inline const T& var_seq<T>::
+ operator[] (size_t i) const
+ {
+ return *(((const T* const*) (data_))[i]);
+ }
+
+ template <typename T>
+ inline void var_seq<T>::
+ pop_back ()
+ {
+ delete static_cast<T**> (data_)[size_ - 1];
+ --size_;
+ }
+
+ template <typename T>
+ inline var_iterator<T> var_seq<T>::
+ erase (iterator i)
+ {
+ delete *i.i_;
+
+ if (i.i_ != static_cast<T**> (data_) + (size_ - 1))
+ erase_ (i.i_, sizeof (T*), 0);
+ else
+ --size_;
+
+ return i;
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ template <typename T>
+ inline void var_seq<T>::
+ push_back (T* x)
+ {
+ guard g (x);
+
+ if (capacity_ < size_ + 1)
+ grow_ (0, sizeof (T*), 0);
+
+ static_cast<T**> (data_)[size_++] = x;
+
+ g.release ();
+ }
+
+ template <typename T>
+ inline var_iterator<T> var_seq<T>::
+ insert (iterator i, T* x)
+ {
+ guard g (x);
+ T** p = static_cast<T**> (insert_ (i.i_, sizeof (T*), 0, 0));
+ *p = x;
+ g.release ();
+ return iterator (p);
+ }
+
+ template <typename T>
+ inline void var_seq<T>::
+ reserve (size_t n)
+ {
+ if (capacity_ < n)
+ grow_ (n, sizeof (T*), 0);
+ }
+#else
+ template <typename T>
+ inline sequence_base::error var_seq<T>::
+ push_back (T* x)
+ {
+ error r = error_none;
+
+ if (capacity_ < size_ + 1)
+ r = grow_ (0, sizeof (T*), 0);
+
+ if (r == error_none)
+ static_cast<T**> (data_)[size_++] = x;
+ else
+ delete x;
+
+ return r;
+ }
+
+ template <typename T>
+ inline sequence_base::error var_seq<T>::
+ insert (iterator i, T* x)
+ {
+ T** p = static_cast<T**> (insert_ (i.i_, sizeof (T*), 0, 0));
+
+ if (p)
+ {
+ *p = x;
+ return error_none;
+ }
+ else
+ {
+ delete x;
+ return error_no_memory;
+ }
+ }
+
+ template <typename T>
+ inline sequence_base::error var_seq<T>::
+ insert (iterator i, T* x, iterator& r)
+ {
+ T** p = static_cast<T**> (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 <typename T>
+ inline sequence_base::error var_seq<T>::
+ 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<void**> (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<void**> (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<void**> (data_);
+ }
+
+ inline const void* data_seq::
+ front () const
+ {
+ return *((const void* const*) (data_));
+ }
+
+ inline void* data_seq::
+ back ()
+ {
+ return static_cast<void**> (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<void**> (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<void**> (data_)[size_ - 1], size_ - 1);
+ --size_;
+ }
+
+ inline data_seq::iterator data_seq::
+ erase (iterator i)
+ {
+ if (destructor_)
+ destructor_ (*i, i - static_cast<void**> (data_));
+
+ if (i != static_cast<void**> (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<void**> (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<void**> (data_));
+
+ void** p = static_cast<void**> (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<void**> (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<void**> (data_);
+ void** p = static_cast<void**> (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<void**> (data_);
+ void** p = static_cast<void**> (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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <new> // placement new
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ //
+ // fix_seq
+ //
+
+ template <typename T>
+ void fix_seq<T>::
+ clear ()
+ {
+ for (size_t i = 0; i < size_; ++i)
+ static_cast<T*> (data_)[i].~T ();
+
+ size_ = 0;
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ template <typename T>
+ void fix_seq<T>::
+ move_ (void* dst, void* src, size_t n)
+ {
+ T* d = static_cast<T*> (dst);
+ T* s = static_cast<T*> (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 <typename T>
+ void fix_seq<T>::
+ move_ (void* dst, void* src, size_t n)
+ {
+ T* d = static_cast<T*> (dst);
+ T* s = static_cast<T*> (src);
+
+ for (size_t i = 0; i < n; i++)
+ {
+ new (d + i) T (s[i]);
+ s[i].~T ();
+ }
+ }
+#endif
+
+ template <typename T>
+ void fix_seq<T>::
+ 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<T*> (p);
+
+ for (size_t i = 0; i < n; i++)
+ d[i] = d[i + 1];
+
+ d[n].~T ();
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ template <typename T>
+ void fix_seq<T>::
+ 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<T*> (p);
+ T* e = d + n;
+
+ new (e) T;
+ size++;
+
+ for (size_t i = n; i > 0; i--)
+ d[i] = d[i - 1];
+ }
+#else
+ template <typename T>
+ void fix_seq<T>::
+ move_backward_ (void* p, size_t n)
+ {
+ // We are moving a sequence of elements one position to the right.
+ //
+ T* d = static_cast<T*> (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 <typename T>
+ void var_seq<T>::
+ clear ()
+ {
+ for (size_t i = 0; i < size_; ++i)
+ delete static_cast<T**> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/buffer.hxx>
+#include <xsde/cxx/date-time.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/qname-stl.hxx>
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/qname.hxx>
+# include <xsde/cxx/string-sequence.hxx>
+#endif
+
+#include <xsde/cxx/hybrid/base.hxx>
+#include <xsde/cxx/hybrid/any-type.hxx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/context.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/c/expat/expat.h>
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/sys-error.hxx>
+#endif
+
+#ifdef XSDE_PARSER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#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 <xsde/cxx/parser/context.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <assert.h>
+
+#include <xsde/cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+
+#ifdef XSDE_PARSER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#endif
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/sys-error.hxx>
+# include <xsde/cxx/parser/error.hxx>
+#endif
+
+#include <xsde/cxx/parser/context.hxx>
+
+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 "<name> <namespace>" 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 "<name> <namespace>" 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 <xsde/cxx/parser/elements.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+#include <xsde/cxx/sys-error.hxx>
+
+#include <xsde/cxx/parser/expat/xml-error.hxx>
+
+#ifdef XSDE_PARSER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#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 <xsde/cxx/parser/error.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#ifdef XSDE_IOSTREAM
+# include <iostream>
+#endif
+
+#include <xsde/cxx/parser/exceptions.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_IOSTREAM
+# include <iosfwd>
+#endif
+
+#include <xsde/cxx/exceptions.hxx> // xsde::cxx::exception
+
+#ifdef XSDE_PARSER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#endif
+
+#include <xsde/cxx/parser/expat/xml-error.hxx>
+
+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 <xsde/cxx/parser/exceptions.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <assert.h>
+#include <string.h> // strchr, strlen
+
+#ifdef XSDE_EXCEPTIONS
+# include <new> // std::bad_alloc
+#endif
+
+#ifdef XSDE_IOSTREAM
+# include <iostream>
+# include <fstream>
+#endif
+
+#ifdef XSDE_EXCEPTIONS
+# include <xsde/cxx/parser/exceptions.hxx>
+#endif
+
+#ifdef XSDE_POLYMORPHIC
+# include <xsde/cxx/parser/substitution-map.hxx>
+#endif
+
+#include <xsde/cxx/parser/expat/document.hxx>
+
+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<const char*> (data),
+ static_cast<int> (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<document_pimpl*> (p);
+ doc.start_element_ (name, ats);
+ }
+
+ void XMLCALL document_pimpl::
+ end_element (void* p, const XML_Char* name)
+ {
+ document_pimpl& doc = *reinterpret_cast<document_pimpl*> (p);
+ doc.end_element_ (name);
+ }
+
+ void XMLCALL document_pimpl::
+ characters (void* p, const XML_Char* s, int n)
+ {
+ document_pimpl& doc = *reinterpret_cast<document_pimpl*> (p);
+ doc.characters_ (s, static_cast<size_t> (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<document_pimpl*> (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<document_pimpl*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#ifdef XSDE_IOSTREAM
+# include <iosfwd>
+#endif
+
+#include <xsde/c/expat/expat.h>
+
+// We only support UTF-8 expat for now.
+//
+#ifdef XML_UNICODE
+#error UTF-16 expat (XML_UNICODE defined) is not supported
+#endif
+
+#include <xsde/cxx/string.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/string-sequence.hxx>
+#endif
+
+#include <xsde/cxx/parser/context.hxx>
+#include <xsde/cxx/parser/elements.hxx>
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/parser/error.hxx>
+#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 "<name> <namespace>" 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 <xsde/cxx/parser/expat/document.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/expat/xml-error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/c/expat/expat.h>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/map.hxx>
+
+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<parser_base* const*> (*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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+#include <xsde/cxx/parser/elements.hxx>
+
+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
+ // "<name> <namespace>" 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 <xsde/cxx/parser/map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<parser_base* const*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/base64-binary.hxx>
+
+static unsigned char
+base64_decode (char c)
+{
+ unsigned char r = 0xFF;
+
+ if (c >= 'A' && c <= 'Z')
+ r = static_cast<unsigned char> (c - 'A');
+ else if (c >= 'a' && c <= 'z')
+ r = static_cast<unsigned char> (c - 'a' + 26);
+ else if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/boolean.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/byte.hxx>
+
+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<signed char> (-static_cast<short> (ul))
+ : static_cast<signed char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul, strtod
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/date-time.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/date.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/parser/non-validating/decimal.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/parser/non-validating/double.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul, strtod
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/duration.hxx>
+
+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<unsigned int> (strtoul (s + pos + 1, 0, 10));
+ }
+
+ if (s[pos] == 'H')
+ {
+ str_.truncate (pos);
+ pos = rfind_delim (s, pos - 1);
+
+ hours =
+ static_cast<unsigned int> (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<unsigned int> (strtoul (s + pos + 1, 0, 10));
+ }
+
+ if (s[pos] == 'M')
+ {
+ str_.truncate (pos);
+ pos = rfind_delim (s, pos - 1);
+
+ months =
+ static_cast<unsigned int> (strtoul (s + pos + 1, 0, 10));
+ }
+
+ if (s[pos] == 'Y')
+ {
+ str_.truncate (pos);
+ pos = rfind_delim (s, pos - 1);
+
+ years =
+ static_cast<unsigned int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtof, strtod
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/float.hxx>
+
+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<float> (strtod (sign_ == minus ? "-INF" : "INF", 0));
+#endif
+ }
+ else if (tmp == "NaN")
+ {
+#ifdef XSDE_STRTOF
+ r = strtof ("NAN", 0);
+#else
+ r = static_cast<float> (strtod ("NAN", 0));
+#endif
+ }
+ else
+ {
+#ifdef XSDE_STRTOF
+ r = strtof (str_, 0);
+#else
+ r = static_cast<float> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/gday.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/gmonth-day.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/gmonth.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/gyear-month.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/gyear.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/hex-binary.hxx>
+
+static unsigned char
+hex_decode (char c)
+{
+ unsigned char r = 0xFF;
+
+ if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ r = static_cast<unsigned char> (10 + (c - 'A'));
+ else if (c >= 'a' && c <= 'f')
+ r = static_cast<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/id-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/id.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/idref.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/pre.hxx>
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/idrefs-stl.hxx>
+
+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 <xsde/cxx/post.hxx>
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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/non-validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/pre.hxx>
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/idrefs.hxx>
+
+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 <xsde/cxx/post.hxx>
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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/non-validating/idref.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/int.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN, LONG_MAX
+
+#include <xsde/cxx/parser/non-validating/integer.hxx>
+
+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<unsigned long> (LONG_MIN)
+ ? LONG_MIN : -static_cast<long> (ul))
+ : static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/language-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/language.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoull
+
+#include <xsde/cxx/parser/non-validating/long-long.hxx>
+
+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<long long> (ull))
+ : static_cast<long long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/long.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/name-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/name.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/ncname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/ncname.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN
+
+#include <xsde/cxx/parser/non-validating/negative-integer.hxx>
+
+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<unsigned long> (LONG_MIN))
+ ? LONG_MIN : -static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/nmtoken-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/nmtoken.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/nmtokens-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/non-validating/nmtoken-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/nmtokens.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/non-validating/nmtoken.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/non-negative-integer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN
+
+#include <xsde/cxx/parser/non-validating/non-positive-integer.hxx>
+
+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<unsigned long> (LONG_MIN))
+ ? LONG_MIN : -static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/normalized-string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/normalized-string.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy
+
+#include <xsde/cxx/parser/non-validating/number.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/ro-string.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <assert.h>
+
+#include <xsde/cxx/parser/non-validating/parser.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/string.hxx>
+#include <xsde/cxx/ro-string.hxx>
+
+#include <xsde/cxx/parser/elements.hxx>
+#include <xsde/cxx/parser/state.hxx>
+
+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 <xsde/cxx/parser/non-validating/parser.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/positive-integer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/qname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/qname.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/short.hxx>
+
+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<short> (-static_cast<int> (ul))
+ : static_cast<short> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/string.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/time.hxx>
+#include <xsde/cxx/parser/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/token-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/token.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/unsigned-byte.hxx>
+
+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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/unsigned-int.hxx>
+
+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<unsigned int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoull
+
+#include <xsde/cxx/parser/non-validating/unsigned-long-long.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/unsigned-long.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/non-validating/unsigned-short.hxx>
+
+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<unsigned short> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/number.hxx>
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/uri-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/uri.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+#include <xsde/cxx/parser/non-validating/any-type.hxx>
+#include <xsde/cxx/parser/non-validating/boolean.hxx>
+#include <xsde/cxx/parser/non-validating/byte.hxx>
+#include <xsde/cxx/parser/non-validating/unsigned-byte.hxx>
+#include <xsde/cxx/parser/non-validating/byte.hxx>
+#include <xsde/cxx/parser/non-validating/unsigned-byte.hxx>
+#include <xsde/cxx/parser/non-validating/short.hxx>
+#include <xsde/cxx/parser/non-validating/unsigned-short.hxx>
+#include <xsde/cxx/parser/non-validating/int.hxx>
+#include <xsde/cxx/parser/non-validating/unsigned-int.hxx>
+
+#ifdef XSDE_LONGLONG
+# include <xsde/cxx/parser/non-validating/long-long.hxx>
+# include <xsde/cxx/parser/non-validating/unsigned-long-long.hxx>
+#else
+# include <xsde/cxx/parser/non-validating/long.hxx>
+# include <xsde/cxx/parser/non-validating/unsigned-long.hxx>
+#endif
+
+#include <xsde/cxx/parser/non-validating/integer.hxx>
+#include <xsde/cxx/parser/non-validating/negative-integer.hxx>
+#include <xsde/cxx/parser/non-validating/non-positive-integer.hxx>
+#include <xsde/cxx/parser/non-validating/positive-integer.hxx>
+#include <xsde/cxx/parser/non-validating/non-negative-integer.hxx>
+#include <xsde/cxx/parser/non-validating/float.hxx>
+#include <xsde/cxx/parser/non-validating/double.hxx>
+#include <xsde/cxx/parser/non-validating/decimal.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/parser/non-validating/string-stl.hxx>
+# include <xsde/cxx/parser/non-validating/normalized-string-stl.hxx>
+# include <xsde/cxx/parser/non-validating/token-stl.hxx>
+# include <xsde/cxx/parser/non-validating/name-stl.hxx>
+# include <xsde/cxx/parser/non-validating/nmtoken-stl.hxx>
+# include <xsde/cxx/parser/non-validating/nmtokens-stl.hxx>
+# include <xsde/cxx/parser/non-validating/ncname-stl.hxx>
+# include <xsde/cxx/parser/non-validating/id-stl.hxx>
+# include <xsde/cxx/parser/non-validating/idref-stl.hxx>
+# include <xsde/cxx/parser/non-validating/idrefs-stl.hxx>
+# include <xsde/cxx/parser/non-validating/language-stl.hxx>
+# include <xsde/cxx/parser/non-validating/uri-stl.hxx>
+# include <xsde/cxx/parser/non-validating/qname-stl.hxx>
+#else
+# include <xsde/cxx/parser/non-validating/string.hxx>
+# include <xsde/cxx/parser/non-validating/normalized-string.hxx>
+# include <xsde/cxx/parser/non-validating/token.hxx>
+# include <xsde/cxx/parser/non-validating/name.hxx>
+# include <xsde/cxx/parser/non-validating/nmtoken.hxx>
+# include <xsde/cxx/parser/non-validating/nmtokens.hxx>
+# include <xsde/cxx/parser/non-validating/ncname.hxx>
+# include <xsde/cxx/parser/non-validating/id.hxx>
+# include <xsde/cxx/parser/non-validating/idref.hxx>
+# include <xsde/cxx/parser/non-validating/idrefs.hxx>
+# include <xsde/cxx/parser/non-validating/language.hxx>
+# include <xsde/cxx/parser/non-validating/uri.hxx>
+# include <xsde/cxx/parser/non-validating/qname.hxx>
+#endif
+
+#include <xsde/cxx/parser/non-validating/base64-binary.hxx>
+#include <xsde/cxx/parser/non-validating/hex-binary.hxx>
+
+#include <xsde/cxx/parser/non-validating/gday.hxx>
+#include <xsde/cxx/parser/non-validating/gmonth.hxx>
+#include <xsde/cxx/parser/non-validating/gyear.hxx>
+#include <xsde/cxx/parser/non-validating/gmonth-day.hxx>
+#include <xsde/cxx/parser/non-validating/gyear-month.hxx>
+#include <xsde/cxx/parser/non-validating/date.hxx>
+#include <xsde/cxx/parser/non-validating/time.hxx>
+#include <xsde/cxx/parser/non-validating/date-time.hxx>
+#include <xsde/cxx/parser/non-validating/duration.hxx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#include <xsde/cxx/parser/xml-schema.hxx>
+
+#include <xsde/cxx/parser/non-validating/parser.hxx>
+
+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 <xsde/cxx/parser/non-validating/xml-schema-pskel.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy
+
+#include <xsde/cxx/parser/state.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/parser/elements.hxx>
+
+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 <xsde/cxx/parser/state.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<parser_state*> (stack_.top ()) = s;
+ return stack::error_none;
+ }
+
+ inline void parser_stack::
+ pop ()
+ {
+ stack_.pop ();
+ }
+
+ inline parser_state& parser_stack::
+ top ()
+ {
+ return *static_cast<parser_state*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <string.h> // strlen, strcmp, strncmp
+
+#ifndef XSDE_EXCEPTIONS
+# include <assert.h> // assert
+# include <stdlib.h> // exit
+#endif
+
+#include <xsde/cxx/parser/substitution-map.hxx>
+#include <xsde/cxx/parser/substitution-map-load.hxx>
+
+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<const value*> (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<const value*> (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<const char*> (p) + sizeof (bucket);
+ const char* e = b + p->size_ * el_size;
+
+ for (; b < e; b += el_size)
+ {
+ const element* e = reinterpret_cast<const element*> (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<const value*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+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 <xsde/cxx/parser/substitution-map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/base64-binary.hxx>
+
+static unsigned char
+base64_decode (char c)
+{
+ unsigned char r = 0xFF;
+
+ if (c >= 'A' && c <= 'Z')
+ r = static_cast<unsigned char> (c - 'A');
+ else if (c >= 'a' && c <= 'z')
+ r = static_cast<unsigned char> (c - 'a' + 26);
+ else if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/boolean.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/validating/byte.hxx>
+
+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<signed char> (-static_cast<short> (ul))
+ : static_cast<signed char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul, strtod
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/date-time.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/date.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/decimal.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/double.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul, strtod
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/duration.hxx>
+
+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<unsigned int> (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<unsigned int> (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<unsigned int> (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<unsigned int> (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<unsigned int> (ul);
+ }
+
+ // Something did not match or appeared in the wrong order.
+ //
+ if (pos != static_cast<size_type> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtof, strtod
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/float.hxx>
+
+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<float> (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<float> (strtod ("-INF", 0));
+#endif
+ break;
+ }
+ }
+ }
+ else if (tmp == "NaN")
+ {
+ if (sign_ == none)
+ {
+#ifdef XSDE_STRTOF
+ value_ = strtof ("NAN", 0);
+#else
+ value_ = static_cast<float> (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<float> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/gday.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/gmonth-day.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/gmonth.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/gyear-month.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/gyear.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/hex-binary.hxx>
+
+static unsigned char
+hex_decode (char c)
+{
+ unsigned char r = 0xFF;
+
+ if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ r = static_cast<unsigned char> (10 + (c - 'A'));
+ else if (c >= 'a' && c <= 'f')
+ r = static_cast<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/id-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/id.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/idref.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/pre.hxx>
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/idrefs-stl.hxx>
+
+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 <xsde/cxx/post.hxx>
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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/pre.hxx>
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/idrefs.hxx>
+
+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 <xsde/cxx/post.hxx>
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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/validating/idref.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <string.h> // strcmp
+
+#ifndef XSDE_EXCEPTIONS
+# include <assert.h> // assert
+# include <stdlib.h> // exit
+#endif
+
+#include <xsde/cxx/parser/validating/inheritance-map.hxx>
+#include <xsde/cxx/parser/validating/inheritance-map-load.hxx>
+
+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<const char* const*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+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 <xsde/cxx/parser/validating/inheritance-map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/int.hxx>
+
+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<int> (ul))
+ : static_cast<int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN, LONG_MAX
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/integer.hxx>
+
+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<unsigned long> (LONG_MIN)) ||
+ (!neg && ul > LONG_MAX))
+ _schema_error (schema_error::invalid_integer_value);
+
+ value_ = neg
+ ? (ul == static_cast<unsigned long> (LONG_MIN)
+ ? LONG_MIN: -static_cast<long> (ul))
+ : static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/language-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/language.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoull
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/long-long.hxx>
+
+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<long long> (ull))
+ : static_cast<long long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/long.hxx>
+
+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<long> (ul))
+ : static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/parser/validating/name-stl.hxx>
+
+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<unsigned char> (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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/parser/validating/name.hxx>
+
+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<unsigned char> (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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/ncname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/ncname.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/negative-integer.hxx>
+
+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<unsigned long> (LONG_MIN))
+ _schema_error (schema_error::invalid_negative_integer_value);
+
+ value_ = ul == static_cast<unsigned long> (LONG_MIN)
+ ? LONG_MIN : -static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/parser/validating/nmtoken-stl.hxx>
+
+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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/parser/validating/nmtoken.hxx>
+
+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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/nmtokens-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/validating/nmtoken-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/nmtokens.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+#include <xsde/cxx/parser/validating/nmtoken.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/non-negative-integer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+#include <limits.h> // LONG_MIN
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/non-positive-integer.hxx>
+
+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<unsigned long> (LONG_MIN))
+ _schema_error (schema_error::invalid_non_positive_integer_value);
+
+ value_ = ul == static_cast<unsigned long> (LONG_MIN)
+ ? LONG_MIN : -static_cast<long> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/normalized-string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/normalized-string.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy
+
+#include <xsde/cxx/parser/validating/number.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/ro-string.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <assert.h>
+
+#include <xsde/cxx/parser/validating/parser.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/string.hxx>
+#include <xsde/cxx/ro-string.hxx>
+
+#include <xsde/cxx/parser/elements.hxx>
+#include <xsde/cxx/parser/state.hxx>
+
+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 <xsde/cxx/parser/validating/parser.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<unsigned char*> (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<unsigned char*> (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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/positive-integer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/qname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/parser/validating/qname.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/validating/short.hxx>
+
+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<short> (-static_cast<int> (ul))
+ : static_cast<short> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/string.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtod
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/time.hxx>
+#include <xsde/cxx/parser/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/token-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/token.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/validating/unsigned-byte.hxx>
+
+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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/unsigned-int.hxx>
+
+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<unsigned int> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoull
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/unsigned-long-long.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/errno.hxx>
+
+#include <xsde/cxx/parser/validating/unsigned-long.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdlib.h> // strtoul
+
+#include <xsde/cxx/parser/validating/unsigned-short.hxx>
+
+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<unsigned short> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/number.hxx>
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/uri-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/validating/uri.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/string.hxx>
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+#include <xsde/cxx/parser/validating/any-type.hxx>
+#include <xsde/cxx/parser/validating/boolean.hxx>
+#include <xsde/cxx/parser/validating/byte.hxx>
+#include <xsde/cxx/parser/validating/unsigned-byte.hxx>
+#include <xsde/cxx/parser/validating/byte.hxx>
+#include <xsde/cxx/parser/validating/unsigned-byte.hxx>
+#include <xsde/cxx/parser/validating/short.hxx>
+#include <xsde/cxx/parser/validating/unsigned-short.hxx>
+#include <xsde/cxx/parser/validating/int.hxx>
+#include <xsde/cxx/parser/validating/unsigned-int.hxx>
+
+#ifdef XSDE_LONGLONG
+# include <xsde/cxx/parser/validating/long-long.hxx>
+# include <xsde/cxx/parser/validating/unsigned-long-long.hxx>
+#else
+# include <xsde/cxx/parser/validating/long.hxx>
+# include <xsde/cxx/parser/validating/unsigned-long.hxx>
+#endif
+
+#include <xsde/cxx/parser/validating/integer.hxx>
+#include <xsde/cxx/parser/validating/negative-integer.hxx>
+#include <xsde/cxx/parser/validating/non-positive-integer.hxx>
+#include <xsde/cxx/parser/validating/positive-integer.hxx>
+#include <xsde/cxx/parser/validating/non-negative-integer.hxx>
+#include <xsde/cxx/parser/validating/float.hxx>
+#include <xsde/cxx/parser/validating/double.hxx>
+#include <xsde/cxx/parser/validating/decimal.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/parser/validating/string-stl.hxx>
+# include <xsde/cxx/parser/validating/normalized-string-stl.hxx>
+# include <xsde/cxx/parser/validating/token-stl.hxx>
+# include <xsde/cxx/parser/validating/name-stl.hxx>
+# include <xsde/cxx/parser/validating/nmtoken-stl.hxx>
+# include <xsde/cxx/parser/validating/nmtokens-stl.hxx>
+# include <xsde/cxx/parser/validating/ncname-stl.hxx>
+# include <xsde/cxx/parser/validating/id-stl.hxx>
+# include <xsde/cxx/parser/validating/idref-stl.hxx>
+# include <xsde/cxx/parser/validating/idrefs-stl.hxx>
+# include <xsde/cxx/parser/validating/language-stl.hxx>
+# include <xsde/cxx/parser/validating/uri-stl.hxx>
+# include <xsde/cxx/parser/validating/qname-stl.hxx>
+#else
+# include <xsde/cxx/parser/validating/string.hxx>
+# include <xsde/cxx/parser/validating/normalized-string.hxx>
+# include <xsde/cxx/parser/validating/token.hxx>
+# include <xsde/cxx/parser/validating/name.hxx>
+# include <xsde/cxx/parser/validating/nmtoken.hxx>
+# include <xsde/cxx/parser/validating/nmtokens.hxx>
+# include <xsde/cxx/parser/validating/ncname.hxx>
+# include <xsde/cxx/parser/validating/id.hxx>
+# include <xsde/cxx/parser/validating/idref.hxx>
+# include <xsde/cxx/parser/validating/idrefs.hxx>
+# include <xsde/cxx/parser/validating/language.hxx>
+# include <xsde/cxx/parser/validating/uri.hxx>
+# include <xsde/cxx/parser/validating/qname.hxx>
+#endif
+
+#include <xsde/cxx/parser/validating/base64-binary.hxx>
+#include <xsde/cxx/parser/validating/hex-binary.hxx>
+
+#include <xsde/cxx/parser/validating/gday.hxx>
+#include <xsde/cxx/parser/validating/gmonth.hxx>
+#include <xsde/cxx/parser/validating/gyear.hxx>
+#include <xsde/cxx/parser/validating/gmonth-day.hxx>
+#include <xsde/cxx/parser/validating/gyear-month.hxx>
+#include <xsde/cxx/parser/validating/date.hxx>
+#include <xsde/cxx/parser/validating/time.hxx>
+#include <xsde/cxx/parser/validating/date-time.hxx>
+#include <xsde/cxx/parser/validating/duration.hxx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#include <xsde/cxx/parser/xml-schema.hxx>
+
+#include <xsde/cxx/parser/validating/parser.hxx>
+
+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 <xsde/cxx/parser/validating/xml-schema-pskel.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/buffer.hxx>
+#include <xsde/cxx/date-time.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/qname-stl.hxx>
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/qname.hxx>
+# include <xsde/cxx/string-sequence.hxx>
+#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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/compilers/vc-8/post.hxx>
+# elif (_MSC_VER >= 1300)
+# include <xsde/cxx/compilers/vc-7/post.hxx>
+# elif (_MSC_VER >= 1200)
+# include <xsde/cxx/compilers/vc-6/post.hxx>
+# 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/compilers/vc-8/pre.hxx>
+# elif (_MSC_VER >= 1300)
+# include <xsde/cxx/compilers/vc-7/pre.hxx>
+# elif (_MSC_VER >= 1200)
+# include <xsde/cxx/compilers/vc-6/pre.hxx>
+# 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 <boris@codesynthesis.com>
+// 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 <string>
+
+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 <xsde/cxx/qname-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen, memcpy
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/qname.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+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 <xsde/cxx/qname.ixx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/ro-string.hxx>
+
+#ifdef XSDE_IOSTREAM
+# include <iostream>
+#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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#ifdef XSDE_IOSTREAM
+# include <iosfwd>
+#endif
+
+#include <xsde/cxx/string.hxx>
+
+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 <xsde/cxx/ro-string.ixx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/schema-error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/schema-error.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy, memmove
+
+#include <xsde/cxx/sequence-base.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ void sequence_base::
+ erase_ (void* vp, size_t es, move_forward_func mv)
+ {
+ char* p = static_cast<char*> (vp);
+ char* d = static_cast<char*> (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<char*> (vp) - static_cast<char*> (data_);
+
+ if (capacity_ < size_ + 1)
+ grow_ (0, es, mv);
+
+ char* d = static_cast<char*> (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<char*> (vp) - static_cast<char*> (data_);
+
+ if (capacity_ < size_ + 1 && grow_ (0, es, mv) != error_none)
+ return 0;
+
+ char* d = static_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // 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 <xsde/cxx/sequence-base.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+
+#ifdef XSDE_EXCEPTIONS
+# include <new> // std::bad_alloc
+# include <xsde/cxx/serializer/exceptions.hxx>
+#endif
+
+#include <xsde/cxx/serializer/context.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/c/genx/genx.h>
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/sys-error.hxx>
+#endif
+
+#include <xsde/cxx/serializer/genx/xml-error.hxx>
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#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 <xsde/cxx/serializer/context.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<constUtf8> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (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<constUtf8> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (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<constUtf8> (name),
+ reinterpret_cast<constUtf8> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (name),
+ reinterpret_cast<constUtf8> (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<constUtf8> (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<constUtf8> (s),
+ static_cast<int> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (""));
+
+#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<constUtf8> (ns), 0, &e);
+
+ if (e != GENX_SUCCESS)
+ {
+#ifdef XSDE_EXCEPTIONS
+ throw_xml_error (e);
+#else
+ xml_error (e);
+#endif
+ return 0;
+ }
+
+ return reinterpret_cast<const char*> (
+ 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <assert.h>
+
+#include <xsde/cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/serializer/context.hxx>
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/serializer/error.hxx>
+#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 "<name> <namespace>" 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 "<name> <namespace>" 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 <xsde/cxx/serializer/elements.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+#include <xsde/cxx/sys-error.hxx>
+
+#include <xsde/cxx/serializer/genx/xml-error.hxx>
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#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 <xsde/cxx/serializer/error.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#ifdef XSDE_IOSTREAM
+# include <iostream>
+#endif
+
+#include <xsde/cxx/serializer/exceptions.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_IOSTREAM
+# include <iosfwd>
+#endif
+
+#include <xsde/cxx/exceptions.hxx> // xsde::cxx::exception
+
+#ifdef XSDE_SERIALIZER_VALIDATION
+# include <xsde/cxx/schema-error.hxx>
+#endif
+
+#include <xsde/cxx/serializer/genx/xml-error.hxx>
+
+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 <xsde/cxx/serializer/exceptions.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <string.h> // strlen, strcmp
+
+#ifdef XSDE_EXCEPTIONS
+# include <new> // std::bad_alloc
+#endif
+
+#ifdef XSDE_IOSTREAM
+# include <iostream>
+#endif
+
+#ifdef XSDE_EXCEPTIONS
+# include <xsde/cxx/serializer/exceptions.hxx>
+#else
+# include <xsde/cxx/serializer/error.hxx>
+#endif
+
+#include <xsde/cxx/serializer/context.hxx>
+
+#ifdef XSDE_POLYMORPHIC
+# include <xsde/cxx/serializer/substitution-map.hxx>
+#endif
+
+#include <xsde/cxx/serializer/genx/document.hxx>
+
+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<std::ostream*> (p);
+ os->write (s, static_cast<std::streamsize> (n));
+
+ if (os->bad ())
+ throw std::ios_base::failure ("write failed");
+ }
+
+ static void
+ ostream_flush (void* p)
+ {
+ std::ostream* os = reinterpret_cast<std::ostream*> (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<std::ostream*> (p);
+ os->write (s, static_cast<std::streamsize> (n));
+ return !os->bad ();
+ }
+
+ static bool
+ ostream_flush (void* p)
+ {
+ std::ostream* os = reinterpret_cast<std::ostream*> (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<writer*> (p)->write (s);
+ }
+
+ static void
+ write_bound_thunk (void* p, const char* s, size_t n)
+ {
+ reinterpret_cast<writer*> (p)->write (s, n);
+ }
+
+ static void
+ flush_thunk (void* p)
+ {
+ reinterpret_cast<writer*> (p)->flush ();
+ }
+#else
+ static bool
+ write_thunk (void* p, const char* s)
+ {
+ return reinterpret_cast<writer*> (p)->write (s);
+ }
+
+ static bool
+ write_bound_thunk (void* p, const char* s, size_t n)
+ {
+ return reinterpret_cast<writer*> (p)->write (s, n);
+ }
+
+ static bool
+ flush_thunk (void* p)
+ {
+ return reinterpret_cast<writer*> (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<const char*> (us);
+ writer_info* wi = reinterpret_cast<writer_info*> (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<size_t> (end - start);
+ const char* s = reinterpret_cast<const char*> (start);
+ writer_info* wi = reinterpret_cast<writer_info*> (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<writer_info*> (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<constUtf8> (root_ns_.data ()),
+ reinterpret_cast<constUtf8> (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<constUtf8> (ns),
+ reinterpret_cast<constUtf8> (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<constUtf8> (prefix_namespaces_[i].c_str ()),
+ reinterpret_cast<constUtf8> (prefixes_[i].c_str ()));
+#else
+ e = genxAddNamespaceLiteral (
+ s,
+ reinterpret_cast<constUtf8> (prefix_namespaces_[i]),
+ reinterpret_cast<constUtf8> (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<constUtf8> (xsi),
+ reinterpret_cast<constUtf8> ("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<constUtf8> (xsi),
+ reinterpret_cast<constUtf8> ("schemaLocation"));
+
+ if (e != GENX_SUCCESS)
+ break;
+
+ start = true;
+ }
+ else
+ {
+ e = genxAddCharacter (s, ' ');
+
+ if (e != GENX_SUCCESS)
+ break;
+ }
+
+ e = genxAddText (s, reinterpret_cast<constUtf8> (ns));
+
+ if (e != GENX_SUCCESS)
+ break;
+
+ e = genxAddCharacter (s, ' ');
+
+ if (e != GENX_SUCCESS)
+ break;
+
+ e = genxAddText (s, reinterpret_cast<constUtf8> (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<constUtf8> (xsi),
+ reinterpret_cast<constUtf8> ("noNamespaceSchemaLocation"));
+
+ if (e != GENX_SUCCESS)
+ break;
+
+ start = true;
+ }
+ else
+ {
+ e = genxAddCharacter (s, ' ');
+
+ if (e != GENX_SUCCESS)
+ break;
+ }
+
+ e = genxAddText (s, reinterpret_cast<constUtf8> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <stddef.h> // size_t
+
+#include <xsde/c/genx/genx.h>
+
+#ifdef XSDE_IOSTREAM
+# include <iosfwd>
+#endif
+
+#include <xsde/cxx/string.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/string-sequence.hxx>
+#endif
+
+#include <xsde/cxx/serializer/elements.hxx>
+
+#ifndef XSDE_EXCEPTIONS
+# include <xsde/cxx/serializer/error.hxx>
+#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 <xsde/cxx/serializer/genx/document.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/genx/xml-error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/c/genx/genx.h>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/map.hxx>
+
+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<serializer_base* const*> (*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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+#include <xsde/cxx/serializer/elements.hxx>
+
+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 <xsde/cxx/serializer/map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<const char*> (type_id));
+ return p ? *static_cast<serializer_base* const*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/base64-binary.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ base64_binary_simpl::
+ ~base64_binary_simpl ()
+ {
+ if (free_)
+ delete const_cast<buffer*> (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<unsigned char> (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<unsigned char> (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<unsigned char> (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<buffer*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/base64-binary.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/boolean.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/byte.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/date-time.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/date-time.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/date.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/date.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/decimal.hxx>
+
+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<int> (precision_), value_);
+#else
+ int n = sprintf (str, "%.*f",
+ static_cast<int> (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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/decimal.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/double.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/double.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/duration.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/duration.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/float.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/float.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/gday.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/gday.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/gmonth-day.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/gmonth-day.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/gmonth.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/gmonth.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/gyear-month.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/gyear-month.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/gyear.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/gyear.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/hex-binary.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ hex_binary_simpl::
+ ~hex_binary_simpl ()
+ {
+ if (free_)
+ delete const_cast<buffer*> (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<unsigned char> (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<buffer*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/hex-binary.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/id-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/id.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ id_simpl::
+ ~id_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void id_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void id_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/id.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/idref.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ idref_simpl::
+ ~idref_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void idref_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void idref_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/idref.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/idrefs-stl.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ idrefs_simpl::
+ ~idrefs_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/non-validating/idref-stl.hxx>
+
+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 <xsde/cxx/serializer/non-validating/idrefs-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/idrefs.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ idrefs_simpl::
+ ~idrefs_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/non-validating/idref.hxx>
+
+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 <xsde/cxx/serializer/non-validating/idrefs.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/int.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/language-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/language.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ language_simpl::
+ ~language_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void language_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void language_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/language.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/long-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/name-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/name.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ name_simpl::
+ ~name_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void name_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void name_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/name.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/ncname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/ncname.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ ncname_simpl::
+ ~ncname_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void ncname_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void ncname_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/ncname.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/negative-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/nmtoken-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/nmtoken.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ nmtoken_simpl::
+ ~nmtoken_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void nmtoken_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void nmtoken_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/nmtoken.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/nmtokens-stl.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ nmtokens_simpl::
+ ~nmtokens_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/non-validating/nmtoken-stl.hxx>
+
+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 <xsde/cxx/serializer/non-validating/nmtokens-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/nmtokens.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ nmtokens_simpl::
+ ~nmtokens_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/non-validating/nmtoken.hxx>
+
+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 <xsde/cxx/serializer/non-validating/nmtokens.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/non-negative-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/non-positive-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/normalized-string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/normalized-string.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ normalized_string_simpl::
+ ~normalized_string_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void normalized_string_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void normalized_string_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/normalized-string.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/positive-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/qname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/qname-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/qname.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ qname_simpl::
+ ~qname_simpl ()
+ {
+ if (free_)
+ delete const_cast<qname*> (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<qname*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/qname.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/serializer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/serializer/elements.hxx>
+
+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 <xsde/cxx/serializer/non-validating/serializer.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/short.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/string.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ string_simpl::
+ ~string_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void string_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void string_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/string.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/date-time.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/time.hxx>
+#include <xsde/cxx/serializer/non-validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/time.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/token-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/token.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ token_simpl::
+ ~token_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void token_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void token_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/token.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/unsigned-byte.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/unsigned-int.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/unsigned-long-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/unsigned-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/non-validating/unsigned-short.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/uri-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/uri.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace non_validating
+ {
+ uri_simpl::
+ ~uri_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void uri_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void uri_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/non-validating/uri.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+#include <xsde/cxx/serializer/non-validating/any-type.hxx>
+#include <xsde/cxx/serializer/non-validating/boolean.hxx>
+#include <xsde/cxx/serializer/non-validating/byte.hxx>
+#include <xsde/cxx/serializer/non-validating/unsigned-byte.hxx>
+#include <xsde/cxx/serializer/non-validating/byte.hxx>
+#include <xsde/cxx/serializer/non-validating/unsigned-byte.hxx>
+#include <xsde/cxx/serializer/non-validating/short.hxx>
+#include <xsde/cxx/serializer/non-validating/unsigned-short.hxx>
+#include <xsde/cxx/serializer/non-validating/int.hxx>
+#include <xsde/cxx/serializer/non-validating/unsigned-int.hxx>
+
+#ifdef XSDE_LONGLONG
+# include <xsde/cxx/serializer/non-validating/long-long.hxx>
+# include <xsde/cxx/serializer/non-validating/unsigned-long-long.hxx>
+#else
+# include <xsde/cxx/serializer/non-validating/long.hxx>
+# include <xsde/cxx/serializer/non-validating/unsigned-long.hxx>
+#endif
+
+#include <xsde/cxx/serializer/non-validating/integer.hxx>
+#include <xsde/cxx/serializer/non-validating/negative-integer.hxx>
+#include <xsde/cxx/serializer/non-validating/non-positive-integer.hxx>
+#include <xsde/cxx/serializer/non-validating/positive-integer.hxx>
+#include <xsde/cxx/serializer/non-validating/non-negative-integer.hxx>
+#include <xsde/cxx/serializer/non-validating/float.hxx>
+#include <xsde/cxx/serializer/non-validating/double.hxx>
+#include <xsde/cxx/serializer/non-validating/decimal.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/serializer/non-validating/string-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/normalized-string-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/token-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/name-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/nmtoken-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/nmtokens-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/ncname-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/id-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/idref-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/idrefs-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/language-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/uri-stl.hxx>
+# include <xsde/cxx/serializer/non-validating/qname-stl.hxx>
+#else
+# include <xsde/cxx/serializer/non-validating/string.hxx>
+# include <xsde/cxx/serializer/non-validating/normalized-string.hxx>
+# include <xsde/cxx/serializer/non-validating/token.hxx>
+# include <xsde/cxx/serializer/non-validating/name.hxx>
+# include <xsde/cxx/serializer/non-validating/nmtoken.hxx>
+# include <xsde/cxx/serializer/non-validating/nmtokens.hxx>
+# include <xsde/cxx/serializer/non-validating/ncname.hxx>
+# include <xsde/cxx/serializer/non-validating/id.hxx>
+# include <xsde/cxx/serializer/non-validating/idref.hxx>
+# include <xsde/cxx/serializer/non-validating/idrefs.hxx>
+# include <xsde/cxx/serializer/non-validating/language.hxx>
+# include <xsde/cxx/serializer/non-validating/uri.hxx>
+# include <xsde/cxx/serializer/non-validating/qname.hxx>
+#endif
+
+#include <xsde/cxx/serializer/non-validating/base64-binary.hxx>
+#include <xsde/cxx/serializer/non-validating/hex-binary.hxx>
+
+#include <xsde/cxx/serializer/non-validating/gday.hxx>
+#include <xsde/cxx/serializer/non-validating/gmonth.hxx>
+#include <xsde/cxx/serializer/non-validating/gyear.hxx>
+#include <xsde/cxx/serializer/non-validating/gmonth-day.hxx>
+#include <xsde/cxx/serializer/non-validating/gyear-month.hxx>
+#include <xsde/cxx/serializer/non-validating/date.hxx>
+#include <xsde/cxx/serializer/non-validating/time.hxx>
+#include <xsde/cxx/serializer/non-validating/date-time.hxx>
+#include <xsde/cxx/serializer/non-validating/duration.hxx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#include <xsde/cxx/serializer/xml-schema.hxx>
+
+#include <xsde/cxx/serializer/non-validating/serializer.hxx>
+
+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 <xsde/cxx/serializer/non-validating/xml-schema-sskel.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <string.h> // strlen, strcmp, strncmp
+
+#ifndef XSDE_EXCEPTIONS
+# include <assert.h> // assert
+# include <stdlib.h> // exit
+#endif
+
+#include <xsde/cxx/serializer/substitution-map.hxx>
+#include <xsde/cxx/serializer/substitution-map-load.hxx>
+
+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<hashmap**> (const_cast<void*> (*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<hashmap**> (const_cast<void*> (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<const char*> (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<const element*> (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<const hashmap* const*> (
+ b + sizeof (element));
+
+ // See if we have a direct substitution.
+ //
+ if (const value* v = static_cast<const value*> (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<const value*> (*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<const hashmap* const*> (*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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+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 <xsde/cxx/serializer/substitution-map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/base64-binary.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ base64_binary_simpl::
+ ~base64_binary_simpl ()
+ {
+ if (free_)
+ delete const_cast<buffer*> (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<unsigned char> (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<unsigned char> (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<unsigned char> (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<buffer*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/base64-binary.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/boolean.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/byte.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/date-time.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/date-time.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/date.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/date.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/decimal.hxx>
+
+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<int> (precision_), value_);
+#else
+ int n = sprintf (str, "%.*f",
+ static_cast<int> (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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/decimal.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/double.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/double.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/duration.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/duration.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/float.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <float.h>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/float.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/gday.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/gday.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/gmonth-day.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/gmonth-day.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/gmonth.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/gmonth.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/gyear-month.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/gyear-month.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/gyear.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/gyear.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/hex-binary.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ hex_binary_simpl::
+ ~hex_binary_simpl ()
+ {
+ if (free_)
+ delete const_cast<buffer*> (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<unsigned char> (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<buffer*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/hex-binary.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/id-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/id.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ id_simpl::
+ ~id_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/id.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/idref-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/idref.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ idref_simpl::
+ ~idref_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/idref.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/idrefs-stl.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ idrefs_simpl::
+ ~idrefs_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/validating/idref-stl.hxx>
+
+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 <xsde/cxx/serializer/validating/idrefs-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/idrefs.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ idrefs_simpl::
+ ~idrefs_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/validating/idref.hxx>
+
+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 <xsde/cxx/serializer/validating/idrefs.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <string.h> // strcmp
+
+#ifndef XSDE_EXCEPTIONS
+# include <assert.h> // assert
+# include <stdlib.h> // exit
+#endif
+
+#include <xsde/cxx/serializer/validating/inheritance-map.hxx>
+#include <xsde/cxx/serializer/validating/inheritance-map-load.hxx>
+
+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<const char* const*> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/ro-string.hxx>
+#include <xsde/cxx/hashmap.hxx>
+
+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 <xsde/cxx/serializer/validating/inheritance-map.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/int.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/language-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/language.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ language_simpl::
+ ~language_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/language.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/long-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/serializer/validating/name-stl.hxx>
+
+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<unsigned char> (*s);
+
+ ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask);
+
+ for (++s; ok && *s != '\0'; ++s)
+ {
+ c = static_cast<unsigned char> (*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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/serializer/validating/name.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ name_simpl::
+ ~name_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<unsigned char> (*s);
+
+ ok = c >= 0x80 || (xml::char_table[c] & xml::name_first_char_mask);
+
+ for (++s; ok && *s != '\0'; ++s)
+ {
+ c = static_cast<unsigned char> (*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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/name.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/ncname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/ncname.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ ncname_simpl::
+ ~ncname_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/ncname.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/negative-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/serializer/validating/nmtoken-stl.hxx>
+
+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<unsigned char> (*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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+#include <xsde/cxx/serializer/validating/nmtoken.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ nmtoken_simpl::
+ ~nmtoken_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<unsigned char> (*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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/nmtoken.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/nmtokens-stl.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ nmtokens_simpl::
+ ~nmtokens_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/validating/nmtoken-stl.hxx>
+
+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 <xsde/cxx/serializer/validating/nmtokens-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/nmtokens.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ nmtokens_simpl::
+ ~nmtokens_simpl ()
+ {
+ if (free_)
+ delete const_cast<string_sequence*> (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<string_sequence*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+#include <xsde/cxx/serializer/validating/nmtoken.hxx>
+
+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 <xsde/cxx/serializer/validating/nmtokens.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/non-negative-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/non-positive-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/normalized-string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/normalized-string.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ normalized_string_simpl::
+ ~normalized_string_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/normalized-string.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/positive-integer.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/qname-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/qname-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen
+
+#include <xsde/cxx/xml/ncname.hxx>
+
+#include <xsde/cxx/serializer/validating/qname.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ qname_simpl::
+ ~qname_simpl ()
+ {
+ if (free_)
+ delete const_cast<qname*> (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<qname*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/qname.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/serializer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/serializer/elements.hxx>
+
+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 <xsde/cxx/serializer/validating/serializer.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/short.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/string-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/string.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ string_simpl::
+ ~string_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (value_);
+ }
+
+ void string_simpl::
+ pre (const char* value)
+ {
+ value_ = value;
+ }
+
+ void string_simpl::
+ _serialize_content ()
+ {
+ _characters (value_);
+
+ if (free_)
+ {
+ delete[] const_cast<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/string.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/date-time.hxx>
+
+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 <xsde/cxx/serializer/validating/time-zone.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/time.hxx>
+#include <xsde/cxx/serializer/validating/time-zone.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/time.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/token-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/token.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ token_simpl::
+ ~token_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/token.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/unsigned-byte.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/unsigned-int.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/unsigned-long-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/unsigned-long.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <stdio.h> // sprintf/snprintf
+
+#include <xsde/cxx/serializer/validating/unsigned-short.hxx>
+
+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<size_t> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/uri-stl.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <string>
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/uri.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace serializer
+ {
+ namespace validating
+ {
+ uri_simpl::
+ ~uri_simpl ()
+ {
+ if (free_)
+ delete[] const_cast<char*> (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<char*> (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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <xsde/cxx/serializer/validating/uri.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+#include <xsde/cxx/serializer/validating/any-type.hxx>
+#include <xsde/cxx/serializer/validating/boolean.hxx>
+#include <xsde/cxx/serializer/validating/byte.hxx>
+#include <xsde/cxx/serializer/validating/unsigned-byte.hxx>
+#include <xsde/cxx/serializer/validating/byte.hxx>
+#include <xsde/cxx/serializer/validating/unsigned-byte.hxx>
+#include <xsde/cxx/serializer/validating/short.hxx>
+#include <xsde/cxx/serializer/validating/unsigned-short.hxx>
+#include <xsde/cxx/serializer/validating/int.hxx>
+#include <xsde/cxx/serializer/validating/unsigned-int.hxx>
+
+#ifdef XSDE_LONGLONG
+# include <xsde/cxx/serializer/validating/long-long.hxx>
+# include <xsde/cxx/serializer/validating/unsigned-long-long.hxx>
+#else
+# include <xsde/cxx/serializer/validating/long.hxx>
+# include <xsde/cxx/serializer/validating/unsigned-long.hxx>
+#endif
+
+#include <xsde/cxx/serializer/validating/integer.hxx>
+#include <xsde/cxx/serializer/validating/negative-integer.hxx>
+#include <xsde/cxx/serializer/validating/non-positive-integer.hxx>
+#include <xsde/cxx/serializer/validating/positive-integer.hxx>
+#include <xsde/cxx/serializer/validating/non-negative-integer.hxx>
+#include <xsde/cxx/serializer/validating/float.hxx>
+#include <xsde/cxx/serializer/validating/double.hxx>
+#include <xsde/cxx/serializer/validating/decimal.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/serializer/validating/string-stl.hxx>
+# include <xsde/cxx/serializer/validating/normalized-string-stl.hxx>
+# include <xsde/cxx/serializer/validating/token-stl.hxx>
+# include <xsde/cxx/serializer/validating/name-stl.hxx>
+# include <xsde/cxx/serializer/validating/nmtoken-stl.hxx>
+# include <xsde/cxx/serializer/validating/nmtokens-stl.hxx>
+# include <xsde/cxx/serializer/validating/ncname-stl.hxx>
+# include <xsde/cxx/serializer/validating/id-stl.hxx>
+# include <xsde/cxx/serializer/validating/idref-stl.hxx>
+# include <xsde/cxx/serializer/validating/idrefs-stl.hxx>
+# include <xsde/cxx/serializer/validating/language-stl.hxx>
+# include <xsde/cxx/serializer/validating/uri-stl.hxx>
+# include <xsde/cxx/serializer/validating/qname-stl.hxx>
+#else
+# include <xsde/cxx/serializer/validating/string.hxx>
+# include <xsde/cxx/serializer/validating/normalized-string.hxx>
+# include <xsde/cxx/serializer/validating/token.hxx>
+# include <xsde/cxx/serializer/validating/name.hxx>
+# include <xsde/cxx/serializer/validating/nmtoken.hxx>
+# include <xsde/cxx/serializer/validating/nmtokens.hxx>
+# include <xsde/cxx/serializer/validating/ncname.hxx>
+# include <xsde/cxx/serializer/validating/id.hxx>
+# include <xsde/cxx/serializer/validating/idref.hxx>
+# include <xsde/cxx/serializer/validating/idrefs.hxx>
+# include <xsde/cxx/serializer/validating/language.hxx>
+# include <xsde/cxx/serializer/validating/uri.hxx>
+# include <xsde/cxx/serializer/validating/qname.hxx>
+#endif
+
+#include <xsde/cxx/serializer/validating/base64-binary.hxx>
+#include <xsde/cxx/serializer/validating/hex-binary.hxx>
+
+#include <xsde/cxx/serializer/validating/gday.hxx>
+#include <xsde/cxx/serializer/validating/gmonth.hxx>
+#include <xsde/cxx/serializer/validating/gyear.hxx>
+#include <xsde/cxx/serializer/validating/gmonth-day.hxx>
+#include <xsde/cxx/serializer/validating/gyear-month.hxx>
+#include <xsde/cxx/serializer/validating/date.hxx>
+#include <xsde/cxx/serializer/validating/time.hxx>
+#include <xsde/cxx/serializer/validating/date-time.hxx>
+#include <xsde/cxx/serializer/validating/duration.hxx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/config.hxx>
+
+#ifdef XSDE_STL
+# include <string>
+#endif
+
+#include <xsde/cxx/serializer/xml-schema.hxx>
+
+#include <xsde/cxx/serializer/validating/serializer.hxx>
+
+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 <xsde/cxx/serializer/validating/xml-schema-sskel.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/buffer.hxx>
+#include <xsde/cxx/date-time.hxx>
+
+#ifdef XSDE_STL
+# include <xsde/cxx/qname-stl.hxx>
+# include <xsde/cxx/string-sequence-stl.hxx>
+#else
+# include <xsde/cxx/qname.hxx>
+# include <xsde/cxx/string-sequence.hxx>
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // strlen, memcpy
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/strdupx.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/string-sequence-stl.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ void string_sequence::
+ clear ()
+ {
+ typedef std::string type;
+ for (size_t i = 0; i < size_; ++i)
+ static_cast<std::string*> (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<std::string*> (dst);
+ std::string* s = static_cast<std::string*> (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<std::string*> (dst);
+ std::string* s = static_cast<std::string*> (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<std::string*> (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<std::string*> (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<std::string*> (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 <boris@codesynthesis.com>
+// 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 <string>
+#include <stddef.h> // size_t, ptrdiff_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/sequence-base.hxx>
+
+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 <xsde/cxx/string-sequence-stl.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<std::string*> (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<std::string*> (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<std::string*> (data_);
+ }
+
+ inline const std::string& string_sequence::
+ front () const
+ {
+ return *((const std::string*) (data_));
+ }
+
+ inline std::string& string_sequence::
+ back ()
+ {
+ return static_cast<std::string*> (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<std::string*> (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<std::string*> (data_)[size_ - 1].~type ();
+ --size_;
+ }
+
+ inline std::string* string_sequence::
+ erase (std::string* i)
+ {
+ if (i != static_cast<std::string*> (data_) + (size_ - 1))
+ erase_ (i, sizeof (std::string), &move_forward_);
+ else
+ {
+ typedef std::string type;
+ static_cast<std::string*> (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<std::string*> (data_) + size_) std::string (x);
+ size_++;
+ }
+
+ inline std::string* string_sequence::
+ insert (std::string* i, const std::string& x)
+ {
+ std::string* p = static_cast<std::string*> (
+ 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<std::string*> (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<std::string*> (
+ 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<std::string*> (
+ 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h> // memcpy, strlen, strcmp
+
+#include <xsde/cxx/string-sequence.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ void string_sequence::
+ clear ()
+ {
+ for (size_t i = 0; i < size_; ++i)
+ delete[] static_cast<char**> (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<char**> (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<char**> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // size_t, ptrdiff_t
+
+#include <xsde/cxx/config.hxx>
+#include <xsde/cxx/sequence-base.hxx>
+
+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 <xsde/cxx/string-sequence.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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<char**> (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<char**> (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<char**> (data_);
+ }
+
+ inline const char* string_sequence::
+ front () const
+ {
+ return *((const char* const*) (data_));
+ }
+
+ inline char* string_sequence::
+ back ()
+ {
+ return static_cast<char**> (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<char**> (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<char**> (data_)[size_ - 1];
+ --size_;
+ }
+
+ inline string_sequence::iterator string_sequence::
+ erase (iterator i)
+ {
+ delete[] *i;
+
+ if (i != static_cast<char**> (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<char**> (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<char**> (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<char**> (data_)[size_++] = x;
+ else
+ delete[] x;
+
+ return r;
+ }
+
+ inline sequence_base::error string_sequence::
+ insert (iterator i, char* x)
+ {
+ char** p = static_cast<char**> (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<char**> (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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h>
+
+#include <xsde/cxx/string.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <stddef.h> // 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 <xsde/cxx/string.ixx>
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <string.h>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/sys-error.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsde/cxx/sys-error.ixx>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/xml/char-table.hxx>
+#include <xsde/cxx/xml/ncname.hxx>
+
+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<unsigned char> (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<unsigned char> (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 <boris@codesynthesis.com>
+// 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 <stddef.h> // 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test xsde::cxx::hashmap type.
+//
+#include <assert.h>
+#include <string.h>
+
+#include <iostream>
+
+#include <xsde/cxx/hashmap.hxx>
+
+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<const char* const*> (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<const char* const*> (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<const char* const*> (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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test built-in types.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"><any></any><any-res x="x"><a>123</a><b>abc</b></any-res><any-simple></any-simple><any-simple-ext x="x"></any-simple-ext><int>123</int><simple-int>456</simple-int><int-base x="x">789</int-base><int-derived x="x" y="y">123</int-derived><bin>YmFzZTY0IGJpbmFyeQ==
+</bin><simple-bin>YmFzZTY0IGJpbmFyeQ==
+</simple-bin><bin-base x="x">YmFzZTY0IGJpbmFyeQ==
+</bin-base><bin-derived x="x" y="y">YmFzZTY0IGJpbmFyeQ==
+</bin-derived><string>abc</string><simple-string>def</simple-string><string-base x="x">ghi</string-base><string-derived x="x" y="y">jkl</string-derived></t:root> \ 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 @@
+<t:root xmlns:t="test" any-simple-attr="">
+
+ <any></any>
+ <any-res x="x"><a>123</a><b>abc</b></any-res>
+
+ <any-simple></any-simple>
+ <any-simple-ext x="x"></any-simple-ext>
+
+ <int>123</int>
+ <simple-int>456</simple-int>
+ <int-base x="x">789</int-base>
+ <int-derived x="x" y="y">123</int-derived>
+
+ <bin>YmFzZTY0IGJpbmFyeQ==</bin>
+ <simple-bin>YmFzZTY0IGJpbmFyeQ==</simple-bin>
+ <bin-base x="x">YmFzZTY0IGJpbmFyeQ==</bin-base>
+ <bin-derived x="x" y="y">YmFzZTY0IGJpbmFyeQ==</bin-derived>
+
+ <string>abc</string>
+ <simple-string>def</simple-string>
+ <string-base x="x">ghi</string-base>
+ <string-derived x="x" y="y">jkl</string-derived>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- anyType -->
+
+ <complexType name="any-res">
+ <complexContent>
+ <restriction base="anyType">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="string"/>
+ </sequence>
+ <attribute name="x" type="string"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- anySimpleType -->
+
+ <complexType name="any-simple-ext">
+ <simpleContent>
+ <extension base="anySimpleType">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+
+ <!-- int -->
+
+ <simpleType name="simple-int">
+ <restriction base="int"/>
+ </simpleType>
+
+ <complexType name="int-base">
+ <simpleContent>
+ <extension base="int">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="int-derived">
+ <simpleContent>
+ <extension base="t:int-base">
+ <attribute name="y" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- base64Binary -->
+
+ <simpleType name="simple-bin">
+ <restriction base="base64Binary"/>
+ </simpleType>
+
+ <complexType name="bin-base">
+ <simpleContent>
+ <extension base="base64Binary">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="bin-derived">
+ <simpleContent>
+ <extension base="t:bin-base">
+ <attribute name="y" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- string -->
+
+ <simpleType name="simple-string">
+ <restriction base="string"/>
+ </simpleType>
+
+ <complexType name="string-base">
+ <simpleContent>
+ <extension base="string">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="string-derived">
+ <simpleContent>
+ <extension base="t:string-base">
+ <attribute name="y" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+
+ <element name="any" type="anyType"/>
+ <element name="any-res" type="t:any-res"/>
+
+ <element name="any-simple" type="anySimpleType"/>
+ <element name="any-simple-ext" type="t:any-simple-ext"/>
+
+ <element name="int" type="int"/>
+ <element name="simple-int" type="t:simple-int"/>
+ <element name="int-base" type="t:int-base"/>
+ <element name="int-derived" type="t:int-derived"/>
+
+ <element name="bin" type="base64Binary"/>
+ <element name="simple-bin" type="t:simple-bin"/>
+ <element name="bin-base" type="t:bin-base"/>
+ <element name="bin-derived" type="t:bin-derived"/>
+
+ <element name="string" type="string"/>
+ <element name="simple-string" type="t:simple-string"/>
+ <element name="string-base" type="t:string-base"/>
+ <element name="string-derived" type="t:string-derived"/>
+
+ </sequence>
+ <attribute name="any-simple-attr" type="anySimpleType"/>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test choice mapping.
+//
+
+#include <cassert>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"><test2><a>123</a></test2><test2><b>abc</b><b>def</b></test2><test2><c><a>1.23</a><b>123</b></c></test2><test2><d><a>true</a><a>false</a><b>abc</b></d></test2><test2><e></e></test2><test2><s1>1.23</s1><s2>123</s2></test2><test2><s3>1.23</s3><s4>123</s4></test2><test2><s5>1.23</s5><s6>123</s6><s5>4.56</s5><s6>456</s6></test2><test3><f1>1.23</f1><v1>true</v1><f5>1.23</f5><v5>true</v5></test3><test3><f2>123</f2><v2><a>true</a><a>false</a><b>abc</b></v2><f3>1.23</f3><v3>true</v3><f6>123</f6><f5>1.23</f5><v6><a>true</a><a>false</a><b>abc</b></v6><v5>true</v5></test3><test4><f1>1.23</f1></test4><test4><v1>true</v1></test4><test4><f5>1.23</f5></test4><test4><v5>true</v5></test4><test4><f2>123</f2></test4><test4><v2><a>true</a><a>false</a><b>abc</b></v2></test4><test4><f3>1.23</f3></test4><test4><v3>true</v3></test4><test4><f6>123</f6><f5>1.23</f5></test4><test4><v6><a>true</a><a>false</a><b>abc</b></v6><v5>true</v5></test4><test5a></test5a><test5b><d>true</d></test5b><test5c><d>true</d></test5c><test5d></test5d></t:root> \ 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 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- test 2 -->
+
+ <test2><a>123</a></test2>
+
+ <test2><b>abc</b><b>def</b></test2>
+
+ <test2><c><a>1.23</a><b>123</b></c></test2>
+
+ <test2><d><a>true</a><a>false</a><b>abc</b></d></test2>
+
+ <test2><e/></test2>
+
+ <test2><s1>1.23</s1><s2>123</s2></test2>
+ <test2><s3>1.23</s3><s4>123</s4></test2>
+ <test2><s5>1.23</s5><s6>123</s6><s5>4.56</s5><s6>456</s6></test2>
+
+ <!-- test 3 -->
+
+ <test3>
+ <f1>1.23</f1>
+ <v1>true</v1>
+ <f5>1.23</f5>
+ <v5>true</v5></test3>
+
+ <test3>
+ <f2>123</f2>
+ <v2><a>true</a><a>false</a><b>abc</b></v2>
+ <f3>1.23</f3>
+ <v3>true</v3>
+ <f6>123</f6><f5>1.23</f5>
+ <v6><a>true</a><a>false</a><b>abc</b></v6><v5>true</v5>
+ </test3>
+
+ <!-- test 4 -->
+
+ <test4><f1>1.23</f1></test4>
+ <test4><v1>true</v1></test4>
+ <test4><f5>1.23</f5></test4>
+ <test4><v5>true</v5></test4>
+ <test4><f2>123</f2></test4>
+ <test4><v2><a>true</a><a>false</a><b>abc</b></v2></test4>
+ <test4><f3>1.23</f3></test4>
+ <test4><v3>true</v3></test4>
+ <test4><f6>123</f6><f5>1.23</f5></test4>
+ <test4><v6><a>true</a><a>false</a><b>abc</b></v6><v5>true</v5></test4>
+
+ <!-- test 5 -->
+
+ <test5a></test5a>
+ <test5b><d>true</d></test5b>
+ <test5c><d>true</d></test5c>
+ <test5d></test5d>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="fix">
+ <sequence>
+ <element name="a" type="double" minOccurs="0"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var">
+ <sequence>
+ <element name="a" type="boolean" maxOccurs="unbounded"/>
+ <element name="b" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="empty">
+ <sequence/>
+ </complexType>
+
+
+ <!-- test 1: fixed choice copying/assignment -->
+
+ <complexType name="test1">
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="string"/>
+ </choice>
+ </complexType>
+
+ <!-- test 2: general -->
+
+ <complexType name="test2">
+ <choice>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string" maxOccurs="unbounded"/>
+ <element name="c" type="t:fix"/>
+ <element name="d" type="t:var"/>
+ <element name="e" type="t:empty"/>
+ <sequence>
+ <element name="s1" type="double"/>
+ <element name="s2" type="int"/>
+ </sequence>
+ <sequence minOccurs="0">
+ <element name="s3" type="double"/>
+ <element name="s4" type="int"/>
+ </sequence>
+ <sequence maxOccurs="unbounded">
+ <element name="s5" type="double"/>
+ <element name="s6" type="int"/>
+ </sequence>
+ </choice>
+ </complexType>
+
+ <!-- test 3: choice cardinalities -->
+
+ <complexType name="test3">
+ <sequence>
+ <choice>
+ <element name="f1" type="double"/>
+ <element name="f2" type="int"/>
+ </choice>
+ <choice>
+ <element name="v1" type="boolean"/>
+ <element name="v2" type="t:var"/>
+ </choice>
+ <choice minOccurs="0">
+ <element name="f3" type="double"/>
+ <element name="f4" type="int"/>
+ </choice>
+ <choice minOccurs="0">
+ <element name="v3" type="boolean"/>
+ <element name="v4" type="t:var"/>
+ </choice>
+ <choice maxOccurs="unbounded">
+ <element name="f5" type="double"/>
+ <element name="f6" type="int"/>
+ </choice>
+ <choice maxOccurs="unbounded">
+ <element name="v5" type="boolean"/>
+ <element name="v6" type="t:var"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <!-- test 4: nested choice -->
+
+ <complexType name="test4">
+ <choice minOccurs="0">
+ <choice>
+ <element name="f1" type="double"/>
+ <element name="f2" type="int"/>
+ </choice>
+ <choice>
+ <element name="v1" type="boolean"/>
+ <element name="v2" type="t:var"/>
+ </choice>
+ <choice minOccurs="0">
+ <element name="f3" type="double"/>
+ <element name="f4" type="int"/>
+ </choice>
+ <choice minOccurs="0">
+ <element name="v3" type="boolean"/>
+ <element name="v4" type="t:var"/>
+ </choice>
+ <choice maxOccurs="unbounded">
+ <element name="f5" type="double"/>
+ <element name="f6" type="int"/>
+ </choice>
+ <choice maxOccurs="unbounded">
+ <element name="v5" type="boolean"/>
+ <element name="v6" type="t:var"/>
+ </choice>
+ </choice>
+ </complexType>
+
+ <!-- test 5: required choice with optional element-->
+
+ <complexType name="test5a">
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="double" minOccurs="0"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </complexType>
+
+ <complexType name="test5b">
+ <sequence>
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="double" minOccurs="0"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ <element name="d" type="boolean"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test5c">
+ <sequence>
+ <element name="d" type="boolean"/>
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="double" minOccurs="0"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="test5d">
+ <choice>
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="double" minOccurs="0"/>
+ </choice>
+ <element name="c" type="boolean"/>
+ </choice>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="test2" type="t:test2" maxOccurs="unbounded"/>
+ <element name="test3" type="t:test3" maxOccurs="unbounded"/>
+ <element name="test4" type="t:test4" maxOccurs="unbounded"/>
+ <element name="test5a" type="t:test5a" maxOccurs="unbounded"/>
+ <element name="test5b" type="t:test5b" maxOccurs="unbounded"/>
+ <element name="test5c" type="t:test5c" maxOccurs="unbounded"/>
+ <element name="test5d" type="t:test5d" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 @@
+<?xml version="1.0" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:t="test"
+ targetNamespace="test">
+
+ <complexType name="member">
+ <choice>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:T="test"
+ targetNamespace="test">
+
+ <include schemaLocation="includee.xsd"/>
+
+ <complexType name="container">
+ <choice>
+ <element name="a" type="T:member" maxOccurs="unbounded"/>
+ </choice>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- all -->
+
+ <complexType name="all-1">
+ <all>
+ <element name="a" type="int"/>
+ <element name="b" type="string"/>
+ </all>
+ </complexType>
+
+ <complexType name="all-2">
+ <all minOccurs="0">
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string" minOccurs="0"/>
+ </all>
+ </complexType>
+
+ <!-- sequence -->
+
+ <complexType name="sequence-1">
+ <sequence>
+ <element name="a" type="int"/>
+ <sequence>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-2">
+ <sequence minOccurs="0">
+ <element name="a" type="int"/>
+ <sequence minOccurs="0">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-3">
+ <sequence maxOccurs="unbounded">
+ <element name="a" type="int"/>
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-4">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-5">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice minOccurs="0">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-6">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-7">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <sequence>
+ <element name="c" type="boolean"/>
+ <element name="d" type="float"/>
+ </sequence>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-8">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <sequence minOccurs="0">
+ <element name="c" type="boolean"/>
+ <element name="d" type="float"/>
+ </sequence>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-9">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <element name="c" type="boolean"/>
+ <element name="d" type="float"/>
+ </sequence>
+ </choice>
+ </sequence>
+ </complexType>
+
+
+ <complexType name="sequence-10">
+ <sequence>
+ <element name="a" type="int"/>
+ <sequence minOccurs="0">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </sequence>
+ <sequence maxOccurs="unbounded">
+ <element name="d" type="string"/>
+ <element name="e" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <!-- choice -->
+
+ <complexType name="choice-1">
+ <choice>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ <element name="d" type="string" minOccurs="0"/>
+ <element name="e" type="boolean" minOccurs="0"/>
+ <element name="f" type="string" maxOccurs="unbounded"/>
+ <element name="g" type="boolean" maxOccurs="unbounded"/>
+ </choice>
+ </choice>
+ </complexType>
+
+ <complexType name="choice-2">
+ <choice minOccurs="0">
+ <element name="a" type="int"/>
+ <choice minOccurs="0">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </choice>
+ </complexType>
+
+ <complexType name="choice-3">
+ <choice maxOccurs="unbounded">
+ <element name="a" type="int"/>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ </choice>
+ </complexType>
+
+ <complexType name="choice-4">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ </choice>
+ <choice>
+ <element name="d" type="string"/>
+ <element name="e" type="boolean"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="fixed">
+ <sequence>
+ <element name="a" type="boolean" minOccurs="0"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="fix-ext">
+ <complexContent>
+ <extension base="t:fixed">
+ <sequence>
+ <element name="c" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="var-ext">
+ <complexContent>
+ <extension base="t:fixed">
+ <sequence>
+ <element name="c" type="string"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="var-ext2">
+ <complexContent>
+ <extension base="t:var-ext">
+ <sequence>
+ <element name="d" type="string"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="sequence-1">
+ <choice maxOccurs="unbounded">
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string" maxOccurs="unbounded"/>
+ <element name="c" type="boolean"/>
+ <sequence maxOccurs="unbounded">
+ <element name="d" type="string"/>
+ <element name="e" type="boolean"/>
+ </sequence>
+ </choice>
+ </complexType>
+
+ <complexType name="sequence-1a">
+ <choice>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ <sequence minOccurs="1">
+ <element name="d" type="string"/>
+ <element name="e" type="boolean"/>
+ </sequence>
+ </choice>
+ </complexType>
+
+ <complexType name="sequence-2">
+ <sequence maxOccurs="10">
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="string"/>
+ <element name="c" type="boolean"/>
+ <sequence maxOccurs="20">
+ <element name="d" type="string"/>
+ <element name="e" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="sequence-3">
+ <sequence maxOccurs="unbounded">
+ <element name="a" type="int" minOccurs="0"/>
+ <sequence maxOccurs="unbounded">
+ <element name="b" type="string" maxOccurs="unbounded"/>
+ <element name="c" type="boolean"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <include schemaLocation="b.xsd"/>
+
+ <complexType name="base">
+ <sequence>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="boolean"/>
+ <element name="c" type="t:derived" minOccurs="0"/>
+ </sequence>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <include schemaLocation="a.xsd"/>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="d" type="double"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+</schema>
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 @@
+<?xml version="1.0" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <include schemaLocation="a.xsd"/>
+ <include schemaLocation="b.xsd"/>
+
+ <element name="root" type="t:derived"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test list mapping.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"><int-list>123 456 789</int-list><qname-list>one t:two three</qname-list><string-list>abc def ghi</string-list><string-list-lang lang="fr">abc def ghi</string-list-lang></t:root> \ 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 @@
+<t:root xmlns:t="test">
+
+ <int-list>123 456 789</int-list>
+ <qname-list>one t:two three</qname-list>
+ <string-list>abc def ghi</string-list>
+ <string-list-lang lang="fr">abc def ghi</string-list-lang>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="int-list">
+ <list itemType="int"/>
+ </simpleType>
+
+ <simpleType name="qname-list">
+ <list itemType="QName"/>
+ </simpleType>
+
+ <simpleType name="string-list">
+ <list itemType="string"/>
+ </simpleType>
+
+ <complexType name="string-list-lang">
+ <simpleContent>
+ <extension base="t:string-list">
+ <attribute name="lang" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="int-list" type="t:int-list"/>
+ <element name="qname-list" type="t:qname-list"/>
+ <element name="string-list" type="t:string-list"/>
+ <element name="string-list-lang" type="t:string-list-lang"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="container">
+ <sequence>
+ <element name="c" type="t:member"/>
+ <element name="d" type="t:member" minOccurs="0"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="member">
+ <sequence>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="boolean"/>
+ </sequence>
+ </complexType>
+
+ <simpleType name="list">
+ <list itemType="t:item"/>
+ </simpleType>
+
+ <simpleType name="item">
+ <restriction base="int"/>
+ </simpleType>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test sequence templates.
+//
+#include <string>
+#include <cassert>
+
+#include <xsde/cxx/config.hxx>
+
+#ifndef XSDE_STL
+#include <xsde/cxx/strdupx.hxx>
+#endif
+
+#include <xsde/cxx/hybrid/sequence.hxx>
+
+using std::string;
+using namespace xsde::cxx::hybrid;
+
+void data_destructor (void* p, size_t)
+{
+ delete static_cast<string*> (p);
+}
+
+void data_destructor_pos (void* p, size_t i)
+{
+ switch (i)
+ {
+ case 0:
+ {
+ delete static_cast<string*> (p);
+ break;
+ }
+ case 1:
+ {
+ delete static_cast<int*> (p);
+ break;
+ }
+ }
+}
+
+int
+main ()
+{
+ //
+ // pod_seq
+ //
+ typedef pod_seq<int> 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<string> 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<string> 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<string*> (s[0]) == "aaa" &&
+ *static_cast<string*> (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<string*> (s[0]) == "aaa" &&
+ *static_cast<int*> (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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- fixed -->
+
+ <complexType name="fixed-base">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="t:fixed-all" minOccurs="0"/>
+ </sequence>
+ <attribute name="x" type="double" use="required"/>
+ </complexType>
+
+ <complexType name="fixed-derived">
+ <complexContent>
+ <extension base="t:fixed-base">
+ <sequence>
+ <element name="c" type="float"/>
+ </sequence>
+ <attribute name="y" type="boolean"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="fixed-all">
+ <all>
+ <element name="a" type="int"/>
+ <element name="b" type="time" minOccurs="0"/>
+ </all>
+ <attribute name="x" type="double"/>
+ </complexType>
+
+ <!-- variable -->
+
+ <complexType name="var-el-string">
+ <all>
+ <element name="b" type="string"/>
+ </all>
+ <attribute name="x" type="double"/>
+ </complexType>
+
+ <complexType name="var-at-string">
+ <all>
+ <element name="b" type="int"/>
+ </all>
+ <attribute name="x" type="string"/>
+ </complexType>
+
+ <complexType name="var-seq1">
+ <sequence>
+ <element name="b" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-seq2">
+ <sequence maxOccurs="2">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-choice">
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="boolean"/>
+ </choice>
+ </complexType>
+
+ <complexType name="var-var-mem">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="t:var-seq1"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-var-base">
+ <complexContent>
+ <extension base="t:var-var-mem">
+ <sequence>
+ <element name="c" type="float"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="var-fwd1">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="t:var-fwd2"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-fwd2">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="string"/>
+ </sequence>
+ </complexType>
+
+
+ <complexType name="var-mem-rec1">
+ <sequence>
+ <element name="a" type="t:var-mem-rec2"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-mem-rec2">
+ <sequence>
+ <element name="a" type="t:var-mem-rec1" minOccurs="0"/>
+ </sequence>
+ </complexType>
+
+
+ <complexType name="var-base-rec1">
+ <sequence>
+ <element name="a" type="t:var-base-rec3"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="var-base-rec2">
+ <complexContent>
+ <extension base="t:var-base-rec1">
+ <sequence>
+ <element name="c" type="float"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="var-base-rec3">
+ <sequence>
+ <element name="a" type="t:var-base-rec2" minOccurs="0"/>
+ </sequence>
+ </complexType>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Insert test description here.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"><a>123</a></t:root> \ 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 @@
+<t:root xmlns:t="test">
+
+ <a>123</a>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="type">
+ <sequence>
+ <element name="a" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test union mapping.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"><int-string-union>123</int-string-union><int-string-union-lang lang="en">one</int-string-union-lang></t:root> \ 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 @@
+<t:root xmlns:t="test">
+
+ <int-string-union>123</int-string-union>
+ <int-string-union-lang lang="en">one</int-string-union-lang>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="int-string-union">
+ <union memberTypes="int string"/>
+ </simpleType>
+
+ <complexType name="int-string-union-lang">
+ <simpleContent>
+ <extension base="t:int-string-union">
+ <attribute name="lang" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="int-string-union" type="t:int-string-union"/>
+ <element name="int-string-union-lang" type="t:int-string-union-lang"/>
+ <element name="dummy" type="boolean" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test built-in type parsing.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <any-type x="x">
+ <a>a</a>
+ <any-type x="xxx">aaa<a>bbb</a>ccc</any-type>
+ </any-type>
+
+ <any-simple-type>123abc</any-simple-type>
+
+ <boolean>1</boolean>
+ <boolean> 0 </boolean>
+ <boolean>true</boolean>
+ <boolean> false </boolean>
+
+ <byte>0</byte>
+ <byte>+127</byte>
+ <byte>-128</byte>
+ <byte> 123 </byte>
+
+ <unsigned-byte>0</unsigned-byte>
+ <unsigned-byte>255</unsigned-byte>
+ <unsigned-byte> 123 </unsigned-byte>
+
+ <short>0</short>
+ <short>+32767</short>
+ <short>-32768</short>
+ <short> -12345 </short>
+
+ <unsigned-short>0</unsigned-short>
+ <unsigned-short>65535</unsigned-short>
+ <unsigned-short> 12345 </unsigned-short>
+
+ <int>0</int>
+ <int>+2147483647</int>
+ <int>-2147483648</int>
+ <int> -1234567890 </int>
+
+ <unsigned-int>0</unsigned-int>
+ <unsigned-int>4294967295</unsigned-int>
+ <unsigned-int> 1234567890 </unsigned-int>
+
+ <long>0</long>
+ <long>+9223372036854775807</long>
+ <long>-9223372036854775808</long>
+ <long> -1234567890123456789 </long>
+
+ <unsigned-long>0</unsigned-long>
+ <unsigned-long>18446744073709551615</unsigned-long>
+ <unsigned-long> 12345678901234567890 </unsigned-long>
+
+ <integer>0</integer>
+ <integer> +2147483647 </integer>
+ <integer>-02147483648</integer>
+ <integer>-1234567890</integer>
+
+ <negative-integer>-02147483648</negative-integer>
+ <negative-integer> -1234567890 </negative-integer>
+
+ <non-positive-integer>0</non-positive-integer>
+ <non-positive-integer>-02147483648</non-positive-integer>
+ <non-positive-integer> -1234567890 </non-positive-integer>
+
+ <positive-integer>4294967295</positive-integer>
+ <positive-integer> +01234567890 </positive-integer>
+
+ <non-negative-integer>0</non-negative-integer>
+ <non-negative-integer>4294967295</non-negative-integer>
+ <non-negative-integer> +01234567890 </non-negative-integer>
+
+ <float>0</float>
+ <float>+0</float>
+ <float>-0</float>
+ <float>INF</float>
+ <float>-INF</float>
+ <float>NaN</float>
+ <float> 123.567 </float>
+ <float>+123.567</float>
+ <float>-123.567e5</float>
+ <float>-.45E-5</float>
+
+ <double>0</double>
+ <double>+0</double>
+ <double>-0</double>
+ <double>INF</double>
+ <double>-INF</double>
+ <double>NaN</double>
+ <double> 123.567 </double>
+ <double>+123.567</double>
+ <double>-123.567e5</double>
+ <double>-.45E-5</double>
+
+ <decimal>0</decimal>
+ <decimal>+0</decimal>
+ <decimal>-0</decimal>
+ <decimal> 123.567 </decimal>
+ <decimal>+123.567</decimal>
+ <decimal>-123.567</decimal>
+
+ <string>string space
+newline
+ </string>
+
+ <normalized-string> string space
+newline
+
+ </normalized-string>
+
+ <token> string space
+newline
+
+ </token>
+
+ <name> as123:345-.abs </name>
+
+ <nmtoken> 1as123:345-.abs </nmtoken>
+
+ <nmtokens> abc 123 </nmtokens>
+
+ <ncname> as123_345-.abs </ncname>
+
+ <id> as123_345-.abs </id>
+ <id> abc </id>
+ <id> a123 </id>
+
+ <idref> as123_345-.abs </idref>
+
+ <idrefs> abc a123 </idrefs>
+
+ <language> x </language>
+ <language> en </language>
+ <language> en-us </language>
+ <language>one-two-three-four44-seven77-eight888</language>
+
+ <uri> </uri>
+ <uri> relative </uri>
+ <uri> #id </uri>
+ <uri> http://www.example.com/foo#bar </uri>
+
+ <qname>schemaLocation</qname>
+ <qname>xsi:schemaLocation</qname>
+
+ <base64_binary> MTIzND
+ VhYmNqaw = =</base64_binary>
+ <base64_binary>YQ==</base64_binary>
+ <base64_binary>YWI=</base64_binary>
+ <base64_binary>YWJj</base64_binary>
+
+ <hex_binary> </hex_binary>
+ <hex_binary> 31323334356162636a6b </hex_binary>
+
+ <gday> ---12+12:00 </gday>
+ <gday>---01</gday>
+ <gday>---31</gday>
+ <gday>---15Z</gday>
+ <gday>---15-14:00</gday>
+
+ <gmonth> --10+12:00 </gmonth>
+ <gmonth>--01</gmonth>
+ <gmonth>--12Z</gmonth>
+
+ <gyear> 2007+12:00 </gyear>
+ <gyear>0001</gyear>
+ <gyear>-20000Z</gyear>
+
+ <gmonth_day> --10-28+12:00 </gmonth_day>
+ <gmonth_day>--12-31</gmonth_day>
+ <gmonth_day>--01-01Z</gmonth_day>
+
+ <gyear_month> 2007-12+12:00 </gyear_month>
+ <gyear_month>-2007-10</gyear_month>
+ <gyear_month>20007-10Z</gyear_month>
+ <gyear_month>-20007-01</gyear_month>
+
+ <date> 2007-12-26+12:00 </date>
+ <date>-2007-10-15</date>
+ <date>20007-12-31Z</date>
+ <date>-20007-01-01</date>
+
+ <time> 12:46:23.456+12:00 </time>
+ <time>12:13:14</time>
+ <time>12:13:14Z</time>
+
+ <date_time> 2007-12-26T12:13:14.123+12:00 </date_time>
+ <date_time>-2007-10-15T12:13:14</date_time>
+ <date_time>20007-12-31T12:13:14Z</date_time>
+ <date_time>-20007-01-01T12:13:14</date_time>
+
+ <duration> -P2007Y13M32DT25H61M61.123S </duration>
+ <duration>P1Y</duration>
+ <duration>P1M</duration>
+ <duration>P1D</duration>
+ <duration>PT1H</duration>
+ <duration>PT1M</duration>
+ <duration>PT1.1S</duration>
+ <duration>P1YT1S</duration>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <any-type x="x">
+ <a>a</a>
+ <any-type x="xxx">aaa<a>bbb</a>ccc</any-type>
+ </any-type>
+
+ <any-simple-type>123abc</any-simple-type>
+
+ <boolean>1</boolean>
+ <boolean> 0 </boolean>
+ <boolean>true</boolean>
+ <boolean> false </boolean>
+
+ <byte>0</byte>
+ <byte>+127</byte>
+ <byte>-128</byte>
+ <byte> 123 </byte>
+
+ <unsigned-byte>0</unsigned-byte>
+ <unsigned-byte>255</unsigned-byte>
+ <unsigned-byte> 123 </unsigned-byte>
+
+ <short>0</short>
+ <short>+32767</short>
+ <short>-32768</short>
+ <short> -12345 </short>
+
+ <unsigned-short>0</unsigned-short>
+ <unsigned-short>65535</unsigned-short>
+ <unsigned-short> 12345 </unsigned-short>
+
+ <int>0</int>
+ <int>+2147483647</int>
+ <int>-2147483648</int>
+ <int> -1234567890 </int>
+
+ <unsigned-int>0</unsigned-int>
+ <unsigned-int>4294967295</unsigned-int>
+ <unsigned-int> 1234567890 </unsigned-int>
+
+ <long>0</long>
+ <long>+2147483647</long>
+ <long>-2147483648</long>
+ <long> -1234567890 </long>
+
+ <unsigned-long>0</unsigned-long>
+ <unsigned-long>4294967295</unsigned-long>
+ <unsigned-long> 1234567890 </unsigned-long>
+
+ <integer>0</integer>
+ <integer> +2147483647 </integer>
+ <integer>-02147483648</integer>
+ <integer>-1234567890</integer>
+
+ <negative-integer>-02147483648</negative-integer>
+ <negative-integer> -1234567890 </negative-integer>
+
+ <non-positive-integer>0</non-positive-integer>
+ <non-positive-integer>-02147483648</non-positive-integer>
+ <non-positive-integer> -1234567890 </non-positive-integer>
+
+ <positive-integer>4294967295</positive-integer>
+ <positive-integer> +01234567890 </positive-integer>
+
+ <non-negative-integer>0</non-negative-integer>
+ <non-negative-integer>4294967295</non-negative-integer>
+ <non-negative-integer> +01234567890 </non-negative-integer>
+
+ <float>0</float>
+ <float>+0</float>
+ <float>-0</float>
+ <float>INF</float>
+ <float>-INF</float>
+ <float>NaN</float>
+ <float> 123.567 </float>
+ <float>+123.567</float>
+ <float>-123.567e5</float>
+ <float>-.45E-5</float>
+
+ <double>0</double>
+ <double>+0</double>
+ <double>-0</double>
+ <double>INF</double>
+ <double>-INF</double>
+ <double>NaN</double>
+ <double> 123.567 </double>
+ <double>+123.567</double>
+ <double>-123.567e5</double>
+ <double>-.45E-5</double>
+
+ <decimal>0</decimal>
+ <decimal>+0</decimal>
+ <decimal>-0</decimal>
+ <decimal> 123.567 </decimal>
+ <decimal>+123.567</decimal>
+ <decimal>-123.567</decimal>
+
+ <string>string space
+newline
+ </string>
+
+ <normalized-string> string space
+newline
+
+ </normalized-string>
+
+ <token> string space
+newline
+
+ </token>
+
+ <name> as123:345-.abs </name>
+
+ <nmtoken> 1as123:345-.abs </nmtoken>
+
+ <nmtokens> abc 123 </nmtokens>
+
+ <ncname> as123_345-.abs </ncname>
+
+ <id> as123_345-.abs </id>
+ <id> abc </id>
+ <id> a123 </id>
+
+ <idref> as123_345-.abs </idref>
+
+ <idrefs> abc a123 </idrefs>
+
+ <language> x </language>
+ <language> en </language>
+ <language> en-us </language>
+ <language>one-two-three-four44-seven77-eight888</language>
+
+ <uri> </uri>
+ <uri> relative </uri>
+ <uri> #id </uri>
+ <uri> http://www.example.com/foo#bar </uri>
+
+ <qname>schemaLocation</qname>
+ <qname>xsi:schemaLocation</qname>
+
+ <base64_binary> MTIzND
+ VhYmNqaw = =</base64_binary>
+ <base64_binary>YQ==</base64_binary>
+ <base64_binary>YWI=</base64_binary>
+ <base64_binary>YWJj</base64_binary>
+
+ <hex_binary> </hex_binary>
+ <hex_binary> 31323334356162636a6b </hex_binary>
+
+ <gday> ---12+12:00 </gday>
+ <gday>---01</gday>
+ <gday>---31</gday>
+ <gday>---15Z</gday>
+ <gday>---15-14:00</gday>
+
+ <gmonth> --10+12:00 </gmonth>
+ <gmonth>--01</gmonth>
+ <gmonth>--12Z</gmonth>
+
+ <gyear> 2007+12:00 </gyear>
+ <gyear>0001</gyear>
+ <gyear>-20000Z</gyear>
+
+ <gmonth_day> --10-28+12:00 </gmonth_day>
+ <gmonth_day>--12-31</gmonth_day>
+ <gmonth_day>--01-01Z</gmonth_day>
+
+ <gyear_month> 2007-12+12:00 </gyear_month>
+ <gyear_month>-2007-10</gyear_month>
+ <gyear_month>20007-10Z</gyear_month>
+ <gyear_month>-20007-01</gyear_month>
+
+ <date> 2007-12-26+12:00 </date>
+ <date>-2007-10-15</date>
+ <date>20007-12-31Z</date>
+ <date>-20007-01-01</date>
+
+ <time> 12:46:23.456+12:00 </time>
+ <time>12:13:14</time>
+ <time>12:13:14Z</time>
+
+ <date_time> 2007-12-26T12:13:14.123+12:00 </date_time>
+ <date_time>-2007-10-15T12:13:14</date_time>
+ <date_time>20007-12-31T12:13:14Z</date_time>
+ <date_time>-20007-01-01T12:13:14</date_time>
+
+ <duration> -P2007Y13M32DT25H61M61.123S </duration>
+ <duration>P1Y</duration>
+ <duration>P1M</duration>
+ <duration>P1D</duration>
+ <duration>PT1H</duration>
+ <duration>PT1M</duration>
+ <duration>PT1.1S</duration>
+ <duration>P1YT1S</duration>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="type">
+ <sequence>
+ <element name="any-type" type="anyType" maxOccurs="unbounded"/>
+ <element name="any-simple-type" type="anySimpleType" maxOccurs="unbounded"/>
+
+ <element name="boolean" type="boolean" maxOccurs="unbounded"/>
+
+ <element name="byte" type="byte" maxOccurs="unbounded"/>
+ <element name="unsigned-byte" type="unsignedByte" maxOccurs="unbounded"/>
+ <element name="short" type="short" maxOccurs="unbounded"/>
+ <element name="unsigned-short" type="unsignedShort" maxOccurs="unbounded"/>
+ <element name="int" type="int" maxOccurs="unbounded"/>
+ <element name="unsigned-int" type="unsignedInt" maxOccurs="unbounded"/>
+ <element name="long" type="long" maxOccurs="unbounded"/>
+ <element name="unsigned-long" type="unsignedLong" maxOccurs="unbounded"/>
+
+ <element name="integer" type="integer" maxOccurs="unbounded"/>
+ <element name="negative-integer" type="negativeInteger" maxOccurs="unbounded"/>
+ <element name="non-positive-integer" type="nonPositiveInteger" maxOccurs="unbounded"/>
+ <element name="positive-integer" type="positiveInteger" maxOccurs="unbounded"/>
+ <element name="non-negative-integer" type="nonNegativeInteger" maxOccurs="unbounded"/>
+
+ <element name="float" type="float" maxOccurs="unbounded"/>
+ <element name="double" type="double" maxOccurs="unbounded"/>
+ <element name="decimal" type="decimal" maxOccurs="unbounded"/>
+
+ <element name="string" type="string" maxOccurs="unbounded"/>
+ <element name="normalized-string" type="normalizedString" maxOccurs="unbounded"/>
+ <element name="token" type="token" maxOccurs="unbounded"/>
+ <element name="name" type="Name" maxOccurs="unbounded"/>
+ <element name="nmtoken" type="NMTOKEN" maxOccurs="unbounded"/>
+ <element name="nmtokens" type="NMTOKENS" maxOccurs="unbounded"/>
+ <element name="ncname" type="NCName" maxOccurs="unbounded"/>
+ <element name="id" type="ID" maxOccurs="unbounded"/>
+ <element name="idref" type="IDREF" maxOccurs="unbounded"/>
+ <element name="idrefs" type="IDREFS" maxOccurs="unbounded"/>
+
+ <element name="language" type="language" maxOccurs="unbounded"/>
+ <element name="uri" type="anyURI" maxOccurs="unbounded"/>
+ <element name="qname" type="QName" maxOccurs="unbounded"/>
+
+ <element name="base64_binary" type="base64Binary" maxOccurs="unbounded"/>
+ <element name="hex_binary" type="hexBinary" maxOccurs="unbounded"/>
+
+ <element name="gday" type="gDay" maxOccurs="unbounded"/>
+ <element name="gmonth" type="gMonth" maxOccurs="unbounded"/>
+ <element name="gyear" type="gYear" maxOccurs="unbounded"/>
+ <element name="gmonth_day" type="gMonthDay" maxOccurs="unbounded"/>
+ <element name="gyear_month" type="gYearMonth" maxOccurs="unbounded"/>
+ <element name="date" type="date" maxOccurs="unbounded"/>
+ <element name="time" type="time" maxOccurs="unbounded"/>
+ <element name="date_time" type="dateTime" maxOccurs="unbounded"/>
+ <element name="duration" type="duration" maxOccurs="unbounded"/>
+
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <a>1</a>
+ <a>2</a>
+ <a>3</a>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- Test duplicate element handling -->
+
+ <complexType name="type">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="a" type="int"/>
+ <element name="a" type="int"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test xsd:enumeration parsing.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <digit>1</digit>
+
+ <gender>male</gender>
+ <gender>female</gender>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="digit">
+ <restriction base="int">
+ <enumeration value="0"/>
+ <enumeration value="1"/>
+ <enumeration value="2"/>
+ <enumeration value="3"/>
+ <enumeration value="4"/>
+ <enumeration value="5"/>
+ <enumeration value="6"/>
+ <enumeration value="7"/>
+ <enumeration value="8"/>
+ <enumeration value="9"/>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="gender">
+ <restriction base="string">
+ <enumeration value="male"/>
+ <enumeration value="female"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="type">
+ <choice maxOccurs="unbounded">
+ <element name="digit" type="t:digit"/>
+ <element name="gender" type="t:gender"/>
+ </choice>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <string>
+#include <cassert>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+#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 ("<t:root xmlns:t='test'>\n</t:rot>");
+ doc_p.parse (is);
+ }
+ else if (i == 8)
+ {
+ istringstream is ("<t:rot xmlns:t='test'>\n</t:rot>");
+ doc_p.parse (is);
+ }
+ else if (i == 9)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'/>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 10)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person><age>64</age></person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 11)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'>\n"
+ "<age>64</age>\n"
+ "<foo/>\n"
+ "</person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 12)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a' foo='f'>\n"
+ "<age>64</age>\n"
+ "</person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 13)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'>\n"
+ "<age>a64</age>\n"
+ "</person>\n"
+ "</t:root>");
+ 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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <person id="old">
+ <age>67</age>
+ </person>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="person">
+ <sequence>
+ <element name="age" type="int"/>
+ </sequence>
+ <attribute name="id" type="string" use="required"/>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="person" type="t:person" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test error reporting with exceptions.
+//
+
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#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 ("<t:root xmlns:t='test'>\n</t:rot>");
+ doc_p.parse (is);
+ }
+ else if (i == 8)
+ {
+ istringstream is ("<t:rot xmlns:t='test'>\n</t:rot>");
+ doc_p.parse (is);
+ }
+ else if (i == 9)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'/>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 10)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person><age>64</age></person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 11)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'>\n"
+ "<age>64</age>\n"
+ "<foo/>\n"
+ "</person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 12)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a' foo='f'>\n"
+ "<age>64</age>\n"
+ "</person>\n"
+ "</t:root>");
+ doc_p.parse (is);
+ }
+ else if (i == 13)
+ {
+ istringstream is (
+ "<t:root xmlns:t='test'>\n"
+ "<person id='a'>\n"
+ "<age>a64</age>\n"
+ "</person>\n"
+ "</t:root>");
+ 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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <person id="old">
+ <age>67</age>
+ </person>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="person">
+ <sequence>
+ <element name="age" type="int"/>
+ </sequence>
+ <attribute name="id" type="string" use="required"/>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="person" type="t:person" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <gender>male</gender>
+ <gender-extension foo="foo">male</gender-extension>
+
+ <list>0 1 2 3</list>
+ <list-extension foo="foo">3 2 1 0</list-extension>
+
+ <union>9</union>
+ <union-extension foo="foo">string</union-extension>
+
+ <complex x="x">
+ <a>aaa</a>
+ </complex>
+
+ <complex-extension x="x" y="y">
+ <a>aaa</a>
+ <b>bbb</b>
+ </complex-extension>
+
+ <any-type>aaa<b>bbb</b>ccc</any-type>
+ <any-simple-type>abc123</any-simple-type>
+
+ <boolean>1</boolean>
+ <boolean> 0 </boolean>
+ <boolean>true</boolean>
+ <boolean> false </boolean>
+
+ <byte>0</byte>
+ <byte>123</byte>
+ <byte>-123</byte>
+
+ <unsigned-byte>0</unsigned-byte>
+ <unsigned-byte>123</unsigned-byte>
+
+ <short>0</short>
+ <short>-1234</short>
+ <short>1234</short>
+
+ <unsigned-short>0</unsigned-short>
+ <unsigned-short>1234</unsigned-short>
+
+ <int>0</int>
+ <int>-12345</int>
+ <int>12345</int>
+
+ <unsigned-int>0</unsigned-int>
+ <unsigned-int>12345</unsigned-int>
+
+ <long>0</long>
+ <long>-123456</long>
+ <long>123456</long>
+
+ <unsigned-long>0</unsigned-long>
+ <unsigned-long>123456</unsigned-long>
+
+ <integer>0</integer>
+ <integer>-123456</integer>
+ <integer>123456</integer>
+
+ <negative-integer>-123456</negative-integer>
+
+ <non-positive-integer>0</non-positive-integer>
+ <non-positive-integer>-123456</non-positive-integer>
+
+ <positive-integer>123456</positive-integer>
+
+ <non-negative-integer>0</non-negative-integer>
+ <non-negative-integer>123456</non-negative-integer>
+
+ <float>0</float>
+ <float>1.123</float>
+ <float>-1.123</float>
+
+ <double>0</double>
+ <double>1.1234</double>
+ <double>-1.1234</double>
+
+ <decimal>0</decimal>
+ <decimal>1.1234</decimal>
+ <decimal>-1.1234</decimal>
+
+ <string>string space newline</string>
+
+ <normalized-string>string space newline</normalized-string>
+
+ <token> string space newline</token>
+
+ <name>as123:345-.abs</name>
+
+ <nmtoken>1as123:345-.abs</nmtoken>
+
+ <nmtokens>abc 123</nmtokens>
+
+ <ncname>as123_345-.abs</ncname>
+
+ <id>abc</id>
+ <id>a123</id>
+
+ <idref>abc</idref>
+
+ <idrefs>abc a123</idrefs>
+
+ <language>en</language>
+ <language>en-us</language>
+
+ <uri>http://www.example.com/foo#bar</uri>
+
+ <qname>schemaLocation</qname>
+ <qname>xsi:schemaLocation</qname>
+
+ <base64_binary>MTIzNDVhYmNqaw==</base64_binary>
+ <base64_binary>YQ==</base64_binary>
+ <base64_binary>YWI=</base64_binary>
+ <base64_binary>YWJj</base64_binary>
+
+ <hex_binary></hex_binary>
+ <hex_binary>31323334356162636a6b</hex_binary>
+
+ <gday>---12+12:00</gday>
+ <gday>---01</gday>
+ <gday>---31</gday>
+ <gday>---15Z</gday>
+ <gday>---15-14:00</gday>
+
+ <gmonth>--10+12:00</gmonth>
+ <gmonth>--01</gmonth>
+ <gmonth>--12Z</gmonth>
+
+ <gyear>2007+12:00</gyear>
+ <gyear>0001</gyear>
+ <gyear>-20000Z</gyear>
+
+ <gmonth_day>--10-28+12:00</gmonth_day>
+ <gmonth_day>--12-31</gmonth_day>
+ <gmonth_day>--01-01Z</gmonth_day>
+
+ <gyear_month>2007-12+12:00</gyear_month>
+ <gyear_month>-2007-10</gyear_month>
+ <gyear_month>20007-10Z</gyear_month>
+ <gyear_month>-20007-01</gyear_month>
+
+ <date>2007-12-26+12:00</date>
+ <date>-2007-10-15</date>
+ <date>20007-12-31Z</date>
+ <date>-20007-01-01</date>
+
+ <time>12:46:23.456+12:00</time>
+ <time>12:13:14</time>
+ <time>12:13:14Z</time>
+
+ <date_time>2007-12-26T12:13:14.123+12:00</date_time>
+ <date_time>-2007-10-15T12:13:14</date_time>
+ <date_time>20007-12-31T12:13:14Z</date_time>
+ <date_time>-20007-01-01T12:13:14</date_time>
+
+ <duration>-P2007Y13M32DT25H61M61.123S</duration>
+ <duration>P1Y</duration>
+ <duration>P1M</duration>
+ <duration>P1D</duration>
+ <duration>PT1H</duration>
+ <duration>PT1M</duration>
+ <duration>PT1.1S</duration>
+ <duration>P1YT1S</duration>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- enum -->
+
+ <simpleType name="gender">
+ <restriction base="string">
+ <enumeration value="male"/>
+ <enumeration value="female"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="gender-extension">
+ <simpleContent>
+ <extension base="t:gender">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- list -->
+
+ <simpleType name="list">
+ <list itemType="int"/>
+ </simpleType>
+
+ <complexType name="list-extension">
+ <simpleContent>
+ <extension base="t:list">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- union -->
+
+ <simpleType name="union">
+ <union memberTypes="int string"/>
+ </simpleType>
+
+ <complexType name="union-extension">
+ <simpleContent>
+ <extension base="t:union">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- complex -->
+
+ <complexType name="complex">
+ <sequence>
+ <element name="a" type="string"/>
+ </sequence>
+ <attribute name="x" type="string"/>
+ </complexType>
+
+ <complexType name="complex-extension">
+ <complexContent>
+ <extension base="t:complex">
+ <sequence>
+ <element name="b" type="string"/>
+ </sequence>
+ <attribute name="y" type="string"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="gender" type="t:gender"/>
+ <element name="gender-extension" type="t:gender-extension"/>
+
+ <element name="list" type="t:list"/>
+ <element name="list-extension" type="t:list-extension"/>
+
+ <element name="union" type="t:union"/>
+ <element name="union-extension" type="t:union-extension"/>
+
+ <element name="complex" type="t:complex"/>
+ <element name="complex-extension" type="t:complex-extension"/>
+
+ <!-- Built-in types. -->
+
+ <element name="any-type" type="anyType" maxOccurs="unbounded"/>
+ <element name="any-simple-type" type="anySimpleType" maxOccurs="unbounded"/>
+
+ <element name="boolean" type="boolean" maxOccurs="unbounded"/>
+
+ <element name="byte" type="byte" maxOccurs="unbounded"/>
+ <element name="unsigned-byte" type="unsignedByte" maxOccurs="unbounded"/>
+ <element name="short" type="short" maxOccurs="unbounded"/>
+ <element name="unsigned-short" type="unsignedShort" maxOccurs="unbounded"/>
+ <element name="int" type="int" maxOccurs="unbounded"/>
+ <element name="unsigned-int" type="unsignedInt" maxOccurs="unbounded"/>
+ <element name="long" type="long" maxOccurs="unbounded"/>
+ <element name="unsigned-long" type="unsignedLong" maxOccurs="unbounded"/>
+
+ <element name="integer" type="integer" maxOccurs="unbounded"/>
+ <element name="negative-integer" type="negativeInteger" maxOccurs="unbounded"/>
+ <element name="non-positive-integer" type="nonPositiveInteger" maxOccurs="unbounded"/>
+ <element name="positive-integer" type="positiveInteger" maxOccurs="unbounded"/>
+ <element name="non-negative-integer" type="nonNegativeInteger" maxOccurs="unbounded"/>
+
+ <element name="float" type="float" maxOccurs="unbounded"/>
+ <element name="double" type="double" maxOccurs="unbounded"/>
+ <element name="decimal" type="decimal" maxOccurs="unbounded"/>
+
+ <element name="string" type="string" maxOccurs="unbounded"/>
+ <element name="normalized-string" type="normalizedString" maxOccurs="unbounded"/>
+ <element name="token" type="token" maxOccurs="unbounded"/>
+ <element name="name" type="Name" maxOccurs="unbounded"/>
+ <element name="nmtoken" type="NMTOKEN" maxOccurs="unbounded"/>
+ <element name="nmtokens" type="NMTOKENS" maxOccurs="unbounded"/>
+ <element name="ncname" type="NCName" maxOccurs="unbounded"/>
+ <element name="id" type="ID" maxOccurs="unbounded"/>
+ <element name="idref" type="IDREF" maxOccurs="unbounded"/>
+ <element name="idrefs" type="IDREFS" maxOccurs="unbounded"/>
+
+ <element name="language" type="language" maxOccurs="unbounded"/>
+ <element name="uri" type="anyURI" maxOccurs="unbounded"/>
+ <element name="qname" type="QName" maxOccurs="unbounded"/>
+
+ <element name="base64_binary" type="base64Binary" maxOccurs="unbounded"/>
+ <element name="hex_binary" type="hexBinary" maxOccurs="unbounded"/>
+
+ <element name="gday" type="gDay" maxOccurs="unbounded"/>
+ <element name="gmonth" type="gMonth" maxOccurs="unbounded"/>
+ <element name="gyear" type="gYear" maxOccurs="unbounded"/>
+ <element name="gmonth_day" type="gMonthDay" maxOccurs="unbounded"/>
+ <element name="gyear_month" type="gYearMonth" maxOccurs="unbounded"/>
+ <element name="date" type="date" maxOccurs="unbounded"/>
+ <element name="time" type="time" maxOccurs="unbounded"/>
+ <element name="date_time" type="dateTime" maxOccurs="unbounded"/>
+ <element name="duration" type="duration" maxOccurs="unbounded"/>
+
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test xsd:list parsing.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <string-list/>
+
+ <string-list> </string-list>
+
+ <string-list>
+
+ </string-list>
+
+ <string-list>one</string-list>
+
+ <string-list>
+ one two
+ three
+ </string-list>
+
+ <string-list-lang lang="en">
+ one two
+ three
+ </string-list-lang>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="string-list">
+ <list itemType="string"/>
+ </simpleType>
+
+ <complexType name="string-list-lang">
+ <simpleContent>
+ <extension base="t:string-list">
+ <attribute name="lang" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <choice maxOccurs="unbounded">
+ <element name="string-list" type="t:string-list"/>
+ <element name="string-list-lang" type="t:string-list-lang"/>
+ </choice>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <e>e</e>
+ <e>e1</e>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ <element name="e" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="e" type="string"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <element name="root" type="t:derived"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <t:base><a>1</a></t:base>
+
+ <t:base xsi:type="t:interm"><a>1</a><b>2</b></t:base>
+ <t:interm><a>1</a><b>2</b></t:interm>
+
+ <t:base xsi:type="t:derived"><a>1</a><b>2</b><c>3</c></t:base>
+ <t:derived><a>1</a><b>2</b><c>3</c></t:derived>
+
+ <!-- same type substitution -->
+
+ <t:another-base><a>1</a></t:another-base>
+ <t:base xsi:type="t:base"><a>1</a></t:base>
+ <t:another-base xsi:type="t:base"><a>1</a></t:another-base>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ <element name="a" type="int"/>
+ </sequence>
+ </complexType>
+
+ <element name="base" type="t:base"/>
+ <element name="another-base" type="t:base" substitutionGroup="t:base"/>
+
+ <complexType name="interm">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <element name="interm" type="t:interm" substitutionGroup="t:base"/>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:interm">
+ <sequence>
+ <element name="c" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <element name="derived" type="t:derived" substitutionGroup="t:interm"/>
+
+ <complexType name="type">
+ <sequence>
+ <element ref="t:base" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test recursive parser invocation.
+//
+
+#include <iostream>
+#include <string>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="test.xsd"
+ name="testName">
+ <sub name="subName">
+ <sub name="sub-subName"/>
+ <indir name="sub-indirName">
+ <sub name="sub-indir-subName"/>
+ </indir>
+ <sub2 name="sub-sub2Name"/>
+ </sub>
+</test>
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 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:complexType name="sub_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" minOccurs="0"/>
+ <xs:element name="indir" type="indir_type" minOccurs="0"/>
+ <xs:element name="sub2" type="sub_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="indir_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="test_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:element name="test" type="test_type" />
+</xs:schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test parser resetting.
+//
+
+#include <assert.h>
+
+#include <string>
+#include <iostream>
+
+#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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <a><b>1</b></a>
+ <a><b>1</b></a>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <a></b>1</b></a>
+
+</t:root>
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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <a><b>1</b></a>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="inner">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="a" type="t:inner"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Insert test description here.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <a>a</a>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="type">
+ <sequence>
+ <element name="a" type="string"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test xsd:union parsing.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <int-string-union/>
+ <int-string-union> </int-string-union>
+ <int-string-union>one</int-string-union>
+ <int-string-union>1</int-string-union>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="int-string-union">
+ <union memberTypes="int string"/>
+ </simpleType>
+
+ <complexType name="type">
+ <choice maxOccurs="unbounded">
+ <element name="int-string-union" type="t:int-string-union"/>
+ </choice>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the all compositor validation.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- all combinations -->
+ <all>
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ </all>
+
+ <all>
+ <a>a</a>
+ <c>c</c>
+ <b>b</b>
+ </all>
+
+ <all>
+ <b>b</b>
+ <a>a</a>
+ <c>c</c>
+ </all>
+
+ <all>
+ <b>b</b>
+ <c>c</c>
+ <a>a</a>
+ </all>
+
+ <all>
+ <c>c</c>
+ <a>a</a>
+ <b>b</b>
+ </all>
+
+ <all>
+ <c>c</c>
+ <b>b</b>
+ <a>a</a>
+ </all>
+
+ <!-- optional c is not present -->
+ <all>
+ <a>a</a>
+ <b>b</b>
+ </all>
+
+ <all>
+ <a>a</a>
+ <b>b</b>
+ </all>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- required b is not present (invalid) -->
+ <all>
+ <a>a</a>
+ <c>c</c>
+ </all>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <all>
+ </all>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <all>
+ <a>a</a>
+ <b>b</b>
+ <a>a</a>
+ </all>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="all">
+ <all minOccurs="1">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ <element name="c" type="string" minOccurs="0"/>
+ </all>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="all" type="t:all" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the any particle validation.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- test dispatching of any-nested elements and attributes -->
+
+ <any-a>
+ <o:any/>
+ </any-a>
+
+ <any-a>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </any-a>
+
+ <any-a x="x">
+ <a>a</a>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </any-a>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="any-a">
+ <sequence>
+ <element name="a" type="string" minOccurs="0"/>
+ <any namespace="other" processContents="skip" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="x" type="string"/>
+ </complexType>
+
+ <complexType name="type">
+ <choice maxOccurs="unbounded">
+ <element name="any-a" type="t:any-a"/>
+ </choice>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <pass-a b="b" t:foo="foo" t:bar="bar"/>
+ <pass-b a="a" b="b"/>
+ <pass-c a="a" b="b"/>
+ <fail/>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+
+ <!-- Test optional and required attributes as well as a wildcard. -->
+ <complexType name="pass-a">
+ <attribute name="a" type="string" use="optional"/>
+ <attribute name="b" type="string" use="required"/>
+ <anyAttribute namespace="##targetNamespace" processContents="skip"/>
+ </complexType>
+
+
+ <!-- Test that in inheritance attributes are checked before wildcards. -->
+ <complexType name="pass-b-base">
+ <attribute name="a" type="string"/>
+ <anyAttribute namespace="#any" processContents="skip"/>
+ </complexType>
+
+ <complexType name="pass-b">
+ <complexContent>
+ <extension base="t:pass-b-base">
+ <attribute name="b" type="string"/>
+ <anyAttribute namespace="#any" processContents="skip"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+
+ <!-- Test that in inheritance by restriction required attribute is
+ checked for even though it is not explicitly mentioned in
+ derived. -->
+ <complexType name="pass-c-base">
+ <attribute name="a" type="string" use="required"/>
+ <attribute name="b" type="string" use="optional"/>
+ </complexType>
+
+ <complexType name="pass-c">
+ <complexContent>
+ <restriction base="t:pass-c-base">
+ <attribute name="b" type="string" use="required"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+
+ <!-- Test detection of missing required attribute. -->
+ <complexType name="fail-base">
+ <attribute name="a" type="string" use="optional"/>
+ </complexType>
+
+ <complexType name="fail">
+ <complexContent>
+ <restriction base="t:fail-base">
+ <attribute name="a" type="string" use="required"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+
+ <complexType name="type">
+ <sequence>
+ <element name="pass-a" type="t:pass-a"/>
+ <element name="pass-b" type="t:pass-b"/>
+ <element name="pass-c" type="t:pass-c"/>
+ <element name="fail" type="t:fail"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd"
+ as="123abc">
+
+ <!-- test dispatching of anyType nested elements and attributes -->
+
+ <a>
+ <o:any/>
+ </a>
+
+ <a>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </a>
+
+ <a x="x">
+ <a>a</a>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </a>
+
+ <!-- anyType extension -->
+
+ <a-extension>
+ <o:any/>
+ </a-extension>
+
+ <a-extension>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </a-extension>
+
+ <a-extension x="x">
+ <a>a</a>
+ <o:any x="xxx">aaa<a>bbb</a>ccc</o:any>
+ </a-extension>
+
+ <!-- anySimpleType extension -->
+
+ <as-extension x="x">abc123</as-extension>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="any-extension">
+ <complexContent mixed="true">
+ <extension base="anyType">
+ <attribute name="x" type="string"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="any-simple-extension">
+ <simpleContent>
+ <extension base="anySimpleType">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <choice maxOccurs="unbounded">
+ <element name="a" type="anyType"/>
+ <element name="a-extension" type="t:any-extension"/>
+ <element name="as-extension" type="t:any-simple-extension"/>
+ </choice>
+ <attribute name="as" type="anySimpleType"/>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <cassert>
+#include <string.h> // memcpy
+
+#include <xsde/cxx/parser/validating/base64-binary.hxx>
+#include <xsde/cxx/parser/validating/hex-binary.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/boolean.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/byte.hxx>
+#include <xsde/cxx/parser/validating/unsigned-byte.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <math.h>
+#include <cassert>
+
+#include <xsde/cxx/parser/validating/float.hxx>
+#include <xsde/cxx/parser/validating/double.hxx>
+#include <xsde/cxx/parser/validating/decimal.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/int.hxx>
+#include <xsde/cxx/parser/validating/unsigned-int.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <limits.h>
+
+#include <string>
+#include <sstream>
+#include <cassert>
+
+#include <xsde/cxx/parser/validating/integer.hxx>
+#include <xsde/cxx/parser/validating/negative-integer.hxx>
+#include <xsde/cxx/parser/validating/non-positive-integer.hxx>
+#include <xsde/cxx/parser/validating/positive-integer.hxx>
+#include <xsde/cxx/parser/validating/non-negative-integer.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/long-long.hxx>
+#include <xsde/cxx/parser/validating/unsigned-long-long.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/long.hxx>
+#include <xsde/cxx/parser/validating/unsigned-long.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/config.h>
+
+// Let the runtime header sort out which version (stl/no-stl) to
+// include.
+//
+#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/parser/validating/short.hxx>
+#include <xsde/cxx/parser/validating/unsigned-short.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <string>
+#include <cassert>
+
+#include <xsde/config.h>
+
+// Let the runtime header sort out which version (stl/no-stl) to
+// include.
+//
+#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>
+
+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<b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ // nmtoken
+ //
+ {
+ context c (0);
+ nmtoken_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ nmtoken_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a,b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ nmtoken_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ nmtoken_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a<b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ // nmtokens
+ //
+ {
+ context c (0);
+ nmtokens_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters (" ");
+ p._characters (" \t\n ");
+ p._post_impl ();
+ assert (c.schema_error () == schema_error::invalid_nmtokens_value);
+ }
+
+ {
+ context c (0);
+ nmtokens_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("ab a,b");
+ p._post_impl ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ // ncname
+ //
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters (".a");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("-a");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters (":a");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("1a");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a:b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a,b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ {
+ context c (0);
+ ncname_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a<b");
+ p._post ();
+ assert (c.schema_error ());
+ }
+
+ // id
+ //
+ {
+ context c (0);
+ id_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a b");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_id_value);
+ }
+
+ // idref
+ //
+ {
+ context c (0);
+ idref_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a b");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_idref_value);
+ }
+
+ // idrefs
+ //
+ {
+ context c (0);
+ idrefs_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters (" ");
+ p._characters (" \t\n ");
+ p._post_impl ();
+ assert (c.schema_error () == schema_error::invalid_idrefs_value);
+ }
+
+ {
+ context c (0);
+ idrefs_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("ab a<b");
+ p._post_impl ();
+ assert (c.schema_error () == schema_error::invalid_idref_value);
+ }
+
+ // language
+ //
+ {
+ context c (0);
+ language_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters (" ");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ context c (0);
+ language_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("en-");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ context c (0);
+ language_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("a1");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ context c (0);
+ language_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("en+us");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ context c (0);
+ language_pimpl p;
+ p.pre ();
+ p._pre_impl (c);
+ p._characters ("en-nine99999");
+ p._post ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+}
diff --git a/tests/cxx/parser/validation/built-in/string/makefile b/tests/cxx/parser/validation/built-in/string/makefile
new file mode 100644
index 0000000..27fc822
--- /dev/null
+++ b/tests/cxx/parser/validation/built-in/string/makefile
@@ -0,0 +1,61 @@
+# file : tests/cxx/parser/validation/built-in/string/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <string>
+#include <cassert>
+
+// Let the runtime header sort out which version (stl/no-stl) to
+// include.
+//
+#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the choice compositor validation.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <choice>
+ <a>a</a>
+
+ <b>b</b>
+ </choice>
+
+ <choice>
+ <c>c</c>
+ <d>d</d>
+
+ <o:any>any</o:any>
+
+ <a>a</a>
+ </choice>
+
+ <choice>
+ <c>c</c>
+ <d>d</d>
+
+ <d>d</d>
+
+ <a>a</a>
+ </choice>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <choice>
+ </choice>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <choice>
+ <c>c</c>
+ <d>d</d>
+
+ <o:any>any</o:any>
+
+ <a>a</a>
+ <b>b</b>
+ </choice>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <choice>
+ <c>c</c>
+ </choice>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- invalid -->
+ <choice>
+ <x>x</x>
+ </choice>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="choice">
+ <choice maxOccurs="3">
+ <element name="a" type="string"/>
+ <element name="b" type="string" maxOccurs="unbounded"/>
+ <sequence>
+ <element name="c" type="string" minOccurs="0"/>
+ <element name="d" type="string"/>
+ </sequence>
+ <any namespace="other" maxOccurs="unbounded"/>
+ </choice>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="choice" type="t:choice" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the restriction compositor validation.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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
--- /dev/null
+++ b/tests/cxx/parser/validation/restriction/test-000.std
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <restriction-a z="z">
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ </restriction-a>
+
+ <restriction-a x="x" y="y" z="z">
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ </restriction-a>
+
+ <restriction-b y="y">
+ <a>a</a>
+ <b>b</b>
+ </restriction-b>
+
+ <restriction-b y="y">
+ <a>a</a>
+ <c>c</c>
+ </restriction-b>
+
+ <restriction-b x="x" y="y">
+ <a>a</a>
+ </restriction-b>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- valid base but not restriction: a element -->
+ <restriction-a z="z">
+ <b>b</b>
+ <c>c</c>
+ </restriction-a>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- valid base but not restriction: z attribute -->
+ <restriction-a>
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ </restriction-a>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- valid base but not restriction: sequence maxOccurs="1" -->
+ <restriction-a z="z">
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ </restriction-a>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- valid extension but not restriction: a element -->
+ <restriction-b y="y">
+ <b>b</b>
+ </restriction-b>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- valid extension but not restriction: y attribute -->
+ <restriction-b>
+ <a>a</a>
+ <b>b</b>
+ </restriction-b>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- simple case -->
+ <complexType name="base-a">
+ <sequence minOccurs="1" maxOccurs="2">
+ <element name="a" type="string" minOccurs="0"/>
+ <element name="b" type="string"/>
+ <element name="c" type="string"/>
+ </sequence>
+ <attribute name="x" type="string"/>
+ <attribute name="y" type="string"/>
+ <attribute name="z" type="string"/>
+ </complexType>
+
+ <complexType name="restriction-a">
+ <complexContent>
+ <restriction base="t:base-a">
+ <sequence minOccurs="1" maxOccurs="1">
+ <element name="a" type="string" minOccurs="1"/>
+ <element name="b" type="string"/>
+ <element name="c" type="string"/>
+ </sequence>
+ <!-- Can be ommited if not changed, e.g., 'x'. -->
+ <attribute name="y" type="string"/> <!-- But can also be repeated without change. -->
+ <attribute name="z" type="string" use="required"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- restriction of an extension -->
+ <complexType name="base-b">
+ <sequence>
+ <element name="a" type="string" minOccurs="0"/>
+ </sequence>
+ <attribute name="x" type="string"/>
+ </complexType>
+
+ <complexType name="extension-b">
+ <complexContent>
+ <extension base="t:base-b">
+ <choice>
+ <element name="b" type="string" minOccurs="0"/>
+ <element name="c" type="string"/>
+ </choice>
+ <attribute name="y" type="string"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="restriction-b">
+ <complexContent>
+ <restriction base="t:extension-b">
+ <sequence>
+ <sequence>
+ <element name="a" type="string" minOccurs="1"/>
+ </sequence>
+ <choice>
+ <element name="b" type="string" minOccurs="0"/>
+ <element name="c" type="string"/>
+ </choice>
+ </sequence>
+ <attribute name="y" type="string" use="required"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type-b">
+ <choice maxOccurs="unbounded">
+ <element name="restriction-a" type="t:base-a"/>
+ <element name="restriction-b" type="t:extension-b"/>
+ </choice>
+ </complexType>
+
+ <complexType name="type-r">
+ <choice maxOccurs="unbounded">
+ <element name="restriction-a" type="t:restriction-a"/>
+ <element name="restriction-b" type="t:restriction-b"/>
+ </choice>
+ </complexType>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the sequence compositor validation.
+//
+
+#include <string>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <sequence>
+ <c>c</c>
+ <d>d</d>
+ <t:any>aaa<a>bbb</a>ccc</t:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+ <sequence>
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ <d>d</d>
+ <d>d</d>
+ <d>d</d>
+ <o:any>any</o:any>
+ <f>f</f>
+ <e>e</e>
+ <e>e</e>
+ </sequence>
+
+ <sequence>
+ <a>a</a>
+ <b>b</b>
+ <c>c</c>
+ <d>d</d>
+ <d>d</d>
+ <d>d</d>
+ <o:any>any</o:any>
+ <f>f</f>
+ <e>e</e>
+ <e>e</e>
+
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail minOccurs="1" -->
+ <sequence>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail maxOccurs="2" -->
+ <sequence>
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail a maxOccurs="1" -->
+ <sequence>
+ <a>a</a>
+ <a>a</a>
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail c minOccurs="1" -->
+ <sequence>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o1="other1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail any namespace="##targetNamespace other" -->
+ <sequence>
+ <c>c</c>
+ <d>d</d>
+ <o1:any>any</o1:any>
+ <f>f</f>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<t:root xmlns:t="test"
+ xmlns:o="other"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="test test.xsd">
+
+ <!-- fail e maxOccurs="2" -->
+ <sequence>
+ <c>c</c>
+ <d>d</d>
+ <t:any>any</t:any>
+ <f>f</f>
+ <e>e</e>
+ <e>e</e>
+ <e>e</e>
+ </sequence>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="sequence">
+ <sequence minOccurs="1" maxOccurs="2">
+ <element name="a" type="string" minOccurs="0"/>
+ <sequence>
+ <element name="b" type="string" minOccurs="0"/>
+ <element name="c" type="string"/>
+ </sequence>
+ <element name="d" type="string" maxOccurs="unbounded"/>
+ <sequence>
+ <any namespace="##targetNamespace other"/>
+ <element name="f" type="string"/>
+ </sequence>
+ <element name="e" type="string" maxOccurs="2"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="sequence" type="t:sequence" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the all compositor serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><test-1><a>123</a><b>234</b></test-1><test-2></test-2><test-2><a>123</a><b>234</b></test-2></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <all>
+ <element name="a" type="int"/>
+ <element name="b" type="int" minOccurs="0"/>
+ </all>
+ </complexType>
+
+ <complexType name="test-2">
+ <all minOccurs="0">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </all>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1" maxOccurs="unbounded"/>
+ <element name="test-2" type="t:test-2" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test built-in type serialization.
+//
+
+#include <stdlib.h> // strtof, strtod
+#include <string.h> // memcpy
+#include <iostream>
+
+#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<char> (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<char> (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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><any-type foo="one" g1:foo="two"><g1:inner>hello</g1:inner></any-type><any-simple-type>hello</any-simple-type><boolean>true</boolean><boolean>false</boolean><byte>-128</byte><byte>-123</byte><byte>0</byte><byte>127</byte><unsigned-byte>0</unsigned-byte><unsigned-byte>123</unsigned-byte><unsigned-byte>255</unsigned-byte><short>-32768</short><short>-12345</short><short>0</short><short>32767</short><unsigned-short>0</unsigned-short><unsigned-short>12345</unsigned-short><unsigned-short>65535</unsigned-short><int>-2147483648</int><int>-1234567890</int><int>0</int><int>2147483647</int><unsigned-int>0</unsigned-int><unsigned-int>1234567890</unsigned-int><unsigned-int>4294967295</unsigned-int><long>-2147483648</long><long>-1234567890</long><long>0</long><long>2147483647</long><unsigned-long>0</unsigned-long><unsigned-long>1234567890</unsigned-long><unsigned-long>4294967295</unsigned-long><integer>-2147483648</integer><integer>-1234567890</integer><integer>0</integer><integer>2147483647</integer><negative-integer>-2147483648</negative-integer><negative-integer>-1234567890</negative-integer><non-positive-integer>-2147483648</non-positive-integer><non-positive-integer>-1234567890</non-positive-integer><non-positive-integer>0</non-positive-integer><positive-integer>1234567890</positive-integer><positive-integer>4294967295</positive-integer><non-negative-integer>0</non-negative-integer><non-negative-integer>1234567890</non-negative-integer><non-negative-integer>4294967295</non-negative-integer><float>INF</float><float>-INF</float><float>NaN</float><float>0</float><float>1</float><float>-1</float><float>123.567</float><float>-1.23567e+07</float><float>-4.5e-06</float><double>INF</double><double>-INF</double><double>NaN</double><double>0</double><double>1</double><double>-1</double><double>123.56789</double><double>-12356789000</double><double>-4.5e-06</double><decimal>0</decimal><decimal>1</decimal><decimal>-1</decimal><decimal>123.567890000000006</decimal><decimal>-123.567890000000006</decimal><string> test
+ string </string><normalized-string>test normalized string</normalized-string><token>test token</token><name>as123:345-.abs</name><nmtoken>1as123:345-.abs</nmtoken><nmtokens>one</nmtokens><nmtokens>one two three</nmtokens><ncname>as123_345-.abs</ncname><id>as123_345-.abs</id><id>one</id><id>two</id><id>three</id><idref>as123_345-.abs</idref><idrefs>one</idrefs><idrefs>two three</idrefs><language>en-us</language><uri>http://www.example.com/foo#bar</uri><qname>g1:qname</qname><qname>qname</qname><base64_binary></base64_binary><base64_binary>MTIzNDVhYmNqaw==
+</base64_binary><base64_binary>YQ==
+</base64_binary><base64_binary>YWI=
+</base64_binary><base64_binary>YWJj
+</base64_binary><base64_binary>AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4
+OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq
+q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj
+5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhsc
+HR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RV
+VldY
+</base64_binary><hex_binary></hex_binary><hex_binary>31323334356162636A6B</hex_binary><hex_binary>000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758</hex_binary><gday>---23</gday><gday>---31+02:30</gday><gday>---15Z</gday><gmonth>--06</gmonth><gmonth>--12+02:30</gmonth><gyear>2007</gyear><gyear>-2007-02:30</gyear><gmonth_day>--06-15</gmonth_day><gmonth_day>--12-31+02:30</gmonth_day><gyear_month>2007-10</gyear_month><gyear_month>-2007-12-02:30</gyear_month><date>2007-06-15</date><date>-2007-12-31-02:30</date><time>12:30:30</time><time>23:59:59.55+02:30</time><date_time>2007-06-15T12:30:30</date_time><date_time>-2007-12-31T23:59:59.55-02:30</date_time><duration>P1Y</duration><duration>-P1M</duration><duration>P1D</duration><duration>-PT1H</duration><duration>PT1M</duration><duration>-PT1.1S</duration><duration>P1Y2M3DT4H5M6.7S</duration></g1:root> \ 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 @@
+<g1:root xmlns:g1="test"><any-type foo="one" g1:foo="two"><g1:inner>hello</g1:inner></any-type><any-simple-type>hello</any-simple-type><boolean>true</boolean><boolean>false</boolean><byte>-128</byte><byte>-123</byte><byte>0</byte><byte>127</byte><unsigned-byte>0</unsigned-byte><unsigned-byte>123</unsigned-byte><unsigned-byte>255</unsigned-byte><short>-32768</short><short>-12345</short><short>0</short><short>32767</short><unsigned-short>0</unsigned-short><unsigned-short>12345</unsigned-short><unsigned-short>65535</unsigned-short><int>-2147483648</int><int>-1234567890</int><int>0</int><int>2147483647</int><unsigned-int>0</unsigned-int><unsigned-int>1234567890</unsigned-int><unsigned-int>4294967295</unsigned-int><long>-9223372036854775808</long><long>-1234567890123456789</long><long>0</long><long>9223372036854775807</long><unsigned-long>0</unsigned-long><unsigned-long>12345678901234567890</unsigned-long><unsigned-long>18446744073709551615</unsigned-long><integer>-2147483648</integer><integer>-1234567890</integer><integer>0</integer><integer>2147483647</integer><negative-integer>-2147483648</negative-integer><negative-integer>-1234567890</negative-integer><non-positive-integer>-2147483648</non-positive-integer><non-positive-integer>-1234567890</non-positive-integer><non-positive-integer>0</non-positive-integer><positive-integer>1234567890</positive-integer><positive-integer>4294967295</positive-integer><non-negative-integer>0</non-negative-integer><non-negative-integer>1234567890</non-negative-integer><non-negative-integer>4294967295</non-negative-integer><float>INF</float><float>-INF</float><float>NaN</float><float>0</float><float>1</float><float>-1</float><float>123.567</float><float>-1.23567e+07</float><float>-4.5e-06</float><double>INF</double><double>-INF</double><double>NaN</double><double>0</double><double>1</double><double>-1</double><double>123.56789</double><double>-12356789000</double><double>-4.5e-06</double><decimal>0</decimal><decimal>1</decimal><decimal>-1</decimal><decimal>123.567890000000006</decimal><decimal>-123.567890000000006</decimal><string> test
+ string </string><normalized-string>test normalized string</normalized-string><token>test token</token><name>as123:345-.abs</name><nmtoken>1as123:345-.abs</nmtoken><nmtokens>one</nmtokens><nmtokens>one two three</nmtokens><ncname>as123_345-.abs</ncname><id>as123_345-.abs</id><id>one</id><id>two</id><id>three</id><idref>as123_345-.abs</idref><idrefs>one</idrefs><idrefs>two three</idrefs><language>en-us</language><uri>http://www.example.com/foo#bar</uri><qname>g1:qname</qname><qname>qname</qname><base64_binary></base64_binary><base64_binary>MTIzNDVhYmNqaw==
+</base64_binary><base64_binary>YQ==
+</base64_binary><base64_binary>YWI=
+</base64_binary><base64_binary>YWJj
+</base64_binary><base64_binary>AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4
+OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmq
+q6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj
+5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/wABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhsc
+HR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RV
+VldY
+</base64_binary><hex_binary></hex_binary><hex_binary>31323334356162636A6B</hex_binary><hex_binary>000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758</hex_binary><gday>---23</gday><gday>---31+02:30</gday><gday>---15Z</gday><gmonth>--06</gmonth><gmonth>--12+02:30</gmonth><gyear>2007</gyear><gyear>-2007-02:30</gyear><gmonth_day>--06-15</gmonth_day><gmonth_day>--12-31+02:30</gmonth_day><gyear_month>2007-10</gyear_month><gyear_month>-2007-12-02:30</gyear_month><date>2007-06-15</date><date>-2007-12-31-02:30</date><time>12:30:30</time><time>23:59:59.55+02:30</time><date_time>2007-06-15T12:30:30</date_time><date_time>-2007-12-31T23:59:59.55-02:30</date_time><duration>P1Y</duration><duration>-P1M</duration><duration>P1D</duration><duration>-PT1H</duration><duration>PT1M</duration><duration>-PT1.1S</duration><duration>P1Y2M3DT4H5M6.7S</duration></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="root">
+ <sequence>
+ <element name="any-type" type="anyType"/>
+ <element name="any-simple-type" type="anySimpleType"/>
+
+ <element name="boolean" type="boolean" maxOccurs="unbounded"/>
+ <element name="byte" type="byte" maxOccurs="unbounded"/>
+ <element name="unsigned-byte" type="unsignedByte" maxOccurs="unbounded"/>
+ <element name="short" type="short" maxOccurs="unbounded"/>
+ <element name="unsigned-short" type="unsignedShort" maxOccurs="unbounded"/>
+ <element name="int" type="int" maxOccurs="unbounded"/>
+ <element name="unsigned-int" type="unsignedInt" maxOccurs="unbounded"/>
+
+ <element name="long" type="long" maxOccurs="unbounded"/>
+ <element name="unsigned-long" type="unsignedLong" maxOccurs="unbounded"/>
+
+
+ <element name="integer" type="integer" maxOccurs="unbounded"/>
+ <element name="negative-integer" type="negativeInteger" maxOccurs="unbounded"/>
+ <element name="non-positive-integer" type="nonPositiveInteger" maxOccurs="unbounded"/>
+ <element name="positive-integer" type="positiveInteger" maxOccurs="unbounded"/>
+ <element name="non-negative-integer" type="nonNegativeInteger" maxOccurs="unbounded"/>
+
+ <element name="float" type="float" maxOccurs="unbounded"/>
+ <element name="double" type="double" maxOccurs="unbounded"/>
+ <element name="decimal" type="decimal" maxOccurs="unbounded"/>
+
+ <element name="string" type="string" maxOccurs="unbounded"/>
+ <element name="normalized-string" type="normalizedString" maxOccurs="unbounded"/>
+ <element name="token" type="token" maxOccurs="unbounded"/>
+ <element name="name" type="Name" maxOccurs="unbounded"/>
+ <element name="nmtoken" type="NMTOKEN" maxOccurs="unbounded"/>
+ <element name="nmtokens" type="NMTOKENS" maxOccurs="unbounded"/>
+ <element name="ncname" type="NCName" maxOccurs="unbounded"/>
+ <element name="id" type="ID" maxOccurs="unbounded"/>
+ <element name="idref" type="IDREF" maxOccurs="unbounded"/>
+ <element name="idrefs" type="IDREFS" maxOccurs="unbounded"/>
+
+ <element name="language" type="language" maxOccurs="unbounded"/>
+ <element name="uri" type="anyURI" maxOccurs="unbounded"/>
+ <element name="qname" type="QName" maxOccurs="unbounded"/>
+
+ <element name="base64_binary" type="base64Binary" maxOccurs="unbounded"/>
+ <element name="hex_binary" type="hexBinary" maxOccurs="unbounded"/>
+
+ <element name="gday" type="gDay" maxOccurs="unbounded"/>
+ <element name="gmonth" type="gMonth" maxOccurs="unbounded"/>
+ <element name="gyear" type="gYear" maxOccurs="unbounded"/>
+ <element name="gmonth_day" type="gMonthDay" maxOccurs="unbounded"/>
+ <element name="gyear_month" type="gYearMonth" maxOccurs="unbounded"/>
+ <element name="date" type="date" maxOccurs="unbounded"/>
+ <element name="time" type="time" maxOccurs="unbounded"/>
+ <element name="date_time" type="dateTime" maxOccurs="unbounded"/>
+ <element name="duration" type="duration" maxOccurs="unbounded"/>
+
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the choice compositor serialization.
+//
+
+#include <iostream>
+
+#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<choice_arm_tag> (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<choice_arm_tag> (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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><test-1><a>123</a></test-1><test-1><b>234</b></test-1><test-1><c>1</c><c>2</c><c>3</c></test-1><test-2></test-2><test-2><b>234</b></test-2><test-3><a>123</a><b>234</b><a>123</a><b>234</b></test-3><test-4><a>123</a></test-4><test-4><c>234</c></test-4><test-4><d>345</d><e>456</e></test-4></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <choice>
+ <element name="a" type="int"/>
+ <element name="b" type="int" minOccurs="0"/>
+ <element name="c" type="int" maxOccurs="unbounded"/>
+ </choice>
+ </complexType>
+
+ <complexType name="test-2">
+ <choice minOccurs="0">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </choice>
+ </complexType>
+
+ <complexType name="test-3">
+ <choice maxOccurs="unbounded">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </choice>
+ </complexType>
+
+ <complexType name="test-4">
+ <choice>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="int"/>
+ <element name="c" type="int"/>
+ </choice>
+ <sequence>
+ <element name="d" type="int"/>
+ <element name="e" type="int"/>
+ </sequence>
+ </choice>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1" maxOccurs="unbounded"/>
+ <element name="test-2" type="t:test-2" maxOccurs="unbounded"/>
+ <element name="test-3" type="t:test-3" maxOccurs="unbounded"/>
+ <element name="test-4" type="t:test-4" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test complex types serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><base x="123" y="234"><a>-123</a><b>-234</b></base><derived x="123" y="234" z="345"><a>-123</a><b>-234</b><c>-345</c></derived></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </sequence>
+ <attribute name="x" type="int" use="required"/>
+ <attribute name="y" type="int" use="required"/>
+ </complexType>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="c" type="int"/>
+ </sequence>
+ <attribute name="z" type="int" use="required"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="base" type="t:base"/>
+ <element name="derived" type="t:derived"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test enumeration type serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><digit>7</digit><boolean>1</boolean></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="digit">
+ <restriction base="int">
+ <enumeration value="0"/>
+ <enumeration value="1"/>
+ <enumeration value="2"/>
+ <enumeration value="3"/>
+ <enumeration value="4"/>
+ <enumeration value="5"/>
+ <enumeration value="6"/>
+ <enumeration value="7"/>
+ <enumeration value="8"/>
+ <enumeration value="9"/>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="boolean">
+ <restriction base="int">
+ <enumeration value="0"/>
+ <enumeration value="1"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="digit" type="t:digit"/>
+ <element name="boolean" type="t:boolean"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <cassert>
+#include <sstream>
+#include <iostream>
+
+#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 ("<g1:root xmlns:g1=\"test\"><test x=\"-1\" y=\"-2\">"
+ "<a>1</a><b>2</b><c>3</c><c>4</c><c>5</c></test></g1:root>");
+ */
+
+ // 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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="int" minOccurs="0"/>
+ <element name="c" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="x" type="int"/>
+ <attribute name="y" type="int" use="required"/>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test" type="t:test"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test error reporting with exceptions.
+//
+
+#include <cassert>
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="int" minOccurs="0"/>
+ <element name="c" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="x" type="int"/>
+ <attribute name="y" type="int" use="required"/>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test" type="t:test"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><value>123</value></g1:root> \ 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 <boris@codesynthesis.com>
+// 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 <boris@codesynthesis.com>
+// 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="type">
+ <sequence>
+ <element name="value" type="int"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- enum -->
+
+ <simpleType name="gender">
+ <restriction base="string">
+ <enumeration value="male"/>
+ <enumeration value="female"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="gender-extension">
+ <simpleContent>
+ <extension base="t:gender">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- list -->
+
+ <simpleType name="list">
+ <list itemType="int"/>
+ </simpleType>
+
+ <complexType name="list-extension">
+ <simpleContent>
+ <extension base="t:list">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- union -->
+
+ <simpleType name="union">
+ <union memberTypes="int string"/>
+ </simpleType>
+
+ <complexType name="union-extension">
+ <simpleContent>
+ <extension base="t:union">
+ <attribute name="foo" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- complex -->
+
+ <complexType name="complex">
+ <sequence>
+ <element name="a" type="string"/>
+ </sequence>
+ <attribute name="x" type="string" use="required"/>
+ </complexType>
+
+ <complexType name="complex-extension">
+ <complexContent>
+ <extension base="t:complex">
+ <sequence>
+ <element name="b" type="string" minOccurs="0"/>
+ <element name="c" type="string" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="y" type="string"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="complex-opt-all">
+ <all minOccurs="0">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ </all>
+ </complexType>
+
+ <complexType name="complex-opt-seq">
+ <sequence minOccurs="0">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="complex-seq-seq">
+ <sequence maxOccurs="unbounded">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="complex-opt-choice">
+ <choice minOccurs="0">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ </choice>
+ </complexType>
+
+ <complexType name="complex-seq-choice">
+ <choice maxOccurs="unbounded">
+ <element name="a" type="string"/>
+ <element name="b" type="string"/>
+ </choice>
+ </complexType>
+
+ <complexType name="complex-any">
+ <sequence>
+ <any namespace="foo" processContents="skip" minOccurs="0"/>
+ <any namespace="bar" processContents="skip" maxOccurs="unbounded"/>
+ </sequence>
+ <anyAttribute namespace="foo" processContents="skip"/>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="gender" type="t:gender"/>
+ <element name="gender-extension" type="t:gender-extension"/>
+
+ <element name="list" type="t:list"/>
+ <element name="list-extension" type="t:list-extension"/>
+
+ <element name="union" type="t:union"/>
+ <element name="union-extension" type="t:union-extension"/>
+
+ <element name="complex" type="t:complex"/>
+ <element name="complex-extension" type="t:complex-extension"/>
+
+ <element name="complex-opt-all" type="t:complex-opt-all"/>
+ <element name="complex-opt-seq" type="t:complex-opt-seq"/>
+ <element name="complex-seq-seq" type="t:complex-seq-seq"/>
+ <element name="complex-opt-choice" type="t:complex-opt-choice"/>
+ <element name="complex-seq-choice" type="t:complex-seq-choice"/>
+ <element name="complex-any" type="t:complex-any"/>
+
+ <!-- Built-in types. -->
+
+ <element name="any-type" type="anyType" maxOccurs="unbounded"/>
+ <element name="any-simple-type" type="anySimpleType" maxOccurs="unbounded"/>
+
+ <element name="boolean" type="boolean" maxOccurs="unbounded"/>
+
+ <element name="byte" type="byte" maxOccurs="unbounded"/>
+ <element name="unsigned-byte" type="unsignedByte" maxOccurs="unbounded"/>
+ <element name="short" type="short" maxOccurs="unbounded"/>
+ <element name="unsigned-short" type="unsignedShort" maxOccurs="unbounded"/>
+ <element name="int" type="int" maxOccurs="unbounded"/>
+ <element name="unsigned-int" type="unsignedInt" maxOccurs="unbounded"/>
+ <element name="long" type="long" maxOccurs="unbounded"/>
+ <element name="unsigned-long" type="unsignedLong" maxOccurs="unbounded"/>
+
+ <element name="integer" type="integer" maxOccurs="unbounded"/>
+ <element name="negative-integer" type="negativeInteger" maxOccurs="unbounded"/>
+ <element name="non-positive-integer" type="nonPositiveInteger" maxOccurs="unbounded"/>
+ <element name="positive-integer" type="positiveInteger" maxOccurs="unbounded"/>
+ <element name="non-negative-integer" type="nonNegativeInteger" maxOccurs="unbounded"/>
+
+ <element name="float" type="float" maxOccurs="unbounded"/>
+ <element name="double" type="double" maxOccurs="unbounded"/>
+ <element name="decimal" type="decimal" maxOccurs="unbounded"/>
+
+ <element name="string" type="string" maxOccurs="unbounded"/>
+ <element name="normalized-string" type="normalizedString" maxOccurs="unbounded"/>
+ <element name="token" type="token" maxOccurs="unbounded"/>
+ <element name="name" type="Name" maxOccurs="unbounded"/>
+ <element name="nmtoken" type="NMTOKEN" maxOccurs="unbounded"/>
+ <element name="nmtokens" type="NMTOKENS" maxOccurs="unbounded"/>
+ <element name="ncname" type="NCName" maxOccurs="unbounded"/>
+ <element name="id" type="ID" maxOccurs="unbounded"/>
+ <element name="idref" type="IDREF" maxOccurs="unbounded"/>
+ <element name="idrefs" type="IDREFS" maxOccurs="unbounded"/>
+
+ <element name="language" type="language" maxOccurs="unbounded"/>
+ <element name="uri" type="anyURI" maxOccurs="unbounded"/>
+ <element name="qname" type="QName" maxOccurs="unbounded"/>
+
+ <element name="base64_binary" type="base64Binary" maxOccurs="unbounded"/>
+ <element name="hex_binary" type="hexBinary" maxOccurs="unbounded"/>
+
+ <element name="gday" type="gDay" maxOccurs="unbounded"/>
+ <element name="gmonth" type="gMonth" maxOccurs="unbounded"/>
+ <element name="gyear" type="gYear" maxOccurs="unbounded"/>
+ <element name="gmonth_day" type="gMonthDay" maxOccurs="unbounded"/>
+ <element name="gyear_month" type="gYearMonth" maxOccurs="unbounded"/>
+ <element name="date" type="date" maxOccurs="unbounded"/>
+ <element name="time" type="time" maxOccurs="unbounded"/>
+ <element name="date_time" type="dateTime" maxOccurs="unbounded"/>
+ <element name="duration" type="duration" maxOccurs="unbounded"/>
+
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test list type serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><int-list></int-list><int-list>1</int-list><int-list>1 2 3</int-list><int-list-base base="123"></int-list-base><int-list-base base="123">1</int-list-base><int-list-base base="123">1 2 3</int-list-base></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="int-list">
+ <list itemType="int"/>
+ </simpleType>
+
+ <complexType name="int-list-base">
+ <simpleContent>
+ <extension base="t:int-list">
+ <attribute name="base" type="int" use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="int-list" type="t:int-list" maxOccurs="unbounded"/>
+ <element name="int-list-base" type="t:int-list-base" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><t:base><a>1</a></t:base><t:base xsi:type="t:interm_type"><a>1</a><b>2</b></t:base><t:interm><a>1</a><b>2</b></t:interm><t:base xsi:type="t:derived_type"><a>1</a><b>2</b><c>3</c></t:base><t:derived><a>1</a><b>2</b><c>3</c></t:derived></t:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ <element name="a" type="int"/>
+ </sequence>
+ </complexType>
+
+ <element name="base" type="t:base"/>
+
+ <complexType name="interm_type">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="interm">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <element name="interm" type="t:interm" substitutionGroup="t:base"/>
+
+ <complexType name="derived_type">
+ <complexContent>
+ <extension base="t:interm_type">
+ <sequence>
+ <element name="c" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:interm">
+ <sequence>
+ <element name="c" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <element name="derived" type="t:derived" substitutionGroup="t:interm"/>
+
+ <complexType name="type">
+ <sequence>
+ <element ref="t:base" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test recursive type serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test" name="234"><sub name="1"><sub name="2"></sub><indir name="123"><sub name="2"></sub></indir><sub2 name="2"></sub2></sub></g1:root> \ 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 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:complexType name="sub_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" minOccurs="0"/>
+ <xs:element name="indir" type="indir_type" minOccurs="0"/>
+ <xs:element name="sub2" type="sub_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:int" />
+ </xs:complexType>
+
+ <xs:complexType name="indir_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:int" />
+ </xs:complexType>
+
+ <xs:complexType name="test_type">
+ <xs:sequence>
+ <xs:element name="sub" type="sub_type" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:int" />
+ </xs:complexType>
+
+ <xs:element name="test" type="test_type" />
+</xs:schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test serializer resetting.
+//
+
+#include <assert.h>
+
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+1: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+2: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+3: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+4: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+5: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
+6: <t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test test.xsd"><a><b>1</b></a></t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="base">
+ <sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="inner">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="a" type="t:inner"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test inheritance-by-restriction serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><test-1 optional="123" required="234"></test-1><test-2><a>1</a><b>2</b><c>3</c><e>5</e></test-2><test-3><b>2</b><g>7</g></test-3><test-4><b>2</b><g>7</g></test-4></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- attribute restriction -->
+
+ <complexType name="test-1-base">
+ <attribute name="optional" type="int"/>
+ <attribute name="required" type="int" use="required"/>
+ <anyAttribute namespace="foo bar" processContents="skip"/>
+ </complexType>
+
+ <complexType name="test-1">
+ <complexContent>
+ <restriction base="t:test-1-base">
+ <attribute name="optional" type="int" use="required"/>
+ <anyAttribute namespace="foo" processContents="skip"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- simple content restriction -->
+
+ <complexType name="test-2-base">
+ <sequence>
+ <element name="a" type="int" minOccurs="0"/>
+ <sequence maxOccurs="unbounded">
+ <element name="b" type="int"/>
+ <element name="c" type="int"/>
+ </sequence>
+ <choice>
+ <element name="d" type="int"/>
+ <element name="e" type="int" minOccurs="0"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-2">
+ <complexContent>
+ <restriction base="t:test-2-base">
+ <sequence>
+ <element name="a" type="int" minOccurs="1"/>
+ <sequence maxOccurs="2">
+ <element name="b" type="int"/>
+ <element name="c" type="int"/>
+ </sequence>
+ <choice>
+ <element name="d" type="int"/>
+ <element name="e" type="int" minOccurs="1"/>
+ </choice>
+ </sequence>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- more complex content restriction with some parts removed-->
+
+ <complexType name="test-3-base">
+ <sequence>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="int"/>
+ <sequence minOccurs="0">
+ <element name="c" type="int"/>
+ <element name="d" type="int"/>
+ </sequence>
+ <choice>
+ <element name="e" type="int" minOccurs="0"/>
+ <element name="f" type="int"/>
+ <element name="g" type="int"/>
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-3">
+ <complexContent>
+ <restriction base="t:test-3-base">
+ <sequence>
+ <element name="b" type="int"/>
+ <choice>
+ <element name="f" type="int"/>
+ <element name="g" type="int"/>
+ </choice>
+ </sequence>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- complex content restriction spread over inheritance-by-extension-->
+
+ <complexType name="test-4-base">
+ <sequence>
+ <element name="a" type="int" minOccurs="0"/>
+ <element name="b" type="int"/>
+ </sequence>
+ <anyAttribute namespace="foo bar" processContents="skip"/>
+ </complexType>
+
+ <complexType name="test-4-ext">
+ <complexContent>
+ <extension base="t:test-4-base">
+ <sequence>
+ <sequence minOccurs="0">
+ <element name="c" type="int"/>
+ <element name="d" type="int"/>
+ </sequence>
+ <choice>
+ <element name="e" type="int" minOccurs="0"/>
+ <element name="f" type="int"/>
+ <element name="g" type="int"/>
+ </choice>
+ </sequence>
+ <anyAttribute namespace="baz biz" processContents="skip"/>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="test-4">
+ <complexContent>
+ <restriction base="t:test-4-ext">
+ <sequence>
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ <sequence>
+ <choice>
+ <element name="f" type="int"/>
+ <element name="g" type="int"/>
+ </choice>
+ </sequence>
+ </sequence>
+ <anyAttribute namespace="foo" processContents="skip"/>
+ <anyAttribute namespace="baz" processContents="skip"/>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- restriction of sequence into optional (compilation only) -->
+
+ <complexType name="test-5-base">
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element name="a" type="int" minOccurs="0" maxOccurs="unbounded"/>
+ <element name="b" type="int"/>
+ </choice>
+ <any namespace="foo" minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-5">
+ <complexContent>
+ <restriction base="t:test-5-base">
+ <sequence minOccurs="0" maxOccurs="1">
+ <choice minOccurs="0" maxOccurs="1">
+ <element name="a" type="int" minOccurs="0" maxOccurs="1"/>
+ <element name="b" type="int"/>
+ </choice>
+ <any namespace="foo" minOccurs="0" maxOccurs="1" processContents="skip"/>
+ </sequence>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <!-- -->
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1"/>
+ <element name="test-2" type="t:test-2"/>
+ <element name="test-3" type="t:test-3"/>
+ <element name="test-4" type="t:test-4"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test the sequence compositor serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><test-1><a>123</a><b>234</b><c>1</c><c>2</c><c>3</c></test-1><test-2></test-2><test-2><a>123</a><b>234</b></test-2><test-3><a>124</a><b>235</b><a>125</a><b>236</b><a>126</a><b>237</b></test-3><test-4><a>123</a><c>234</c><d>346</d><e>457</e><d>347</d><e>458</e><d>348</d><e>459</e></test-4></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="int" minOccurs="0"/>
+ <element name="c" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-2">
+ <sequence minOccurs="0">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-3">
+ <sequence maxOccurs="unbounded">
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-4">
+ <sequence>
+ <element name="a" type="int"/>
+ <choice>
+ <element name="b" type="int"/>
+ <element name="c" type="int"/>
+ </choice>
+ <sequence maxOccurs="unbounded">
+ <element name="d" type="int"/>
+ <element name="e" type="int"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1" maxOccurs="unbounded"/>
+ <element name="test-2" type="t:test-2" maxOccurs="unbounded"/>
+ <element name="test-3" type="t:test-3" maxOccurs="unbounded"/>
+ <element name="test-4" type="t:test-4" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Insert test description here.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><a>1234</a></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="root">
+ <sequence>
+ <element name="a" type="int"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test union type serialization.
+//
+
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test"><int-bool-union>123</int-bool-union><int-bool-union>false</int-bool-union><int-bool-base base="123">123</int-bool-base><int-bool-base base="123">false</int-bool-base></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="int-bool-union">
+ <union memberTypes="int boolean"/>
+ </simpleType>
+
+ <complexType name="int-bool-base">
+ <simpleContent>
+ <extension base="t:int-bool-union">
+ <attribute name="base" type="int" use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="int-bool-union" type="t:int-bool-union" maxOccurs="unbounded"/>
+ <element name="int-bool-base" type="t:int-bool-base" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test any validation.
+//
+
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <sequence>
+ <any namespace="foo" processContents="skip" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-2">
+ <sequence>
+ <any namespace="##any" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-3">
+ <sequence>
+ <any namespace="##other" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-4">
+ <sequence>
+ <any namespace="##local" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-5">
+ <sequence>
+ <any namespace="##targetNamespace" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="test-6">
+ <sequence>
+ <any namespace="bar" processContents="skip"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="root">
+ <choice>
+ <element name="test-1" type="t:test-1"/>
+ <element name="test-2" type="t:test-2"/>
+ <element name="test-3" type="t:test-3"/>
+ <element name="test-4" type="t:test-4"/>
+ <element name="test-5" type="t:test-5"/>
+ <element name="test-6" type="t:test-6"/>
+ </choice>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test attribute and anyAttribute validation.
+//
+
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <attribute name="x" type="int" use="required"/>
+ <anyAttribute namespace="##any" processContents="skip"/>
+ <anyAttribute namespace="##other" processContents="skip"/>
+ <anyAttribute namespace="##local" processContents="skip"/>
+ <anyAttribute namespace="##targetNamespace" processContents="skip"/>
+ <anyAttribute namespace="foo" processContents="skip"/>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <stdlib.h> // strtod
+#include <cassert>
+
+#include <xsde/cxx/serializer/validating/decimal.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/cxx/serializer/validating/negative-integer.hxx>
+#include <xsde/cxx/serializer/validating/non-positive-integer.hxx>
+#include <xsde/cxx/serializer/validating/positive-integer.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <cassert>
+
+#include <xsde/config.h>
+
+// Let the runtime header sort out which version (stl/no-stl) to
+// include.
+//
+#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// 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 <string>
+#include <cassert>
+
+#include <xsde/config.h>
+
+// Let the runtime header sort out which version (stl/no-stl) to
+// include.
+//
+#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>
+
+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<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 ");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_name_value);
+ }
+
+ // nmtoken
+ //
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre ("");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre (" a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre ("a,b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre ("a b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre ("a<b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ {
+ nmtoken_simpl s;
+ context c (0);
+ s.pre ("a ");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ // nmtokens
+ //
+ {
+ nmtokens_simpl s;
+ context c (0);
+ string_sequence seq;
+ s.pre (&seq);
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtokens_value);
+ }
+
+ {
+ nmtokens_simpl s;
+ context c (0);
+ string_sequence seq;
+#ifdef XSDE_STL
+ seq.push_back ("a,b");
+ seq.push_back ("ab");
+#else
+ seq.push_back_copy ("a,b");
+ seq.push_back_copy ("ab");
+#endif
+ s.pre (&seq);
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_nmtoken_value);
+ }
+
+ // ncname
+ //
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre (" a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre (".a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("-a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre (":a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("1a");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("a,b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("a b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("a:b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("a<b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ {
+ ncname_simpl s;
+ context c (0);
+ s.pre ("a ");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_ncname_value);
+ }
+
+ // id
+ //
+ {
+ id_simpl s;
+ context c (0);
+ s.pre ("a b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_id_value);
+ }
+
+ // idref
+ //
+ {
+ idref_simpl s;
+ context c (0);
+ s.pre ("a b");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_idref_value);
+ }
+
+ // idrefs
+ //
+ {
+ idrefs_simpl s;
+ context c (0);
+ string_sequence seq;
+ s.pre (&seq);
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_idrefs_value);
+ }
+
+ {
+ idrefs_simpl s;
+ context c (0);
+ string_sequence seq;
+#ifdef XSDE_STL
+ seq.push_back ("a,b");
+ seq.push_back ("ab");
+#else
+ seq.push_back_copy ("a,b");
+ seq.push_back_copy ("ab");
+#endif
+ s.pre (&seq);
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_idref_value);
+ }
+
+ // language
+ //
+ {
+ language_simpl s;
+ context c (0);
+ s.pre ("");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ language_simpl s;
+ context c (0);
+ s.pre (" ");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ language_simpl s;
+ context c (0);
+ s.pre ("en-");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ language_simpl s;
+ context c (0);
+ s.pre ("a1");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ language_simpl s;
+ context c (0);
+ s.pre ("en+us");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+
+ {
+ language_simpl s;
+ context c (0);
+ s.pre ("en-nine99999");
+ s._pre_impl (c);
+ s._serialize_content ();
+ assert (c.schema_error () == schema_error::invalid_language_value);
+ }
+}
diff --git a/tests/cxx/serializer/validation/built-in/string/makefile b/tests/cxx/serializer/validation/built-in/string/makefile
new file mode 100644
index 0000000..42a7d81
--- /dev/null
+++ b/tests/cxx/serializer/validation/built-in/string/makefile
@@ -0,0 +1,61 @@
+# file : tests/cxx/serializer/validation/built-in/string/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test choice validation.
+//
+
+#include <sstream>
+#include <iostream>
+
+#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<choice_arm_tag> (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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <choice maxOccurs="5">
+ <choice maxOccurs="unbounded"> <!-- 1..unbounded-->
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </choice>
+ </choice>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test element validation.
+//
+
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <sequence>
+ <element name="a" type="int" minOccurs="0" maxOccurs="5"/>
+ <element name="b" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test sequence validation.
+//
+
+#include <sstream>
+#include <iostream>
+
+#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 <boris@codesynthesis.com>
+# 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="test-1">
+ <sequence maxOccurs="5">
+ <sequence maxOccurs="unbounded"> <!-- 1..unbounded-->
+ <element name="a" type="int"/>
+ <element name="b" type="int"/>
+ </sequence>
+ </sequence>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <element name="test-1" type="t:test-1"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test wildcard (any & anyAttribute) serialization.
+//
+
+#include <string.h> // strcpy
+#include <iostream>
+
+#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_arm_tag> (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 <boris@codesynthesis.com>
+# 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 @@
+<g1:root xmlns:g1="test" xmlns:g2="foo" x="##local#x" g2:x="foo#x"><a x="123"><a>321</a></a><g2:a>0</g2:a><g2:a>1</g2:a><g2:a>2</g2:a><g3:b xmlns:g3="bar">bar#b</g3:b></g1:root> \ 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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <complexType name="content">
+ <sequence>
+ <element name="a" type="int"/>
+ </sequence>
+ <attribute name="x" type="int" use="required"/>
+ </complexType>
+
+ <complexType name="root">
+ <sequence>
+ <any namespace="##local" processContents="skip"/>
+ <choice maxOccurs="unbounded">
+ <any namespace="foo" processContents="skip" maxOccurs="unbounded"/>
+ <any namespace="bar" processContents="skip" minOccurs="0"/>
+ </choice>
+ </sequence>
+ <anyAttribute namespace="foo" processContents="skip"/>
+ <anyAttribute namespace="##local" processContents="skip"/>
+ </complexType>
+
+ <element name="root" type="t:root"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <assert.h>
+
+#include <xsde/cxx/string.hxx>
+
+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 <boris@codesynthesis.com>
+# 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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+
+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<NarrowString> const& nsm,
+ Containers::Vector<NarrowString> const& nsr,
+ Boolean trace_namespace_regex_,
+ Containers::Vector<NarrowString> const& ir,
+ Boolean trace_include_regex_,
+ Boolean inline_,
+ Containers::Vector<NarrowString> 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<SemanticGraph::Implies> ());
+ n = &u.schema ().names_begin ()->named ();
+ }
+
+ xs_ns_ = dynamic_cast<SemanticGraph::Namespace*> (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<NarrowString>::ConstIterator
+ i (nsr.begin ()), e (nsr.end ()); i != e; ++i)
+ {
+ nsr_mapping_.push_back (Regex (*i));
+ }
+
+ // Custom direct mapping.
+ //
+ for (Containers::Vector<NarrowString>::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<NarrowString>::ConstIterator
+ i (ir.begin ()), e (ir.end ()); i != e; ++i)
+ {
+ include_mapping_.push_back (Regex (*i));
+ }
+
+ // Reserved names.
+ //
+ for (Containers::Vector<NarrowString>::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<Schema&> (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<SemanticGraph::Namespace*> (&n));
+
+ return ns ? *ns : namespace_ (s);
+ }
+ else
+ {
+ SemanticGraph::Type& t (dynamic_cast<SemanticGraph::Type&> (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<Schema*> (&n))
+ {
+ return L""; // Map to global namespace.
+ }
+ else if (SemanticGraph::Namespace* ns =
+ dynamic_cast<SemanticGraph::Namespace*> (&n))
+ {
+ r = ns_name (*ns);
+ }
+ else
+ {
+ r = fq_name (n.scope ());
+ r += L"::";
+ r += n.context ().get<String> (
+ 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<Complex*> (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<SemanticGraph::Element*> (
+ "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<SemanticGraph::Any*> (
+ "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<SemanticGraph::Compositor*> (
+ "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<WideChar> (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<WideChar> (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<WideChar> (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<WideChar> (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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+#include <cult/containers/map.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <elements.hxx>
+
+#include <ostream>
+
+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<WideChar> RegexPat;
+ typedef BackendElements::Regex::Expression<WideChar> Regex;
+ typedef Cult::Containers::Vector<Regex> RegexMapping;
+ typedef Cult::Containers::Map<String, String> MapMapping;
+ typedef Cult::Containers::Map<String, String> MappingCache;
+
+ typedef Cult::Containers::Map<String, String> 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<NarrowString> const& nsm,
+ Containers::Vector<NarrowString> const& nsr,
+ Boolean trace_namespace_regex_,
+ Containers::Vector<NarrowString> const& include_regex,
+ Boolean trace_include_regex_,
+ Boolean inline_,
+ Containers::Vector<NarrowString> 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<String> (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 <typename X>
+ 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 <typename X, typename Y>
+ Boolean
+ has (Y& y)
+ {
+ using SemanticGraph::Scope;
+
+ Boolean result (false);
+ Has<X> 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 <typename X>
+ Boolean
+ has_particle (SemanticGraph::Compositor& y)
+ {
+ using SemanticGraph::Compositor;
+
+ Boolean result (false);
+ Has<X> 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<Compositor> ())
+ result = has_particle<X> (dynamic_cast<Compositor&> (p));
+ }
+
+ return result;
+ }
+
+ // Specialization for Complex
+ //
+ template <typename X>
+ Boolean
+ has_particle (SemanticGraph::Complex& c)
+ {
+ return c.contains_compositor_p () &&
+ has_particle<X> (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<Char> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+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<NarrowString>,
+ custom_parser, Cult::Containers::Vector<NarrowString>,
+ custom_serializer, Cult::Containers::Vector<NarrowString>,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element_all, Boolean,
+ root_element_none, Boolean,
+ root_element, Cult::Containers::Vector<NarrowString>,
+ root_type, Cult::Containers::Vector<NarrowString>,
+ 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<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ include_regex_trace, Boolean,
+ guard_prefix, NarrowString,
+ hxx_suffix, NarrowString,
+ ixx_suffix, NarrowString,
+ cxx_suffix, NarrowString,
+ fwd_suffix, NarrowString,
+ hxx_regex, Cult::Containers::Vector<NarrowString>,
+ ixx_regex, Cult::Containers::Vector<NarrowString>,
+ cxx_regex, Cult::Containers::Vector<NarrowString>,
+ fwd_regex, NarrowString,
+ hxx_prologue, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue, Cult::Containers::Vector<NarrowString>,
+ fwd_prologue, Cult::Containers::Vector<NarrowString>,
+ prologue, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ fwd_epilogue, Cult::Containers::Vector<NarrowString>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ hxx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ fwd_prologue_file, NarrowString,
+ prologue_file, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ fwd_epilogue_file, NarrowString,
+ epilogue_file, Cult::Containers::Vector<NarrowString>,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+
+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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ options (ops),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ stl (!ops.value<CLI::no_stl> ()),
+ poly_code (false),
+ poly_runtime (false),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ 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<String> ("p:ret-type");
+ }
+
+ String const& Context::
+ parg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:arg-type");
+ }
+
+ String const& Context::
+ post_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("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<String> ("ppre-impl");
+ }
+
+ String const& Context::
+ epname (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:name");
+ }
+
+ String const& Context::
+ epname (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("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<String> ("p:impl");
+ }
+
+ String const& Context::
+ epimpl_custom (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ if (!c.count ("p:impl-base"))
+ return c.get<String> ("p:impl");
+ else
+ return c.get<String> ("p:impl-base");
+ }
+
+ String const& Context::
+ epstate (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate");
+ }
+
+ String const& Context::
+ epstate_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-type");
+ }
+
+ String const& Context::
+ epstate_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-member");
+ }
+
+ String const& Context::
+ epstate_base (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-base");
+ }
+
+ String const& Context::
+ epstate_member (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("pstate-member");
+ }
+
+ String const& Context::
+ epskel (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:name");
+ }
+
+ String const& Context::
+ eppresent (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:present");
+ }
+
+ String const& Context::
+ epnext (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:next");
+ }
+
+ String const& Context::
+ eptag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:tag");
+ }
+
+ String const& Context::
+ eparm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm");
+ }
+
+ String const& Context::
+ eparm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm-tag");
+ }
+
+ // Serializer
+ //
+ String const& Context::
+ sret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:ret-type");
+ }
+
+ String const& Context::
+ sarg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:arg-type");
+ }
+
+ String const& Context::
+ esname (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:name");
+ }
+
+ String const& Context::
+ esname (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("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<String> ("s:impl");
+ }
+
+ String const& Context::
+ esimpl_custom (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ if (!c.count ("s:impl-base"))
+ return c.get<String> ("s:impl");
+ else
+ return c.get<String> ("s:impl-base");
+ }
+
+ String const& Context::
+ esstate (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate");
+ }
+
+ String const& Context::
+ esstate_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate-type");
+ }
+
+ String const& Context::
+ esstate_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate-member");
+ }
+
+ String const& Context::
+ esstate_member (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("sstate-member");
+ }
+
+ String const& Context::
+ esstate_member_end (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("sstate-member-end");
+ }
+
+ String const& Context::
+ esskel (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:name");
+ }
+
+ String const& Context::
+ espresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ espresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ esnext (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ estag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:tag");
+ }
+
+ String const& Context::
+ esarm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm");
+ }
+
+ String const& Context::
+ esarm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("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<Complex&> (
+ 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<Complex&> (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 <boris@codesynthesis.com>
+// 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 <sstream>
+
+#include <cult/containers/deque.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> 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<String> ("name");
+ }
+
+ static String const&
+ etype (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("type");
+ }
+
+ static String const&
+ emember (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("member");
+ }
+
+ static String const&
+ emember (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("member");
+ }
+
+ // Optional.
+ //
+ static String const&
+ epresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("present");
+ }
+
+ static String const&
+ epresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("present");
+ }
+
+ static String const&
+ epresent_member (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("present-member");
+ }
+
+ static String const&
+ epresent_member (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("present-member");
+ }
+
+ // Sequence.
+ //
+ static String const&
+ esequence (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("sequence");
+ }
+
+ static String const&
+ esequence (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("sequence");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("const-iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("const-iterator");
+ }
+
+ // Choice.
+ //
+ static String const&
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("tag");
+ }
+
+ static String const&
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm");
+ }
+
+ static String const&
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm-tag");
+ }
+
+ static UnsignedLong const&
+ arm_tag_count (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<UnsignedLong> ("arm-tag-count");
+ }
+
+ static String const&
+ earm_member (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm-member");
+ }
+
+ // Custom data.
+ //
+ static String const&
+ ecd_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-name");
+ }
+
+ static String const&
+ ecd_name (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-name");
+ }
+
+ static String const&
+ ecd_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-member");
+ }
+
+ static String const&
+ ecd_member (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-member");
+ }
+
+ static String const&
+ ecd_sequence (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-sequence");
+ }
+
+ static String const&
+ ecd_sequence (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-sequence");
+ }
+
+ static String const&
+ ecd_iterator (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-iterator");
+ }
+
+ static String const&
+ ecd_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-iterator");
+ }
+
+ static String const&
+ ecd_const_iterator (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-const-iterator");
+ }
+
+ static String const&
+ ecd_const_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("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<SemanticGraph::Restricts> ())
+ {
+ // Restriction of anyType is a special case.
+ //
+ return !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+
+ return false;
+ }
+
+ public:
+ static Boolean
+ fixed_length (SemanticGraph::Type& t)
+ {
+ return t.context ().get<Boolean> ("fixed");
+ }
+
+ static Boolean
+ fixed_length (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<Boolean> ("fixed");
+ }
+
+ public:
+ Void
+ close_ns ();
+
+ Void
+ open_ns ();
+
+ public:
+ typedef
+ Cult::Containers::Deque<String>
+ 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<CLI::no_long_long> ())
+ 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<CLI::no_long_long> ())
+ 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<CLI::generate_forward> ()),
+ 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+#include <cxx/hybrid/generator.hxx>
+
+#include <cxx/hybrid/validator.hxx>
+
+#include <cxx/hybrid/tree-size-processor.hxx>
+#include <cxx/hybrid/tree-name-processor.hxx>
+
+
+#include <cxx/hybrid/tree-forward.hxx>
+#include <cxx/hybrid/tree-header.hxx>
+#include <cxx/hybrid/tree-inline.hxx>
+#include <cxx/hybrid/tree-source.hxx>
+#include <cxx/hybrid/tree-type-map.hxx>
+
+#include <cxx/hybrid/parser-name-processor.hxx>
+#include <cxx/hybrid/parser-header.hxx>
+#include <cxx/hybrid/parser-source.hxx>
+#include <cxx/hybrid/parser-aggregate-header.hxx>
+#include <cxx/hybrid/parser-aggregate-source.hxx>
+
+#include <cxx/hybrid/serializer-name-processor.hxx>
+#include <cxx/hybrid/serializer-header.hxx>
+#include <cxx/hybrid/serializer-source.hxx>
+#include <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/serializer-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#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 <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> 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 <type>" << endl
+ << " Add custom data to the C++ class generated for\n"
+ << " XML Schema type <type>."
+ << endl;
+
+ e << "--custom-parser <map>" << endl
+ << " Use a custom parser implementation instead of the\n"
+ << " generated version. The <map> argument is in the\n"
+ << " form type[=base[/include]], where <type> is an XML\n"
+ << " Schema type name, optional <base> is a C++ name\n"
+ << " that should be given to the generated version,\n"
+ << " and optional <include> is the header file that\n"
+ << " defines the custom implementation."
+ << endl;
+
+ e << "--custom-serializer <map>" << endl
+ << " Use a custom serializer implementation instead of\n"
+ << " the generated version. The <map> argument is in\n"
+ << " the form type[=base[/include]], where <type> is\n"
+ << " an XML Schema type name, optional <base> is a C++\n"
+ << " name that should be given to the generated\n"
+ << " version, and optional <include> 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 <element>" << endl
+ << " Treat only <element> as a document root. Repeat\n"
+ << " this option to specify more than one root element."
+ << endl;
+
+ e << "--root-type <type>" << endl
+ << " Generate parser/serializer aggregate for <type>.\n"
+ << " Repeat this option to specify more than one type."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--pskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeletons."
+ << endl;
+
+ e << "--sskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--pskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--sskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--pimpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementations."
+ << endl;
+
+ e << "--simpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementations."
+ << endl;
+
+ e << "--pimpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementation files."
+ << endl;
+
+ e << "--simpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementation files."
+ << endl;
+
+ e << "--paggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_paggs' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " aggregates."
+ << endl;
+
+ e << "--saggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_saggr' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " aggregates."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> 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 <name>" << endl
+ << " Add <name> 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 <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> 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 <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ // File suffix.
+ //
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header files."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline files."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source files."
+ << endl;
+
+ e << "--fwd-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-fwd.hxx'\n"
+ << " to construct the name of the forward declaration\n"
+ << " file."
+ << endl;
+
+ // File regex.
+ //
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-regex <regex>" << endl
+ << " Use <regex> to construct the name of the forward\n"
+ << " declaration file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-prologue <text>" << endl
+ << " Insert <text> at the beginning of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header files."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline files."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source files."
+ << endl;
+
+ e << "--fwd-epilogue <text>" << endl
+ << " Insert <text> at the end of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header files."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline files."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source files."
+ << endl;
+
+ e << "--fwd-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the forward declaration file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> 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 <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header files."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline files."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source files."
+ << endl;
+
+ e << "--fwd-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the forward declaration file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> 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 <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. 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<CLI::pskel_file_suffix> ().default_value ("-pskel");
+ spec.option<CLI::sskel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::pskel_type_suffix> ().default_value ("_pskel");
+ spec.option<CLI::sskel_type_suffix> ().default_value ("_sskel");
+
+ spec.option<CLI::pimpl_file_suffix> ().default_value ("-pimpl");
+ spec.option<CLI::simpl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::pimpl_type_suffix> ().default_value ("_pimpl");
+ spec.option<CLI::simpl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::paggr_type_suffix> ().default_value ("_paggr");
+ spec.option<CLI::saggr_type_suffix> ().default_value ("_saggr");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+ spec.option<CLI::fwd_suffix> ().default_value ("-fwd.hxx");
+
+ return spec;
+ }
+
+ namespace
+ {
+ NarrowString
+ find_value (Cult::Containers::Vector<NarrowString> const& v,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> 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<NarrowString>& dst,
+ Cult::Containers::Vector<NarrowString> const& src,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> 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<P::Options> r (new P::Options);
+
+ r->value<P::no_stl> () = h.value<H::no_stl> ();
+ r->value<P::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<P::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<P::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<P::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<P::reuse_style_none> () = false;
+ r->value<P::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<P::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_parser_val> ();
+ r->value<P::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
+ r->value<P::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
+ r->value<P::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<P::output_dir> () = h.value<H::output_dir> ();
+ r->value<P::skel_file_suffix> () = h.value<H::pskel_file_suffix> ();
+ r->value<P::skel_type_suffix> () = h.value<H::pskel_type_suffix> ();
+ r->value<P::impl_type_suffix> () = h.value<H::pimpl_type_suffix> ();
+ r->value<P::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<P::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<P::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<P::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<P::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<P::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<P::include_regex> () = h.value<H::include_regex> ();
+ r->value<P::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<P::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<P::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<P::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<P::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "pskel";
+
+ r->value<P::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<P::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<P::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<P::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<P::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<P::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<P::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<P::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<P::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<P::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<P::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<P::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<P::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<P::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<P::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<P::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<P::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<P::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<P::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<P::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<P::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ return r.release ();
+ }
+
+ Serializer::CLI::Options* Hybrid::Generator::
+ serializer_options (CLI::Options const& h)
+ {
+ namespace H = CLI;
+ namespace S = Serializer::CLI;
+
+ Evptr<S::Options> r (new S::Options);
+
+ r->value<S::no_stl> () = h.value<H::no_stl> ();
+ r->value<S::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<S::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<S::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<S::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<S::reuse_style_none> () = false;
+ r->value<S::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<S::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_serializer_val> ();
+ r->value<S::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
+ r->value<S::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
+ r->value<S::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<S::output_dir> () = h.value<H::output_dir> ();
+ r->value<S::skel_file_suffix> () = h.value<H::sskel_file_suffix> ();
+ r->value<S::skel_type_suffix> () = h.value<H::sskel_type_suffix> ();
+ r->value<S::impl_type_suffix> () = h.value<H::simpl_type_suffix> ();
+ r->value<S::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<S::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<S::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<S::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<S::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<S::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<S::include_regex> () = h.value<H::include_regex> ();
+ r->value<S::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<S::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<S::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<S::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<S::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "sskel";
+
+ r->value<S::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<S::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<S::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<S::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<S::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<S::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<S::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<S::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<S::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<S::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<S::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<S::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<S::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<S::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<S::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<S::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<S::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<S::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<S::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<S::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<S::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ 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 <typename S>
+ 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<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def,
+ Char const* primary_key,
+ Char const* def_key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> 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<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> 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<CLI::generate_xml_schema> ());
+
+ // 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<CLI::extern_xml_schema> ())
+ {
+ 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<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean forward (ops.value<CLI::generate_forward> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+ NarrowString fwd_suffix (ops.value <CLI::fwd_suffix> ());
+
+ NarrowString hxx_regex (find_value (ops.value <CLI::hxx_regex> (), ""));
+ NarrowString ixx_regex (find_value (ops.value <CLI::ixx_regex> (), ""));
+ NarrowString cxx_regex (find_value (ops.value <CLI::cxx_regex> (), ""));
+
+ 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 <CLI::fwd_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#"
+ : ops.value <CLI::fwd_regex> ());
+
+ 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<CLI::output_dir> ())
+ {
+ 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<CLI::proprietary_license> ()
+ ? 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<CLI::prologue_file> (), ""));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), ""));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::fwd_prologue> (),
+ ops.value<CLI::prologue> (),
+ 0,
+ "");
+ append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue);
+
+ fwd << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ fwd << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ fwd << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd);
+
+ // Generate.
+ //
+ generate_tree_forward (ctx, false);
+
+ fwd << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ fwd << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (fwd, ops.value<CLI::fwd_epilogue_file> (), epilogue);
+ append (fwd,
+ ops.value<CLI::fwd_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ 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<Indentation::SLOC, WideChar> 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<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), ""),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << 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 <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ 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<CLI::no_exceptions> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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 <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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 <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), ""),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::ixx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (ixx,
+ find_value (ops.value<CLI::ixx_prologue_file> (), ""),
+ prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+ // Generate.
+ //
+ generate_tree_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx,
+ find_value (ops.value<CLI::ixx_epilogue_file> (), ""),
+ epilogue);
+ append (ixx,
+ ops.value<CLI::ixx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ 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<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), ""),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ cxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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 <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), ""),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ 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<CLI::generate_parser> () ||
+ ops.value<CLI::generate_serializer> ())
+ {
+ 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<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> 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<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // 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<CLI::extern_xml_schema> ())
+ {
+ 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 <CLI::pskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::pimpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_obj_regex (
+ find_value (ops.value <CLI::hxx_regex> (), ""));
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pskel"));
+
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pimpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "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<CLI::output_dir> ())
+ {
+ 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<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "pimpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "pimpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_parser_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "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<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_parser_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "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<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> 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<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // 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<CLI::extern_xml_schema> ())
+ {
+ 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 <CLI::sskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::simpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "sskel"));
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "simpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "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<CLI::output_dir> ())
+ {
+ 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<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "simpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "simpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "simpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_serializer_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "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<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "simpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_serializer_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "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<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsde.hxx>
+#include <type-map/type-map.hxx>
+#include <cxx/hybrid/cli.hxx>
+
+#include <cxx/parser/cli.hxx>
+#include <cxx/serializer/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-aggregate-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ typedef Cult::Containers::Set<String> 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<String> ("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<TypeInstanceMap> ("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<String> ("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<TypeInstanceMap> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ 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<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ 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<String> ("paggr"));
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("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<String> ("paggr"));
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("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<String> ("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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+ Boolean hae (has_particle<Traversal::Any> (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<String> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/parser-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/map.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> 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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ impl_suffix_ (ops.value<CLI::pimpl_type_suffix> ()),
+ aggr_suffix_ (ops.value<CLI::paggr_type_suffix> ()),
+ options (ops),
+ schema (root),
+ schema_path (schema_path_),
+ aggregate (ops.value<CLI::generate_aggregate> ()),
+ 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<NarrowString> Vector;
+ Vector const& v (ops.value<CLI::custom_parser> ());
+
+ 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<Boolean> ("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<String> ("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<String, CustomParser>
+ CustomParserMap;
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const impl_suffix_;
+ String const aggr_suffix_;
+ CustomParserMap custom_parser_map_;
+
+ Cult::Containers::Map<String, NameSet*> 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<String, NameSet*>& 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<String> ("p:impl-base")
+ : lc.get<String> ("p:impl"));
+ if (!name)
+ return;
+
+ NameSet set;
+ set.insert (name);
+ set.insert (unclash (lc.get<String> ("p:name"), "item"));
+
+ lc.set ("pstate-member",
+ find_name (lc.get<String> ("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<String> ("p:impl-base")
+ : uc.get<String> ("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<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ 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<String> ("p:impl-base")
+ : cc.get<String> ("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<NameSet> ("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<String> ("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<NarrowString> Names;
+ Names const& names (options.value<CLI::root_type> ());
+
+ // 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<CLI::root_element_last> ())
+ process (*last_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean p (false);
+
+ if (last_ == 0 && options.value<CLI::root_element_first> ())
+ p = true;
+
+ last_ = &e;
+
+ if (!p &&
+ !options.value<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().empty ())
+ {
+ // By default process them all.
+ //
+ p = true;
+ }
+
+ if (!p && options.value<CLI::root_element_all> ())
+ p = true;
+
+ if (!p)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_element> ());
+
+ // 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<NameSet> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("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<Compositor> ())
+ {
+ 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<Compositor&> (p);
+ seq = element && c->max () != 1;
+ }
+
+ Complex& t (
+ dynamic_cast<Complex&> (
+ 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<Complex&> (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<Boolean> ("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<SemanticGraph::Compositor&> (
+ 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<SemanticGraph::Complex&> (
+ 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<Complex&> (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<Complex&> (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<SemanticGraph::AnyType> () &&
+ !b.is_a<SemanticGraph::AnySimpleType> ())
+ {
+ // 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-aggregate-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ typedef Cult::Containers::Set<String> 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<String> ("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<TypeInstanceMap> ("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<String> ("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<TypeInstanceMap> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ 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<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ 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<String> ("saggr"));
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("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<String> ("saggr"));
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("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<String> ("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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (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<String> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/serializer-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> 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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ impl_suffix_ (ops.value<CLI::simpl_type_suffix> ()),
+ aggr_suffix_ (ops.value<CLI::saggr_type_suffix> ()),
+ options (ops),
+ schema (root),
+ schema_path (schema_path_),
+ aggregate (ops.value<CLI::generate_aggregate> ()),
+ 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<NarrowString> Vector;
+ Vector const& v (ops.value<CLI::custom_serializer> ());
+
+ 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<String> ("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<String, CustomSerializer>
+ CustomSerializerMap;
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const impl_suffix_;
+ String const aggr_suffix_;
+ CustomSerializerMap custom_serializer_map_;
+
+ Cult::Containers::Map<String, NameSet*> 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<String, NameSet*>& 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<String> ("s:impl-base")
+ : lc.get<String> ("s:impl"));
+ if (!name)
+ return;
+
+ String const& skel (lc.get<String> ("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<String> ("s:impl-base")
+ : uc.get<String> ("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<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ 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<String> ("s:impl-base")
+ : cc.get<String> ("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<NameSet> ("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<String> ("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<NarrowString> Names;
+ Names const& names (options.value<CLI::root_type> ());
+
+ // 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<CLI::root_element_last> ())
+ process (*last_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean p (false);
+
+ if (last_ == 0 && options.value<CLI::root_element_first> ())
+ p = true;
+
+ last_ = &e;
+
+ if (!p &&
+ !options.value<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().empty ())
+ {
+ // By default process them all.
+ //
+ p = true;
+ }
+
+ if (!p && options.value<CLI::root_element_all> ())
+ p = true;
+
+ if (!p)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_element> ());
+
+ // 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<NameSet> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("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<Compositor&> (p);
+ seq = element && c->max () != 1;
+ }
+
+ Complex& t (
+ dynamic_cast<Complex&> (
+ 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<Complex&> (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<SemanticGraph::Complex&> (
+ 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<SemanticGraph::Complex&> (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<SemanticGraph::Complex&> (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<SemanticGraph::AnyType> () &&
+ !b.is_a<SemanticGraph::AnySimpleType> ())
+ {
+
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<CLI::no_long_long> ())
+ {
+ 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<CLI::extern_xml_schema> ());
+
+ // 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 <string>" << endl;
+ else
+ ctx.os << "#include <xsde/cxx/strdupx.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/hybrid/xml-schema.hxx>" << 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("value"));
+ String const& member (uc.get<String> ("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<CLI::no_long_long> ()
+ ? "long"
+ : "long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ align_type (options.value<CLI::no_long_long> ()
+ ? "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 <xsde/cxx/hybrid/sequence.hxx>" << endl
+ << endl;
+
+ Boolean inline_ (ctx.options.value<CLI::generate_inline> ());
+
+ // 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<String> ("value"));
+ String const& member (uc.get<String> ("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<SemanticGraph::Choice&> (
+ 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<SemanticGraph::Choice&> (
+ 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<CLI::generate_inline> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/tree-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/map.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> 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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ 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<NarrowString> CustomData;
+ CustomData const& cd (ops.value<CLI::custom_data> ());
+
+ 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<CustomDataMap>& p ((*map)[entry]);
+
+ if (p == 0)
+ p = Shptr<CustomDataMap> (new CustomDataMap);
+
+ b = e;
+
+ if (b == String::npos)
+ {
+ // Last name. Add an empty string to indicate this.
+ //
+ (*p)[L""] = Shptr<CustomDataMap> (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<Boolean> ("fixed");
+ }
+
+ Boolean
+ fixed_length (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<Boolean> ("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<Boolean> ("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<String, Shptr<CustomDataMap> >
+ {
+ };
+
+ private:
+ SemanticGraph::Path const schema_path_;
+
+ CustomDataMap custom_data_map_;
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+
+ CustomDataMap& custom_data_map;
+ Cult::Containers::Map<String, NameSet*>& 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<String> ("name"));
+
+ lc.set (member_set_key, NameSet ());
+ NameSet& set (lc.get<NameSet> (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<NameSet> (member_set_key));
+ String const& base (lc.get<String> ("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<String> ("name"));
+
+ uc.set (member_set_key, NameSet ());
+ NameSet& set (uc.get<NameSet> (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<NameSet> (member_set_key));
+ uc.set ("value-member", find_name ("value_", set));
+
+ // Custom data.
+ //
+ if (uc.count ("cd-name"))
+ {
+ String const& base (uc.get<String> ("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<String> ("name") + L"_present", set_));
+ }
+ else
+ {
+ String const& base (ac.get<String> ("name"));
+
+ if (a.optional ())
+ {
+ if (fixed_length (a.type ()))
+ ac.set ("present-member",
+ find_name (ac.get<String> ("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<String> ("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<String> ("name") + L"_present", set_));
+ }
+ }
+ else
+ {
+ String const& base (ec.get<String> ("name"));
+
+ if (e.max () == 1 && e.min () == 0)
+ {
+ if (fixed_length (e.type ()))
+ ec.set ("present-member",
+ find_name (ec.get<String> ("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<String> ("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<NameSet> (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<NameSet> (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<String> ("cd-name"));
+ ac.set ("cd-member", find_name (base + L"_", name_set));
+ }
+ }
+
+ if (fixed_length (a))
+ ac.set ("present-member",
+ find_name (ac.get<String> ("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<String> ("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<String> ("name"));
+ c.context ().set ("tag", find_name (base, L"_tag", set_));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ String const& base (s.context ().get<String> ("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<String> ("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<NameSet> (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<NameSet> (member_set_key));
+ traverse_nested (c, name_set, 0);
+
+ // Tags.
+ //
+ cc.set ("arm-member",
+ find_name (cc.get<String> ("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<String> ("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<String> ("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<String> ("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<String> ("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<NameSet> (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<NameSet> (member_set_key));
+ traverse_nested (s, name_set, 0);
+
+ // Custom data.
+ //
+ if (sc.count ("cd-name"))
+ {
+ String const& base (sc.get<String> ("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<String> ("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<String> ("name"));
+
+ cc.set (member_set_key, NameSet ());
+ NameSet& member_set (cc.get<NameSet> (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::Complex> ())
+ {
+ SemanticGraph::Context& bc (b.context ());
+
+ if (!bc.count (member_set_key))
+ dispatch (b);
+
+ NameSet const& bset (bc.get<NameSet> (member_set_key));
+ member_set.insert (bset.begin (), bset.end ());
+ }
+
+ // Inheritance by restriction from anyType is a special case.
+ //
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !b.is_a<SemanticGraph::AnyType> ();
+ }
+
+ 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<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ NameSet& member_set (cc.get<NameSet> (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<String> ("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<NameSet> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+#include <cxx/hybrid/tree-size-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef Cult::Containers::Set<String> 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<Boolean> ("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<CLI::no_stl> ());
+
+ // 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<NarrowString> CustomData;
+ CustomData const& cd (ops.value<CLI::custom_data> ());
+
+ 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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 <new>" << 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/tree-type-map.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <iostream>
+
+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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ())
+ {
+ }
+
+ 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<Boolean> ("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<SemanticGraph::Schema*> 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<CLI::generate_parser> () ? &parser_map : 0),
+ (ops.value<CLI::generate_serializer> () ? &serializer_map : 0));
+
+ schema >> schema_names >> ns;
+
+ Traversal::Names used_schema_names;
+ Namespace used_ns (
+ ctx, 0,
+ (ops.value<CLI::generate_parser> () ? &parser_map : 0),
+ (ops.value<CLI::generate_serializer> () ? &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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+#include <iostream>
+
+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<SemanticGraph::Namespace> ())
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ assert (n.named ());
+
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ 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<SemanticGraph::Type&> (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<Schema&> (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<CLI::generate_polymorphic> () &&
+ !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<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ Containers::Set<String> 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<SemanticGraph::Fundamental::IdRef> ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRefs> ())
+ {
+ 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<CLI::show_anonymous> ())
+ 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<CLI::show_anonymous> ())
+ {
+ 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<CLI::show_anonymous> ())
+ {
+ 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<String> 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<SemanticGraph::Complex&> (
+ 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<CLI::generate_parser> ());
+ Boolean ser (options.value<CLI::generate_serializer> ());
+ Boolean agg (options.value<CLI::generate_aggregate> ());
+
+ 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<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().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<CLI::suppress_validation> () ||
+ options.value<CLI::suppress_parser_val> ()))
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+#include <xsde.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Attribute> (c));
+ Boolean has_any (has<Traversal::AnyAttribute> (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<SemanticGraph::Restricts> ())
+ {
+ // 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<SemanticGraph::Restricts> ())
+ {
+ // 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<SemanticGraph::Restricts> ())
+ {
+ // 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<SemanticGraph::Restricts> ())
+ {
+ // 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/characters-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+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<NarrowString>,
+ 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<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ 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<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue, Cult::Containers::Vector<NarrowString>,
+ prologue, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ 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<Options> {};
+ }
+ }
+}
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/driver-source.hxx>
+#include <cxx/parser/print-impl-common.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ typedef Cult::Containers::Set<String> 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<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ return false;
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Cult::Containers::Set<SemanticGraph::Type*> 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ 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<CLI::no_iostream> ())
+ os << "#include <stdio.h>" << endl;
+ else
+ os << "#include <iostream>" << endl;
+
+ os << endl
+ << "int" << endl
+ << "main (int argc, char* argv[])"
+ << "{"
+ << "const char* input;"
+ << endl
+ << "if (argc < 2)"
+ << "{"
+ << "input = \"STDIN\";";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ {
+ 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<CLI::no_iostream> () ||
+ ctx.options.value<CLI::no_exceptions> ())
+ os << "int r = 0;"
+ << endl;
+
+ if (!ctx.options.value<CLI::no_exceptions> ())
+ 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<CLI::no_iostream> ())
+ os << "bool io_error = false;";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ 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<CLI::no_exceptions> ())
+ os << "if (e = doc_p._error ())" << endl
+ << "break;"
+ << endl;
+
+ os << root_p << ".pre ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << endl
+ << "if (e = " << root_p << "._error ())" << endl
+ << "break;";
+
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ 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<CLI::no_exceptions> ())
+ 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<CLI::no_exceptions> ())
+ 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<CLI::no_exceptions> ())
+ os << "e = " << root_p << "._error ();";
+ }
+ else
+ {
+ os << Context::arg_type (root_type) << " v = " <<
+ root_p << "." << post << " ());"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = " << root_p << "._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (ctx.options.value<CLI::generate_print_impl> ())
+ {
+ 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<CLI::no_exceptions> ())
+ os << "}"
+ << "while (false);"
+ << endl;
+ else if (ctx.options.value<CLI::no_iostream> ())
+ os << "}" // if (!io_error)
+ << "else"
+ << "{"
+ << "fprintf (stderr, \"%s: read failure\\n\", input);"
+ << "r = 1;"
+ << "}";
+
+ // Error handling.
+ //
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "// Handle errors." << endl
+ << "//" << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ os << "if (io_error)"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::suppress_validation> ())
+ {
+ os << "case " << xs << "::parser_error::schema:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ {
+ os << "catch (const std::ios_base::failure&)"
+ << "{"
+ << "std::cerr << input << \": unable to open or " <<
+ "read failure\" << std::endl;"
+ << "return 1;"
+ << "}";
+ }
+ }
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "if (argc > 1)" << endl
+ << "fclose (f);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> () ||
+ ctx.options.value<CLI::no_exceptions> ())
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/element-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/vector.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ typedef Cult::Containers::Vector<SemanticGraph::Particle*> 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<Choice*> (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<Particles> ("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<Particles> ("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<Element*> (&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<UnsignedLong> ("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<UnsignedLong> ("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<UnsignedLong> ("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<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("p:comp-number"));
+ UnsignedLong state (cc.get<UnsignedLong> ("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<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("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<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("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<UnsignedLong> ("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<Choice*> (&c))
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (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<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("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<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("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<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("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<UnsignedLong> ("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<Choice*> (&c);
+
+ if (pc)
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (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<Element&> (ci->particle ()));
+ String ns (e.qualified () ? e.namespace_ ().name () : String ());
+ UnsignedLong state (e.context ().get<UnsignedLong> ("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<UnsignedLong> ("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<Compositor> () && !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<UnsignedLong> ("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<Compositor> () && !p.context().count ("p:comp-number"))
+ {
+ // Empty compositor.
+ //
+ ++ci;
+ continue;
+ }
+
+ // Find the next state.
+ //
+ do
+ ++ci;
+ while (ci != ce &&
+ ci->particle ().is_a<Compositor> () &&
+ !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<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("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<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("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<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("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<UnsignedLong> ("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<Choice*> (&c));
+
+ if (pc)
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (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<UnsignedLong> ("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<UnsignedLong> ("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<Choice*> (&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<Traversal::Element> (c) &&
+ !has_particle<Traversal::Any> (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<SemanticGraph::Restricts> ());
+
+ 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<SemanticGraph::All> ())
+ {
+ 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<SemanticGraph::All> ())
+ {
+ 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<SemanticGraph::All> ())
+ {
+ // 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<SemanticGraph::All> ())
+ 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<SemanticGraph::All> ())
+ {
+ // 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 <assert.h>" << 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/elements.hxx>
+
+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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ 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<CLI::suppress_validation> ()),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
+ poly_runtime (poly_code || ops.value<CLI::runtime_polymorphic> ()),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin && !ops.value<CLI::reuse_style_none> ()),
+ 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<String> ("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<Complex*> (&base))
+ return content (*cb);
+
+ if (base.is_a<AnyType> ())
+ 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<String> ("p:ret-type");
+ }
+
+ String const& Context::
+ arg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:arg-type");
+ }
+
+ String const& Context::
+ post_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:post");
+ }
+
+ String const& Context::
+ epresent (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:present");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::Sequence& s)
+ {
+ return s.context ().get<String> ("p:next");
+ }
+
+ String const& Context::
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:tag");
+ }
+
+ String const& Context::
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm");
+ }
+
+ String const& Context::
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm-tag");
+ }
+
+ String const& Context::
+ eparser (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:parser");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member");
+ }
+
+ String const& Context::
+ emember_cache (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member-cache");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member-map");
+ }
+
+ String const& Context::
+ etiein (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:tiein");
+ }
+
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:impl");
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << t.context ().get<String> (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 <boris@codesynthesis.com>
+// 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 <sstream>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ struct Content
+ {
+ enum Value
+ {
+ simple,
+ complex,
+ mixed
+ };
+ };
+
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> 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<SemanticGraph::Restricts> ())
+ {
+ // Restriction of anyType is a special case.
+ //
+ return !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+
+ 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options_.value<CLI::root_element> ())
+ {
+ 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <type-map/lexer.hxx>
+#include <type-map/parser.hxx>
+
+#include <cxx/parser/elements.hxx>
+#include <cxx/parser/generator.hxx>
+
+#include <cxx/parser/validator.hxx>
+#include <cxx/parser/name-processor.hxx>
+#include <cxx/parser/state-processor.hxx>
+#include <cxx/parser/type-processor.hxx>
+
+#include <cxx/parser/parser-forward.hxx>
+#include <cxx/parser/parser-header.hxx>
+#include <cxx/parser/parser-inline.hxx>
+#include <cxx/parser/parser-source.hxx>
+
+#include <cxx/parser/impl-header.hxx>
+#include <cxx/parser/impl-source.hxx>
+#include <cxx/parser/driver-source.hxx>
+
+#include <cxx/parser/element-validation-source.hxx>
+#include <cxx/parser/attribute-validation-source.hxx>
+#include <cxx/parser/characters-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#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 <mapfile>" << endl
+ << " Read XML Schema to C++ type mapping information\n"
+ << " from <mapfile>. 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 <element>" << endl
+ << " Indicate that <element> 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 <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> and xsd:included in the schema\n"
+ << " being compiled."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--skel-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_pskel' to\n"
+ << " construct the names of generated parser skeletons."
+ << endl;
+
+ e << "--skel-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-pskel' to\n"
+ << " construct the names of generated parser skeleton\n"
+ << " files."
+ << endl;
+
+ e << "--impl-type-suffix <suffix>" << endl
+ << " Use <suffix> 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 <suffix>" << endl
+ << " Use <suffix> instead of the default '-pimpl' to\n"
+ << " construct the names of generated sample parser\n"
+ << " implementation files."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> 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 <name>" << endl
+ << " Add <name> 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 <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> 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 <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header file."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline file."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source file."
+ << endl;
+
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the header\n"
+ << " file."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the inline\n"
+ << " file."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the source\n"
+ << " file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header file."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline file."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header file."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline file."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header file."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline file."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> 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 <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header file."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline file."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> 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 <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. 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<CLI::skel_file_suffix> ().default_value ("-pskel");
+ spec.option<CLI::skel_type_suffix> ().default_value ("_pskel");
+ spec.option<CLI::impl_file_suffix> ().default_value ("-pimpl");
+ spec.option<CLI::impl_type_suffix> ().default_value ("_pimpl");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+
+ return spec;
+ }
+
+
+ namespace
+ {
+ template <typename S>
+ 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<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def)
+ {
+ Cult::Containers::Vector<NarrowString> const& v (
+ primary.empty () ? def : primary);
+
+ for (Containers::Vector<NarrowString>::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<Char> Regex;
+
+ try
+ {
+ Boolean generate_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // 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<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ generate_xml_schema = false;
+ }
+ }
+
+ Boolean impl (!generate_xml_schema &&
+ (ops.value<CLI::generate_noop_impl> () ||
+ ops.value<CLI::generate_print_impl> ()));
+
+ Boolean driver (gen_driver && !generate_xml_schema &&
+ ops.value<CLI::generate_test_driver> ());
+
+
+ // 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<CLI::suppress_validation> ());
+
+ // Compute state machine info.
+ //
+ if (validation)
+ {
+ StateProcessor proc;
+ proc.process (schema, file_path);
+ }
+
+ // Read-in type maps.
+ //
+ {
+ using namespace TypeMap;
+ typedef Containers::Vector<NarrowString> Files;
+
+ Files const& files (ops.value<CLI::type_map> ());
+
+ 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<CLI::no_stl> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::skel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::impl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ Regex hxx_expr (
+ ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (
+ ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (
+ ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#"
+ : ops.value <CLI::cxx_regex> ());
+
+ 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<CLI::output_dir> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::proprietary_license> ()
+ ? 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<CLI::prologue_file> ());
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (ops.value<CLI::epilogue_file> ());
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::hxx_prologue> (), ops.value<CLI::prologue> ());
+ append (hxx, ops.value<CLI::hxx_prologue_file> (), prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << 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 <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ 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<CLI::no_iostream> ())
+ {
+ 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<CLI::no_exceptions> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<CLI::suppress_validation> ())
+ {
+ 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<CLI::generate_polymorphic> () ||
+ ops.value<CLI::runtime_polymorphic> ())
+ {
+ 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<CLI::reuse_style_mixin> ())
+ {
+ 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<CLI::reuse_style_none> ())
+ {
+ 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 <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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 <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx, ops.value<CLI::hxx_epilogue_file> (), epilogue);
+ append (
+ hxx, ops.value<CLI::hxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ ixx, ops.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ());
+ append (ixx, ops.value<CLI::ixx_prologue_file> (), prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+
+ // Generate.
+ //
+ generate_parser_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue);
+ append (
+ ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ cxx, ops.value<CLI::cxx_prologue> (), ops.value<CLI::prologue> ());
+ append (cxx, ops.value<CLI::cxx_prologue_file> (), prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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<CLI::cxx_epilogue_file> (), epilogue);
+ append (
+ cxx, ops.value<CLI::cxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::CXX, WideChar> 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<Indentation::CXX, WideChar> 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<Indentation::CXX, WideChar> 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<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsde.hxx>
+#include <type-map/type-map.hxx>
+#include <cxx/parser/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/impl-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/impl-source.hxx>
+#include <cxx/parser/print-impl-common.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, e.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ 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<CLI::generate_print_impl> ())
+ {
+ 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<CLI::generate_print_impl> ())
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<Complex&> (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<CLI::generate_print_impl> ())
+ {
+ 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<Complex&> (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<CLI::generate_print_impl> ())
+ {
+ 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<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, c.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ 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<CLI::generate_print_impl> ())
+ {
+ if (ctx.options.value<CLI::no_iostream> ())
+ ctx.os << "#include <stdio.h>" << endl
+ << endl;
+ else
+ ctx.os << "#include <iostream>" << 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/parser/name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> 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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ skel_suffix_ (ops.value<CLI::skel_type_suffix> ()),
+ impl_suffix_ (ops.value<CLI::impl_type_suffix> ()),
+ schema (root),
+ schema_path (schema_path_),
+ impl (ops.value<CLI::generate_noop_impl> () ||
+ ops.value<CLI::generate_print_impl> () ||
+ ops.value<CLI::generate_test_driver> ()),
+ tiein (!ops.value<CLI::reuse_style_mixin> () &&
+ !ops.value<CLI::reuse_style_none> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ 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<String, NameSet*> 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<String, NameSet*>& 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<Element*> ("xsd-frontend-restriction-correspondence"));
+
+ ec.set ("p:name", prot->context ().get<String> ("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<Attribute*> ("xsd-frontend-restriction-correspondence"));
+
+ ac.set ("p:name", prot->context ().get<String> ("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<String> ("p:name"));
+ ec.set ("p:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("p:tag", prot->context ().get<String> ("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<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("p:tag", prot->context ().get<String> ("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<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ cc.set ("p:tag", prot->context ().get<String> ("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<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ sc.set ("p:tag", prot->context ().get<String> ("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<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ cc.set ("p:arm-tag", bc.get<String> ("p:arm-tag"));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("p:arm", bc.get<String> ("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<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ sc.set ("p:next", bc.get<String> ("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<String> ("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<String> ("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<SemanticGraph::Element*> (
+ "xsd-frontend-restriction-correspondence")->context ());
+
+ ec.set ("p:parser", bc.get<String> ("p:parser"));
+ ec.set ("p:member", bc.get<String> ("p:member"));
+
+ if (poly)
+ {
+ ec.set ("p:member-cache", bc.get<String> ("p:member-cache"));
+ ec.set ("p:member-map", bc.get<String> ("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<String> ("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<SemanticGraph::Attribute*> (
+ "xsd-frontend-restriction-correspondence")->context ());
+
+ ac.set ("p:parser", bc.get<String> ("p:parser"));
+ ac.set ("p:member", bc.get<String> ("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<String> ("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<NameSet> ("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<SemanticGraph::Complex> ())
+ {
+ if (!base.context ().count (
+ "cxx-parser-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_set (
+ base.context ().get<NameSet> (
+ "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<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+ }
+
+ // 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<Complex*> (&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<String> ("p:post"));
+ else
+ set.insert (find_post_name (*b));
+
+ Complex* cb (dynamic_cast<Complex*> (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<NameSet> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/parser-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/parser-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<UnsignedLong> ("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<UnsignedLong> ("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<UnsignedLong> ("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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (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<UnsignedLong> ("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<CLI::no_stl> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<String> ("p:real-name"));
+ String const& name (c.get<String> ("p:name"));
+
+ os << "typedef " << real_name << " " << name << ";";
+
+ String const& real_impl (c.get<String> ("p:real-impl"));
+ String const& impl (c.get<String> ("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<CLI::extern_xml_schema> ();
+
+ 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<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("p:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsde/config.h>" << endl
+ << "#include <xsde/cxx/ro-string.hxx>" << endl
+ << endl;
+
+ // Data types.
+ //
+ ctx.os << "#include <xsde/cxx/parser/xml-schema.hxx>" << endl
+ << endl;
+
+ // Error handling.
+ //
+ if (ctx.exceptions)
+ ctx.os << "#include <xsde/cxx/parser/exceptions.hxx>" << endl
+ << endl;
+ else
+ {
+ ctx.os << "#include <xsde/cxx/sys-error.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/schema-error.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/parser/error.hxx>" << endl
+ << "#include <xsde/cxx/parser/expat/xml-error.hxx>" << endl
+ << endl;
+ }
+
+ // Polymorphism support.
+ //
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <xsde/cxx/parser/map.hxx>" << endl
+ << "#include <xsde/cxx/parser/substitution-map-load.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/inheritance-map-load.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Parsers.
+ //
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/parser.hxx>" << endl
+ << "#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>" << endl
+ << endl;
+ else
+ ctx.os << "#include <xsde/cxx/parser/non-validating/parser.hxx>" << endl
+ << "#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx>" << endl
+ << endl;
+
+ // Document.
+ //
+ ctx.os << "#include <xsde/cxx/parser/expat/document.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("p:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/parser-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<UnsignedLong> ("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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (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))
+ {
+ // <name>_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<CLI::generate_inline> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/parser-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<SemanticGraph::Element*> (&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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Scope&> (
+ 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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (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<SemanticGraph::All> () &&
+ 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<SemanticGraph::Element*> (&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<SemanticGraph::Restricts> ();
+
+ // _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 <assert.h>" << endl
+ << endl;
+
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <string.h>" << endl
+ << "#include <xsde/cxx/parser/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/inheritance-map.hxx>" << 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<CLI::generate_inline> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ "static_cast<short> (" << arg_ << ") << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ if (default_type (t, "unsigned char"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ "static_cast<unsigned short> (" << arg_ << ") << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ if (default_type (t, "short"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_long_long> ())
+ {
+ if (default_type (t, "long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_long_long> ())
+ {
+ if (default_type (t, "unsigned long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_stl> ())
+ {
+ if (default_type (t, xs_ns_name () + L"::qname*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_stl> ())
+ {
+ if (default_type (t, "char*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ {
+ if (options.value<CLI::no_stl> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_stl> () &&
+ 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<CLI::no_stl> () && 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/state-processor.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <iostream>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ typedef Cult::Containers::Vector<SemanticGraph::Particle*> 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<SemanticGraph::Element*> (*i))
+ {
+ wcerr << e->name () << endl;
+ }
+ else
+ {
+ wcerr << "<any>" << 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<SemanticGraph::Element> () ||
+ p.is_a<SemanticGraph::Any> ())
+ {
+ 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<UnsignedLong> ("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<SemanticGraph::Element> () ||
+ p.is_a<SemanticGraph::Any> ())
+ {
+ 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<UnsignedLong> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+#include <xsd-frontend/semantic-graph.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/containers/set.hxx>
+
+#include <cxx/parser/elements.hxx>
+#include <cxx/parser/type-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<SemanticGraph::Schema*> ("p:root-schema"));
+
+ if (&schema_ == s)
+ return;
+
+ set = false;
+ }
+
+ SemanticGraph::Namespace& ns (
+ dynamic_cast<SemanticGraph::Namespace&> (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<String> Includes;
+
+ SemanticGraph::Context& sc (schema_.context ());
+
+ if (!sc.count ("p:includes"))
+ sc.set ("p:includes", Includes ());
+
+ Includes& is (sc.get<Includes> ("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<CLI::reuse_style_mixin> () &&
+ !options.value<CLI::reuse_style_none> ());
+
+ 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<CLI::extern_xml_schema> ());
+
+ // 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/parser/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+#include <iostream>
+
+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<SemanticGraph::Namespace> ())
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ assert (n.named ());
+
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ 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<SemanticGraph::Complex&> (
+ 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<SemanticGraph::Type&> (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<Schema&> (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<CLI::generate_polymorphic> () &&
+ !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<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ Containers::Set<String> 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<SemanticGraph::Fundamental::IdRef> ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRefs> ())
+ {
+ 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<CLI::show_anonymous> ())
+ 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<CLI::show_anonymous> ())
+ {
+ 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<CLI::show_anonymous> ())
+ {
+ 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<String> 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (options.value<CLI::root_element_last> ())
+ {
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ 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<CLI::generate_noop_impl> () &&
+ options.value<CLI::generate_print_impl> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--generate-noop-impl and --generate-print-impl"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ {
+ Boolean ref (options.value<CLI::root_element_first> ());
+ Boolean rel (options.value<CLI::root_element_last> ());
+ Boolean re (options.value<CLI::root_element> ());
+
+ 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<CLI::reuse_style_mixin> () &&
+ options.value<CLI::reuse_style_none> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--reuse-style-mixin and --reuse-style-none"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_none> () &&
+ (options.value<CLI::generate_noop_impl> () ||
+ options.value<CLI::generate_print_impl> ()) &&
+ !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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+#include <xsde.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Attribute> (c) &&
+ !has<Traversal::AnyAttribute> (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<SemanticGraph::Restricts> ());
+
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+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<NarrowString>,
+ 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<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ 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<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue, Cult::Containers::Vector<NarrowString>,
+ prologue, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ 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<Options> {};
+ }
+ }
+}
+
+#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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/driver-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ typedef Cult::Containers::Set<String> 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<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ return false;
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Cult::Containers::Set<SemanticGraph::Type*> 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ 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<CLI::no_iostream> ())
+ os << "#include <stdio.h>" << endl
+ << endl;
+ else
+ os << "#include <iostream>" << endl
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ 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<CLI::no_exceptions> ())
+ 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<CLI::no_iostream> ())
+ os << "writer w;";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ 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<CLI::no_exceptions> ())
+ 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<CLI::no_exceptions> ())
+ os << "if (e = " << root_s << "._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "doc_s.serialize (w);"
+ << endl;
+ else
+ os << "doc_s.serialize (std::cout);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_s._error ())" << endl
+ << "break;"
+ << endl;
+
+ os << root_s << ".post ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << endl
+ << "e = " << root_s << "._error ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "}"
+ << "while (false);"
+ << endl;
+
+ // Error handling.
+ //
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "// Handle errors." << endl
+ << "//" << endl
+ << "if (e)"
+ << "{"
+ << "switch (e.type ())"
+ << "{"
+ << "case " << xs << "::serializer_error::sys:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.xml_text ());";
+ else
+ os << "std::cerr << e.xml_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+
+ if (!ctx.options.value<CLI::suppress_validation> ())
+ {
+ os << "case " << xs << "::serializer_error::schema:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ 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<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"error: %s\\n\", e.text ());";
+ else
+ os << "std::cerr << \"error: \" << e.text () << std::endl;";
+
+ os << "return 1;"
+ << "}";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/element-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Element> (c) &&
+ !has_particle<Traversal::Any> (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<SemanticGraph::Restricts> ());
+
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/elements.hxx>
+
+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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ 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<CLI::suppress_validation> ()),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ stl (!ops.value<CLI::no_stl> ()),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
+ poly_runtime (poly_code || ops.value<CLI::runtime_polymorphic> ()),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin && !ops.value<CLI::reuse_style_none> ()),
+ 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<String> ("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<Complex*> (&base))
+ return content (*cb);
+
+ if (base.is_a<AnyType> ())
+ 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<String> ("s:ret-type");
+ }
+
+ String const& Context::
+ arg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:arg-type");
+ }
+
+ //
+ //
+ String const& Context::
+ epresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ epresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:tag");
+ }
+
+ String const& Context::
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm");
+ }
+
+ String const& Context::
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm-tag");
+ }
+
+ //
+ //
+ String const& Context::
+ eserializer (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:serializer");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member-map");
+ }
+
+ String const& Context::
+ etiein (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:tiein");
+ }
+
+ //
+ //
+ String const& Context::
+ eserialize (SemanticGraph::Any& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ String const& Context::
+ eserialize (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ //
+ //
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:impl");
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << t.context ().get<String> (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 <boris@codesynthesis.com>
+// 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 <sstream>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ struct Content
+ {
+ enum Value
+ {
+ simple,
+ complex,
+ mixed
+ };
+ };
+
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> 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<SemanticGraph::Restricts> ())
+ {
+ // Restriction of anyType is a special case.
+ //
+ return !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+
+ 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options_.value<CLI::root_element> ())
+ {
+ 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <type-map/lexer.hxx>
+#include <type-map/parser.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/generator.hxx>
+
+#include <cxx/serializer/validator.hxx>
+#include <cxx/serializer/name-processor.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <cxx/serializer/serializer-forward.hxx>
+#include <cxx/serializer/serializer-header.hxx>
+#include <cxx/serializer/serializer-inline.hxx>
+#include <cxx/serializer/serializer-source.hxx>
+
+#include <cxx/serializer/impl-header.hxx>
+#include <cxx/serializer/impl-source.hxx>
+#include <cxx/serializer/driver-source.hxx>
+
+#include <cxx/serializer/element-validation-source.hxx>
+#include <cxx/serializer/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#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 <mapfile>" << endl
+ << " Read XML Schema to C++ type mapping information\n"
+ << " from <mapfile>. 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 <element>" << endl
+ << " Indicate that <element> 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 <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> and xsd:included in the schema\n"
+ << " being compiled."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--skel-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--skel-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--impl-type-suffix <suffix>" << endl
+ << " Use <suffix> 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 <suffix>" << endl
+ << " Use <suffix> instead of the default '-simpl' to\n"
+ << " construct the names of generated sample\n"
+ << " serializer implementation files."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> 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 <name>" << endl
+ << " Add <name> 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 <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> 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 <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header file."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline file."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source file."
+ << endl;
+
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the header\n"
+ << " file."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the inline\n"
+ << " file."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the source\n"
+ << " file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header file."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline file."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header file."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline file."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header file."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline file."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> 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 <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header file."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline file."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> 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 <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. 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<CLI::skel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::skel_type_suffix> ().default_value ("_sskel");
+ spec.option<CLI::impl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::impl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+
+ return spec;
+ }
+
+
+ namespace
+ {
+ template <typename S>
+ 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<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def)
+ {
+ Cult::Containers::Vector<NarrowString> const& v (
+ primary.empty () ? def : primary);
+
+ for (Containers::Vector<NarrowString>::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<Char> Regex;
+
+ try
+ {
+ Boolean generate_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // 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<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ generate_xml_schema = false;
+ }
+ }
+
+ Boolean impl (!generate_xml_schema &&
+ ops.value<CLI::generate_empty_impl> ());
+
+ Boolean driver (gen_driver && !generate_xml_schema &&
+ ops.value<CLI::generate_test_driver> ());
+
+ // 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<CLI::suppress_validation> ());
+
+ // Read-in type maps.
+ //
+ {
+ using namespace TypeMap;
+ typedef Containers::Vector<NarrowString> Files;
+
+ Files const& files (ops.value<CLI::type_map> ());
+
+ 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<CLI::no_stl> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::skel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::impl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+
+ Regex hxx_expr (
+ ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (
+ ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (
+ ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#"
+ : ops.value <CLI::cxx_regex> ());
+
+ 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<CLI::output_dir> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::force_overwrite> ())
+ {
+ 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<CLI::proprietary_license> ()
+ ? 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<CLI::prologue_file> ());
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (ops.value<CLI::epilogue_file> ());
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ 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<Indentation::SLOC, WideChar> 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<CLI::hxx_prologue> (), ops.value<CLI::prologue> ());
+ append (hxx, ops.value<CLI::hxx_prologue_file> (), prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << 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 <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ 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<CLI::no_iostream> ())
+ {
+ 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<CLI::no_exceptions> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<CLI::suppress_validation> ())
+ {
+ 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<CLI::generate_polymorphic> () ||
+ ops.value<CLI::runtime_polymorphic> ())
+ {
+ 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<CLI::reuse_style_mixin> ())
+ {
+ 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<CLI::reuse_style_none> ())
+ {
+ 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 <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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 <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx, ops.value<CLI::hxx_epilogue_file> (), epilogue);
+ append (
+ hxx, ops.value<CLI::hxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ ixx, ops.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ());
+ append (ixx, ops.value<CLI::ixx_prologue_file> (), prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+
+ // Generate.
+ //
+ generate_serializer_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue);
+ append (
+ ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ cxx, ops.value<CLI::cxx_prologue> (), ops.value<CLI::prologue> ());
+ append (cxx, ops.value<CLI::cxx_prologue_file> (), prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> 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<CLI::cxx_epilogue_file> (), epilogue);
+ append (
+ cxx, ops.value<CLI::cxx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ 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<Indentation::CXX, WideChar> 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<Indentation::CXX, WideChar> 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<Indentation::CXX, WideChar> 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<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsde.hxx>
+#include <type-map/type-map.hxx>
+#include <cxx/serializer/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/impl-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/impl-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<SemanticGraph::Complex&> (
+ 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<SemanticGraph::Complex&> (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<SemanticGraph::Complex&> (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<SemanticGraph::Complex&> (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<SemanticGraph::Complex&> (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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/serializer/name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> 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<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ skel_suffix_ (ops.value<CLI::skel_type_suffix> ()),
+ impl_suffix_ (ops.value<CLI::impl_type_suffix> ()),
+ schema (root),
+ schema_path (schema_path_),
+ impl (ops.value<CLI::generate_empty_impl> () ||
+ ops.value<CLI::generate_test_driver> ()),
+ tiein (!ops.value<CLI::reuse_style_mixin> () &&
+ !ops.value<CLI::reuse_style_none> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ 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<String, NameSet*> 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<String, NameSet*>& 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<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:name", prot->context ().get<String> ("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<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("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<Attribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("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<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("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<String> ("s:name"));
+ ec.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+ ac.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:tag", prot->context ().get<String> ("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<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ cc.set ("s:tag", prot->context ().get<String> ("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<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ sc.set ("s:tag", prot->context ().get<String> ("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<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ cc.set ("s:next", bc.get<String> ("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<String> ("s:present"));
+
+ // Tags.
+ //
+ cc.set ("s:arm-tag", bc.get<String> ("s:arm-tag"));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("s:arm", bc.get<String> ("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<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ sc.set ("s:next", bc.get<String> ("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<String> ("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<String> ("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<SemanticGraph::Element*> (
+ "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<String> ("s:present"));
+ else if (max != 1)
+ {
+ ec.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (e.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ec.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ec.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ec.set ("s:member", bc.get<String> ("s:member"));
+
+ if (poly)
+ ec.set ("s:member-map", bc.get<String> ("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<String> ("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<Any*> ("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<String> ("s:present"));
+ }
+ else if (max != 1)
+ {
+ ac.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (a.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ac.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ac.set ("s:serialize", bc.get<String> ("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<String> ("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<Attribute*> ("xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ if (a.optional ())
+ ac.set ("s:present", bc.get<String> ("s:present"));
+
+ ac.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ac.set ("s:member", bc.get<String> ("s:member"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ using SemanticGraph::AnyAttribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("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<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ ac.set ("s:next", bc.get<String> ("s:next"));
+ ac.set ("s:serialize", bc.get<String> ("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<String> ("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<NameSet> ("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<SemanticGraph::Complex> ())
+ {
+ if (!base.context ().count (
+ "cxx-serializer-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_set (
+ base.context ().get<NameSet> (
+ "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<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+ }
+
+ // 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<NameSet> ("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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (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<CLI::no_stl> ())
+ {
+ 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<CLI::no_long_long> ())
+ {
+ 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<String> ("s:real-name"));
+ String const& name (c.get<String> ("s:name"));
+
+ os << "typedef " << real_name << " " << name << ";";
+
+ String const& real_impl (c.get<String> ("s:real-impl"));
+ String const& impl (c.get<String> ("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<CLI::extern_xml_schema> ();
+
+ 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<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("s:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsde/config.h>" << endl
+ << endl;
+
+ // std::string or xsde::cxx::string is used in wildcard API.
+ //
+ if (ctx.stl)
+ {
+ ctx.os << "#include <string>" << endl
+ << endl;
+ }
+ else
+ {
+ ctx.os << "#include <xsde/cxx/string.hxx>" << endl
+ << endl;
+ }
+
+ // Data types.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/xml-schema.hxx>" << endl
+ << endl;
+
+ // Error handling.
+ //
+ if (ctx.exceptions)
+ ctx.os << "#include <xsde/cxx/serializer/exceptions.hxx>" << endl
+ << endl;
+ else
+ {
+ ctx.os << "#include <xsde/cxx/sys-error.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/schema-error.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/serializer/error.hxx>" << endl
+ << "#include <xsde/cxx/serializer/genx/xml-error.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Polymorphism support.
+ //
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <xsde/cxx/serializer/map.hxx>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map-load.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map-load.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Serializers.
+ //
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+ else
+ ctx.os << "#include <xsde/cxx/serializer/non-validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+
+ // Document.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/genx/document.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("s:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (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))
+ {
+ // <name>_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<CLI::generate_inline> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/serializer-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Scope&> (
+ 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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Element*> (&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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Scope&> (
+ 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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<SemanticGraph::Type&> (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<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (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<SemanticGraph::Element*> (&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<SemanticGraph::Restricts> ());
+
+ // _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 <assert.h>" << endl
+ << endl;
+
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <string.h>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map.hxx>" << 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<CLI::generate_inline> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/containers/set.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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<SemanticGraph::Schema*> ("s:root-schema"));
+
+ if (&schema_ == s)
+ return;
+
+ set = false;
+ }
+
+ SemanticGraph::Namespace& ns (
+ dynamic_cast<SemanticGraph::Namespace&> (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<WideChar> 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<String> Includes;
+
+ SemanticGraph::Context& sc (schema_.context ());
+
+ if (!sc.count ("s:includes"))
+ sc.set ("s:includes", Includes ());
+
+ Includes& is (sc.get<Includes> ("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<CLI::reuse_style_mixin> () &&
+ !options.value<CLI::reuse_style_none> ());
+
+ 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<CLI::extern_xml_schema> ());
+
+ // 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/serializer/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+#include <iostream>
+
+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<SemanticGraph::Namespace> ())
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ assert (n.named ());
+
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ 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<SemanticGraph::Type&> (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<Schema&> (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<CLI::generate_polymorphic> () &&
+ !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<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ Containers::Set<String> 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<SemanticGraph::Fundamental::IdRef> ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRefs> ())
+ {
+ 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<CLI::show_anonymous> ())
+ 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<CLI::show_anonymous> ())
+ {
+ 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<CLI::show_anonymous> ())
+ {
+ 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<String> 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<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (options.value<CLI::root_element_last> ())
+ {
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ 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<CLI::root_element_first> ());
+ Boolean rel (options.value<CLI::root_element_last> ());
+ Boolean re (options.value<CLI::root_element> ());
+
+ 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<CLI::reuse_style_mixin> () &&
+ options.value<CLI::reuse_style_none> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--reuse-style-mixin and --reuse-style-none"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_none> () &&
+ options.value<CLI::generate_empty_impl> () &&
+ !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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+#include <xsde.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+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 <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <processing/inheritance/processor.hxx>
+
+#include <elements.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <iostream>
+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<Dep> DepSet;
+ typedef Containers::Set<SemanticGraph::Type*> TypeSet;
+
+
+ String
+ xpath (SemanticGraph::Nameable& n)
+ {
+ if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0)
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ if (n.named ())
+ {
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0)
+ return n.name ();
+
+ return xpath (scope) + L"/" + n.name ();
+ }
+ else
+ {
+ return L"(anonymous type for " +
+ n.context ().get<String> ("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<Boolean> (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<String> ("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<Boolean> (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 <typename N, typename A>
+ struct NodeArgs
+ {
+ NodeArgs (N& node, A arg)
+ : node_ (node), arg_ (arg)
+ {
+ }
+
+ operator N& () const
+ {
+ return node_;
+ }
+
+ template <typename E>
+ Void
+ add_edge_left (E& e)
+ {
+ node_.add_edge_left (e, arg_);
+ }
+
+ template <typename E>
+ 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<Schema&> (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<SG::Type> () ? "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<Scope, Scope::NamesIterator> na (scope, i);
+ root_.new_edge<Names> (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<Sources> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <iostream>
+
+#include <type-map/lexer.hxx>
+
+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<char> 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"<end-of-stream>", 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 <boris@codesynthesis.com>
+// 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 <locale>
+#include <iosfwd>
+
+#include <cult/types.hxx>
+
+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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2007-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <iostream>
+
+#include <backend-elements/regex.hxx>
+
+#include <type-map/parser.hxx>
+
+using std::endl;
+
+namespace TypeMap
+{
+ typedef Lexer::Token Token;
+ typedef BackendElements::Regex::Format<WideChar> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <type-map/type-map.hxx>
+#include <type-map/lexer.hxx>
+
+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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <backend-elements/regex.hxx>
+
+namespace TypeMap
+{
+ using namespace Cult::Types;
+ typedef WideString String;
+ typedef BackendElements::Regex::Pattern<WideChar> 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<String> 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<Type> 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<Namespace> 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 <boris@codesynthesis.com>
+// 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 <cult/types.hxx>
+
+#include <backend-elements/indentation/buffer.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+namespace CLI
+{
+ using namespace Cult::Types;
+
+ template <typename C>
+ class OptionsUsage: public BackendElements::Indentation::Buffer<C>
+ {
+ typedef BackendElements::Indentation::Buffer<C> 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <iostream>
+#include <boost/filesystem/fstream.hpp>
+
+#include <cult/types.hxx>
+
+#include <cult/trace/log.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/exceptions.hxx>
+#include <cult/cli/file-arguments.hxx>
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+#include <cult/cli/options-parser.hxx>
+
+#include <xsd-frontend/parser.hxx>
+#include <xsd-frontend/transformations/anonymous.hxx>
+#include <xsd-frontend/transformations/restriction.hxx>
+#include <xsd-frontend/transformations/schema-per-type.hxx>
+#include <xsd-frontend/transformations/simplifier.hxx>
+
+#include <xsde.hxx>
+#include <usage.hxx>
+#include <type-map/type-map.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cxx/parser/generator.hxx>
+#include <cxx/serializer/generator.hxx>
+#include <cxx/hybrid/generator.hxx>
+
+#include <processing/inheritance/processor.hxx>
+
+#include "../libxsde/xsde/cxx/version.hxx"
+
+using namespace Cult::Types;
+
+typedef Cult::Containers::Vector<NarrowString> 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<HelpOptions> {};
+
+
+ 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<NarrowString>,
+ 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<CommonOptions> {};
+}
+
+//
+//
+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<NarrowString, NarrowString> Map;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+ typedef BackendElements::Regex::Format<Char> RegexFormat;
+ typedef Cult::Containers::Vector<Regex> RegexVector;
+
+ typedef Cult::Containers::Map<NarrowString, NarrowString> 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<WideChar> Regex;
+ typedef BackendElements::Regex::Format<WideChar> RegexFormat;
+ typedef Cult::Containers::Vector<Regex> 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<WideChar> Regex;
+ typedef BackendElements::Regex::Format<WideChar> RegexFormat;
+ typedef Cult::Containers::Vector<Regex> 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<CLI::version> () || 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<CLI::proprietary_license> () &&
+ 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<CLI::proprietary_license> ())
+ {
+ 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<CLI::help> () || 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 <warn>" << endl
+ << " Disable printing warning with id <warn>. 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 <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 <ol>=<nl>" << endl
+ << " Map the original schema location <ol> that is\n"
+ << " specified in the XML Schema include or import\n"
+ << " elements to new schema location <nl>. Repeat\n"
+ << " this option to map more than one schema location."
+ << endl;
+
+ e << "--location-regex <regex>" << endl
+ << " Add <regex> 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 <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 <file>" << endl
+ << " Write a list of generated C++ files to <file>."
+ << endl;
+
+ e << "--file-list-prologue <p>" << endl
+ << " Insert <p> at the beginning of the file list. All\n"
+ << " occurrences of the \\n character sequence in <p>\n"
+ << " are replaced with new lines."
+ << endl;
+
+ e << "--file-list-prologue <e>" << endl
+ << " Insert <e> at the end of the file list. All\n"
+ << " occurrences of the \\n character sequence in <e>\n"
+ << " are replaced with new lines."
+ << endl;
+
+ e << "--file-list-delim <d>" << endl
+ << " Delimit file names written to the file list with\n"
+ << " <d> instead of new lines. All occurrences of the\n"
+ << " \\n character sequence in <d> are replaced with\n"
+ << " new lines."
+ << endl;
+ }
+ else
+ {
+ e << "Usage: " << args[0] << " <cmd> ..." << endl
+ << "Commands:" << endl;
+
+ e << " help Print usage information and exit. Use\n"
+ << " 'help <cmd>' 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<CLI::file_list_delim> ().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<NarrowString> Warnings;
+ Warnings const& w (common_ops.value<CLI::disable_warning> ());
+
+ 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<CXX::Parser::CLI::Options> p_ops;
+ Evptr<CXX::Serializer::CLI::Options> s_ops;
+ Evptr<CXX::Hybrid::CLI::Options> 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<CXX::Parser::CLI::show_sloc> ();
+ }
+ 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<CXX::Serializer::CLI::show_sloc> ();
+ }
+ else if (cmd == "cxx-hybrid")
+ {
+ h_ops = new CXX::Hybrid::CLI::Options (
+ CLI::parse (CXX::Hybrid::Generator::options_spec (), args));
+
+ if (h_ops->value<CXX::Hybrid::CLI::generate_parser> ())
+ p_ops = CXX::Hybrid::Generator::parser_options (*h_ops);
+
+ if (h_ops->value<CXX::Hybrid::CLI::generate_serializer> ())
+ s_ops = CXX::Hybrid::Generator::serializer_options (*h_ops);
+
+ show_sloc = h_ops->value<CXX::Hybrid::CLI::show_sloc> ();
+ }
+
+ if (args.size () < 2)
+ {
+ e << "error: no input file specified" << endl;
+ return 1;
+ }
+
+ Boolean fpt (common_ops.value<CLI::file_per_type> ());
+
+ // 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<CXX::Parser::CLI::generate_xml_schema> ();
+ use = p_ops->value<CXX::Parser::CLI::extern_xml_schema> ();
+ }
+ else if (cmd == "cxx-serializer")
+ {
+ gen = s_ops->value<CXX::Serializer::CLI::generate_xml_schema> ();
+ use = s_ops->value<CXX::Serializer::CLI::extern_xml_schema> ();
+ }
+ else if (cmd == "cxx-hybrid")
+ {
+ gen = h_ops->value<CXX::Hybrid::CLI::generate_xml_schema> ();
+ use = h_ops->value<CXX::Hybrid::CLI::extern_xml_schema> ();
+ }
+
+ // 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<CLI::location_map> (),
+ common_ops.value<CLI::location_regex> (),
+ common_ops.value<CLI::location_regex_trace> ());
+
+ AnonymousNameTranslator anon_translator (
+ common_ops.value<CLI::anonymous_regex> (),
+ common_ops.value<CLI::anonymous_regex_trace> ());
+
+ Boolean gen_hybrid (cmd == "cxx-hybrid");
+
+ Boolean gen_parser (
+ cmd == "cxx-parser" ||
+ (gen_hybrid && h_ops->value<CXX::Hybrid::CLI::generate_parser> ()));
+
+ Boolean gen_serializer (
+ cmd == "cxx-serializer" ||
+ (gen_hybrid && h_ops->value<CXX::Hybrid::CLI::generate_serializer> ()));
+
+ 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<CLI::disable_full_check> (),
+ loc_translator,
+ disabled_w);
+
+ Evptr<SemanticGraph::Schema> 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<CXX::Parser::CLI::generate_xml_schema> ();
+
+ if (gen_xml_schema)
+ {
+ if (NarrowString name =
+ p_ops->value<CXX::Parser::CLI::extern_xml_schema> ())
+ {
+ if (tu.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+ }
+ else if (cmd == "cxx-serializer")
+ {
+ gen_xml_schema =
+ s_ops->value<CXX::Serializer::CLI::generate_xml_schema> ();
+
+ if (gen_xml_schema)
+ {
+ if (NarrowString name =
+ s_ops->value<CXX::Serializer::CLI::extern_xml_schema> ())
+ {
+ if (tu.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+ }
+ else if (cmd == "cxx-hybrid")
+ {
+ gen_xml_schema =
+ h_ops->value<CXX::Hybrid::CLI::generate_xml_schema> ();
+
+ if (gen_xml_schema)
+ {
+ if (NarrowString name =
+ h_ops->value<CXX::Hybrid::CLI::extern_xml_schema> ())
+ {
+ 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<CLI::preserve_anonymous> ())
+ {
+ 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<CXX::Parser::CLI::generate_test_driver> ()) ||
+ (cmd == "cxx-serializer" &&
+ s_ops->value<CXX::Serializer::CLI::generate_test_driver> ())))
+ {
+ e << "info: generating test driver for the first schema only: '" <<
+ paths[0] << "'" << endl;
+ }
+
+ XSDFrontend::Parser parser (
+ cmd != "cxx-hybrid",
+ !common_ops.value<CLI::disable_full_check> (),
+ loc_translator,
+ disabled_w);
+
+ Evptr<SemanticGraph::Schema> schema (parser.parse (paths));
+
+ // Morph anonymous types.
+ //
+ if (!common_ops.value<CLI::preserve_anonymous> ())
+ {
+ 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<SemanticGraph::Schema*> Schemas;
+
+ TypeSchemaTranslator type_translator (
+ common_ops.value<CLI::type_file_regex> (),
+ common_ops.value<CLI::type_file_regex_trace> ());
+
+ 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<CLI::file_list> ())
+ {
+ 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<CLI::file_list_delim> ());
+ expand_nl (d);
+
+ if (NarrowString p = common_ops.value<CLI::file_list_prologue> ())
+ {
+ 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<CLI::file_list_epilogue> ())
+ {
+ 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<CLI::sloc_limit> ())
+ {
+ 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 <boris@codesynthesis.com>
+// 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 <xsd-frontend/semantic-graph/elements.hxx> // Path
+
+#include <cult/types.hxx>
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <cstdio> // std::remove
+
+using namespace Cult::Types;
+
+//
+//
+typedef Cult::Containers::Set<NarrowString> WarningSet;
+
+//
+//
+typedef Cult::Containers::Vector<NarrowString> 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<AutoUnlink> (new AutoUnlink (file)));
+ }
+
+ Void
+ cancel ()
+ {
+ for (Unlinks::Iterator i (unlinks_.begin ()); i != unlinks_.end (); ++i)
+ {
+ (*i)->cancel ();
+ }
+ }
+
+private:
+ typedef Cult::Containers::Vector<Evptr<AutoUnlink> > Unlinks;
+ Unlinks unlinks_;
+};
+
+#endif // XSDE_HXX