aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
commite4c22d3686da0e973e21eae0561c1169c0eeff36 (patch)
tree0a49e9167edc88938b0287949080931314e8afea
parent0d62005a3ff3b62d02c2eb3fd8644e0e19b202e8 (diff)
Implement support for XML Schema polymorphism in C++/Hybrid
examples/cxx/hybrid/polyroot/ examples/cxx/hybrid/polymorphism/: new examples tests/cxx/hybrid/polymorphism/: new tests
-rw-r--r--NEWS9
-rw-r--r--build/xsde/hybrid/xsd-cxx.make6
-rw-r--r--dist/examples/cxx/hybrid/binary/cdr/makefile4
-rw-r--r--dist/examples/cxx/hybrid/binary/cdr/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/binary/custom/makefile4
-rw-r--r--dist/examples/cxx/hybrid/binary/custom/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/binary/xdr/makefile4
-rw-r--r--dist/examples/cxx/hybrid/binary/xdr/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/compositors/makefile4
-rw-r--r--dist/examples/cxx/hybrid/compositors/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/custom/wildcard/makefile4
-rw-r--r--dist/examples/cxx/hybrid/custom/wildcard/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/filter/makefile4
-rw-r--r--dist/examples/cxx/hybrid/filter/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/hello/makefile4
-rw-r--r--dist/examples/cxx/hybrid/hello/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/library/makefile4
-rw-r--r--dist/examples/cxx/hybrid/library/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/makefile4
-rw-r--r--dist/examples/cxx/hybrid/minimal/makefile4
-rw-r--r--dist/examples/cxx/hybrid/minimal/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/multiroot/makefile4
-rw-r--r--dist/examples/cxx/hybrid/multiroot/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/polymorphism/makefile56
-rw-r--r--dist/examples/cxx/hybrid/polymorphism/nmakefile53
-rw-r--r--dist/examples/cxx/hybrid/polyroot/makefile58
-rw-r--r--dist/examples/cxx/hybrid/polyroot/nmakefile55
-rw-r--r--dist/examples/cxx/hybrid/streaming/makefile4
-rw-r--r--dist/examples/cxx/hybrid/streaming/nmakefile4
-rw-r--r--dist/examples/cxx/hybrid/wildcard/makefile4
-rw-r--r--dist/examples/cxx/hybrid/wildcard/nmakefile4
-rw-r--r--dist/libxsde/xsde/makefile6
-rw-r--r--dist/libxsde/xsde/nmakefile6
-rw-r--r--documentation/cxx/hybrid/guide/index.xhtml397
-rw-r--r--documentation/cxx/parser/guide/index.xhtml4
-rw-r--r--documentation/cxx/serializer/guide/index.xhtml2
-rw-r--r--documentation/xsde.137
-rw-r--r--documentation/xsde.xhtml34
-rw-r--r--examples/cxx/hybrid/README8
-rw-r--r--examples/cxx/hybrid/binary/xdr/driver.cxx1
-rw-r--r--examples/cxx/hybrid/custom/wildcard/driver.cxx1
-rw-r--r--examples/cxx/hybrid/filter/driver.cxx1
-rw-r--r--examples/cxx/hybrid/library/driver.cxx1
-rw-r--r--examples/cxx/hybrid/makefile8
-rw-r--r--examples/cxx/hybrid/minimal/driver.cxx1
-rw-r--r--examples/cxx/hybrid/polymorphism/README57
-rw-r--r--examples/cxx/hybrid/polymorphism/driver.cxx202
-rw-r--r--examples/cxx/hybrid/polymorphism/makefile113
-rw-r--r--examples/cxx/hybrid/polymorphism/supermen.xml26
-rw-r--r--examples/cxx/hybrid/polymorphism/supermen.xsd49
-rw-r--r--examples/cxx/hybrid/polyroot/README60
-rw-r--r--examples/cxx/hybrid/polyroot/batman.xml17
-rw-r--r--examples/cxx/hybrid/polyroot/driver.cxx322
-rw-r--r--examples/cxx/hybrid/polyroot/makefile115
-rw-r--r--examples/cxx/hybrid/polyroot/person.xml16
-rw-r--r--examples/cxx/hybrid/polyroot/superman.xml17
-rw-r--r--examples/cxx/hybrid/polyroot/supermen.xsd40
-rw-r--r--examples/cxx/hybrid/streaming/driver.cxx1
-rw-r--r--examples/cxx/hybrid/wildcard/driver.cxx1
-rw-r--r--examples/cxx/parser/README16
-rw-r--r--examples/cxx/parser/polymorphism/README6
-rw-r--r--examples/cxx/serializer/README16
-rw-r--r--examples/cxx/serializer/polymorphism/README6
-rw-r--r--libxsde/xsde/cxx/hybrid/any-type.cxx53
-rw-r--r--libxsde/xsde/cxx/hybrid/any-type.hxx28
-rw-r--r--libxsde/xsde/cxx/hybrid/parser-map.cxx59
-rw-r--r--libxsde/xsde/cxx/hybrid/parser-map.hxx52
-rw-r--r--libxsde/xsde/cxx/hybrid/serializer-map.cxx61
-rw-r--r--libxsde/xsde/cxx/hybrid/serializer-map.hxx52
-rw-r--r--libxsde/xsde/cxx/parser/map.cxx8
-rw-r--r--libxsde/xsde/cxx/parser/map.hxx1
-rw-r--r--libxsde/xsde/cxx/parser/map.ixx2
-rw-r--r--libxsde/xsde/cxx/serializer/map.cxx8
-rw-r--r--libxsde/xsde/cxx/serializer/map.hxx1
-rw-r--r--libxsde/xsde/cxx/serializer/map.ixx2
-rw-r--r--libxsde/xsde/makefile6
-rw-r--r--tests/cxx/hybrid/makefile2
-rw-r--r--tests/cxx/hybrid/polymorphism/any-type/driver.cxx59
-rw-r--r--tests/cxx/hybrid/polymorphism/any-type/makefile99
-rw-r--r--tests/cxx/hybrid/polymorphism/any-type/test.xml7
-rw-r--r--tests/cxx/hybrid/polymorphism/any-type/test.xsd37
-rw-r--r--tests/cxx/hybrid/polymorphism/makefile24
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/driver.cxx60
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/makefile100
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/output1
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/test.xml7
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/test.xsd28
-rw-r--r--tests/cxx/hybrid/polymorphism/multischema/type.xsd26
-rw-r--r--xsde/cxx/elements.cxx9
-rw-r--r--xsde/cxx/hybrid/aggregate-elements.hxx31
-rw-r--r--xsde/cxx/hybrid/aggregate-include.hxx223
-rw-r--r--xsde/cxx/hybrid/cli.hxx10
-rw-r--r--xsde/cxx/hybrid/elements.cxx7
-rw-r--r--xsde/cxx/hybrid/elements.hxx12
-rw-r--r--xsde/cxx/hybrid/generator.cxx130
-rw-r--r--xsde/cxx/hybrid/generator.hxx63
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.cxx315
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.cxx162
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx35
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx11
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx52
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.cxx330
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.cxx169
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx35
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx13
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx100
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx94
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx9
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx13
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx274
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.hxx5
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx225
-rw-r--r--xsde/cxx/hybrid/validator.cxx9
-rw-r--r--xsde/cxx/parser/generator.cxx10
-rw-r--r--xsde/cxx/parser/generator.hxx17
-rw-r--r--xsde/cxx/parser/name-processor.cxx11
-rw-r--r--xsde/cxx/parser/name-processor.hxx5
-rw-r--r--xsde/cxx/parser/validator.cxx2
-rw-r--r--xsde/cxx/serializer/generator.cxx10
-rw-r--r--xsde/cxx/serializer/generator.hxx17
-rw-r--r--xsde/cxx/serializer/name-processor.cxx11
-rw-r--r--xsde/cxx/serializer/name-processor.hxx5
-rw-r--r--xsde/cxx/serializer/validator.cxx2
-rw-r--r--xsde/xsde.cxx202
128 files changed, 4985 insertions, 363 deletions
diff --git a/NEWS b/NEWS
index 95ccd71..c4c7628 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,15 @@ Version 3.1.0
C++/Hybrid
+ * Support for XML Schema polymorphism. The new --generate-polymorphic
+ option 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 3.7, "Support
+ for Polymorphism" and Section 4.9, "Polymorphic Object Models" in
+ the Embedded C++/Parser Mapping Getting Started Guide we well as
+ the polymorphism and polyroot examples in the examples/cxx/hybrid/
+ directory.
+
* Support for saving the object model to and loading it from binary
representations. The new --generate--insertion and --generate-extraction
options trigger generation of data representation stream insertion and
diff --git a/build/xsde/hybrid/xsd-cxx.make b/build/xsde/hybrid/xsd-cxx.make
index b221d7a..a4e9eeb 100644
--- a/build/xsde/hybrid/xsd-cxx.make
+++ b/build/xsde/hybrid/xsd-cxx.make
@@ -81,9 +81,9 @@ ifeq ($(xsde_serializer_validation),n)
ops += --suppress-serializer-val
endif
-#ifeq ($(xsde_polymorphic),y)
-#ops += --runtime-polymorphic
-#endif
+ifeq ($(xsde_polymorphic),y)
+ops += --runtime-polymorphic
+endif
ifeq ($(xsde_reuse_style),mixin)
ops += --reuse-style-mixin
diff --git a/dist/examples/cxx/hybrid/binary/cdr/makefile b/dist/examples/cxx/hybrid/binary/cdr/makefile
index 96c6274..6814623 100644
--- a/dist/examples/cxx/hybrid/binary/cdr/makefile
+++ b/dist/examples/cxx/hybrid/binary/cdr/makefile
@@ -24,6 +24,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o library.o library-pskel.o library-pimpl.o \
library-sskel.o library-simpl.o $(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/binary/cdr/nmakefile b/dist/examples/cxx/hybrid/binary/cdr/nmakefile
index a87ded2..f08cd4c 100644
--- a/dist/examples/cxx/hybrid/binary/cdr/nmakefile
+++ b/dist/examples/cxx/hybrid/binary/cdr/nmakefile
@@ -24,6 +24,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj library.obj library-pskel.obj library-pimpl.obj \
library-sskel.obj library-simpl.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/binary/custom/makefile b/dist/examples/cxx/hybrid/binary/custom/makefile
index c0e57ad..39ba93c 100644
--- a/dist/examples/cxx/hybrid/binary/custom/makefile
+++ b/dist/examples/cxx/hybrid/binary/custom/makefile
@@ -22,6 +22,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o library.o library-pskel.o library-pimpl.o \
library-sskel.o library-simpl.o exceptions.o orawstream.o \
irawstream.o $(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/binary/custom/nmakefile b/dist/examples/cxx/hybrid/binary/custom/nmakefile
index b53db8e..c99b887 100644
--- a/dist/examples/cxx/hybrid/binary/custom/nmakefile
+++ b/dist/examples/cxx/hybrid/binary/custom/nmakefile
@@ -22,6 +22,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj library.obj library-pskel.obj library-pimpl.obj \
library-sskel.obj library-simpl.obj exceptions.obj orawstream.obj \
irawstream.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/binary/xdr/makefile b/dist/examples/cxx/hybrid/binary/xdr/makefile
index 95ceade..ede26ea 100644
--- a/dist/examples/cxx/hybrid/binary/xdr/makefile
+++ b/dist/examples/cxx/hybrid/binary/xdr/makefile
@@ -24,6 +24,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o library.o library-pskel.o library-pimpl.o \
library-sskel.o library-simpl.o $(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/binary/xdr/nmakefile b/dist/examples/cxx/hybrid/binary/xdr/nmakefile
index f71e178..2930de2 100644
--- a/dist/examples/cxx/hybrid/binary/xdr/nmakefile
+++ b/dist/examples/cxx/hybrid/binary/xdr/nmakefile
@@ -22,6 +22,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj library.obj library-pskel.obj library-pimpl.obj \
library-sskel.obj library-simpl.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/compositors/makefile b/dist/examples/cxx/hybrid/compositors/makefile
index fbc44f9..d030bf4 100644
--- a/dist/examples/cxx/hybrid/compositors/makefile
+++ b/dist/examples/cxx/hybrid/compositors/makefile
@@ -30,6 +30,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o compositors.o $(root)/libxsde/xsde/libxsde.a
driver.o: driver.cxx compositors.hxx
diff --git a/dist/examples/cxx/hybrid/compositors/nmakefile b/dist/examples/cxx/hybrid/compositors/nmakefile
index 9bc77b7..b51cbe3 100644
--- a/dist/examples/cxx/hybrid/compositors/nmakefile
+++ b/dist/examples/cxx/hybrid/compositors/nmakefile
@@ -30,6 +30,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj compositors.obj $(root)\libxsde\xsde\xsde.lib
driver.obj: driver.cxx compositors.hxx
diff --git a/dist/examples/cxx/hybrid/custom/wildcard/makefile b/dist/examples/cxx/hybrid/custom/wildcard/makefile
index e0a881d..71283bb 100644
--- a/dist/examples/cxx/hybrid/custom/wildcard/makefile
+++ b/dist/examples/cxx/hybrid/custom/wildcard/makefile
@@ -18,6 +18,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o email.o body.o email-pskel.o email-pimpl.o \
email-sskel.o email-simpl.o envelope-pimpl.o envelope-simpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/custom/wildcard/nmakefile b/dist/examples/cxx/hybrid/custom/wildcard/nmakefile
index 0a88820..33f3570 100644
--- a/dist/examples/cxx/hybrid/custom/wildcard/nmakefile
+++ b/dist/examples/cxx/hybrid/custom/wildcard/nmakefile
@@ -18,6 +18,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj email.obj body.obj email-pskel.obj email-pimpl.obj \
email-sskel.obj email-simpl.obj envelope-pimpl.obj envelope-simpl.obj \
$(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/filter/makefile b/dist/examples/cxx/hybrid/filter/makefile
index f1ea235..f9137fc 100644
--- a/dist/examples/cxx/hybrid/filter/makefile
+++ b/dist/examples/cxx/hybrid/filter/makefile
@@ -18,6 +18,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o people.o people-pskel.o people-pimpl.o people-sskel.o \
people-simpl.o people-custom-pimpl.o people-custom-simpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/filter/nmakefile b/dist/examples/cxx/hybrid/filter/nmakefile
index b93ac66..0343a90 100644
--- a/dist/examples/cxx/hybrid/filter/nmakefile
+++ b/dist/examples/cxx/hybrid/filter/nmakefile
@@ -18,6 +18,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj people.obj people-pskel.obj people-pimpl.obj \
people-sskel.obj people-simpl.obj people-custom-pimpl.obj \
people-custom-simpl.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/hello/makefile b/dist/examples/cxx/hybrid/hello/makefile
index f184264..3a6f645 100644
--- a/dist/examples/cxx/hybrid/hello/makefile
+++ b/dist/examples/cxx/hybrid/hello/makefile
@@ -22,6 +22,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o hello.o hello-pskel.o hello-pimpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/hello/nmakefile b/dist/examples/cxx/hybrid/hello/nmakefile
index 4044cb1..2e5730f 100644
--- a/dist/examples/cxx/hybrid/hello/nmakefile
+++ b/dist/examples/cxx/hybrid/hello/nmakefile
@@ -22,6 +22,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj hello.obj hello-pskel.obj hello-pimpl.obj \
$(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/library/makefile b/dist/examples/cxx/hybrid/library/makefile
index 8610879..be92939 100644
--- a/dist/examples/cxx/hybrid/library/makefile
+++ b/dist/examples/cxx/hybrid/library/makefile
@@ -18,6 +18,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o library.o library-pskel.o library-pimpl.o \
library-sskel.o library-simpl.o $(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/library/nmakefile b/dist/examples/cxx/hybrid/library/nmakefile
index 5585416..b5a622b 100644
--- a/dist/examples/cxx/hybrid/library/nmakefile
+++ b/dist/examples/cxx/hybrid/library/nmakefile
@@ -18,6 +18,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj library.obj library-pskel.obj library-pimpl.obj \
library-sskel.obj library-simpl.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/makefile b/dist/examples/cxx/hybrid/makefile
index 11af66b..3a9ddaa 100644
--- a/dist/examples/cxx/hybrid/makefile
+++ b/dist/examples/cxx/hybrid/makefile
@@ -13,6 +13,10 @@ ifeq ($(XSDE_STL),y)
dirs += library wildcard filter
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+dirs += polymorphism polyroot
+endif
+
endif
endif
diff --git a/dist/examples/cxx/hybrid/minimal/makefile b/dist/examples/cxx/hybrid/minimal/makefile
index 87e5325..14b7008 100644
--- a/dist/examples/cxx/hybrid/minimal/makefile
+++ b/dist/examples/cxx/hybrid/minimal/makefile
@@ -24,6 +24,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o people.o people-pskel.o people-pimpl.o \
people-sskel.o people-simpl.o $(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/minimal/nmakefile b/dist/examples/cxx/hybrid/minimal/nmakefile
index 6a1c736..f3faf72 100644
--- a/dist/examples/cxx/hybrid/minimal/nmakefile
+++ b/dist/examples/cxx/hybrid/minimal/nmakefile
@@ -24,6 +24,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj people.obj people-pskel.obj people-pimpl.obj \
people-sskel.obj people-simpl.obj $(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/multiroot/makefile b/dist/examples/cxx/hybrid/multiroot/makefile
index 28423c1..d427726 100644
--- a/dist/examples/cxx/hybrid/multiroot/makefile
+++ b/dist/examples/cxx/hybrid/multiroot/makefile
@@ -22,6 +22,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o protocol.o protocol-pskel.o protocol-pimpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/multiroot/nmakefile b/dist/examples/cxx/hybrid/multiroot/nmakefile
index a647e50..bd3ffe3 100644
--- a/dist/examples/cxx/hybrid/multiroot/nmakefile
+++ b/dist/examples/cxx/hybrid/multiroot/nmakefile
@@ -22,6 +22,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj protocol.obj protocol-pskel.obj protocol-pimpl.obj \
$(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/nmakefile b/dist/examples/cxx/hybrid/nmakefile
index d9d791c..70d4dfe 100644
--- a/dist/examples/cxx/hybrid/nmakefile
+++ b/dist/examples/cxx/hybrid/nmakefile
@@ -13,6 +13,10 @@ dirs = $(dirs) hello multiroot streaming
dirs = $(dirs) library wildcard filter
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+dirs = $(dirs) polymorphism polyroot
+!endif
+
!endif
!endif
diff --git a/dist/examples/cxx/hybrid/polymorphism/makefile b/dist/examples/cxx/hybrid/polymorphism/makefile
new file mode 100644
index 0000000..353e692
--- /dev/null
+++ b/dist/examples/cxx/hybrid/polymorphism/makefile
@@ -0,0 +1,56 @@
+root := ../../../..
+
+include $(root)/build/cxx/rules.make
+
+# Build.
+#
+EXTRA_CPPFLAGS := -I$(root)/libxsde
+
+ifeq ($(XSDE_STL),n)
+EXTRA_XSDFLAGS += --no-stl
+endif
+
+ifeq ($(XSDE_LONGLONG),n)
+EXTRA_XSDFLAGS += --no-long-long
+endif
+
+ifeq ($(XSDE_PARSER_VALIDATION),n)
+EXTRA_XSDFLAGS += --suppress-validation
+endif
+
+ifeq ($(XSDE_REUSE_STYLE),mixin)
+EXTRA_XSDFLAGS += --reuse-style-mixin
+endif
+
+driver: driver.o supermen.o supermen-pskel.o supermen-pimpl.o \
+supermen-sskel.o supermen-simpl.o $(root)/libxsde/xsde/libxsde.a
+
+driver.o: driver.cxx supermen.hxx supermen-pimpl.hxx supermen-simpl.hxx
+supermen.o: supermen.cxx supermen.hxx
+supermen-pskel.o: supermen-pskel.cxx
+supermen-pimpl.o: supermen-pimpl.cxx
+supermen-simpl.o: supermen-simpl.cxx
+supermen-simpl.o: supermen-simpl.cxx
+
+.PRECIOUS: %.hxx %.cxx %-pskel.hxx %-pskel.cxx %-pimpl.hxx %-pimpl.cxx \
+%-sskel.hxx %-sskel.cxx %-simpl.hxx %-simpl.cxx
+
+%.hxx %.cxx %-pskel.hxx %-pskel.cxx %-pimpl.hxx %-pimpl.cxx \
+%-sskel.hxx %-sskel.cxx %-simpl.hxx %-simpl.cxx: %.xsd
+ $(root)/bin/xsde cxx-hybrid $(XSDFLAGS) $(EXTRA_XSDFLAGS) \
+--generate-parser --generate-serializer --generate-aggregate \
+--generate-polymorphic --generate-typeinfo --root-element supermen $<
+
+# Test.
+#
+.PHONY: test
+test: driver supermen.xml
+ ./driver supermen.xml
+
+# Clean.
+#
+.PHONY: clean
+clean:
+ rm -f supermen-pimpl.?xx supermen-pskel.?xx supermen-simpl.?xx \
+supermen-sskel.?xx supermen.?xx supermen-pimpl.o supermen-pskel.o \
+supermen-simpl.o supermen-sskel.o supermen.o driver.o driver
diff --git a/dist/examples/cxx/hybrid/polymorphism/nmakefile b/dist/examples/cxx/hybrid/polymorphism/nmakefile
new file mode 100644
index 0000000..479a557
--- /dev/null
+++ b/dist/examples/cxx/hybrid/polymorphism/nmakefile
@@ -0,0 +1,53 @@
+root = ..\..\..\..
+
+!include $(root)\build\cxx\rules.nmake
+
+# Build.
+#
+EXTRA_CPPFLAGS = /I$(root)\libxsde
+
+!if "$(XSDE_STL)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --no-stl
+!endif
+
+!if "$(XSDE_LONGLONG)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --no-long-long
+!endif
+
+!if "$(XSDE_PARSER_VALIDATION)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
+!endif
+
+!if "$(XSDE_REUSE_STYLE)" == "mixin"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
+!endif
+
+driver.exe: driver.obj supermen.obj supermen-pskel.obj supermen-pimpl.obj \
+supermen-sskel.obj supermen-simpl.obj $(root)\libxsde\xsde\xsde.lib
+
+driver.obj: driver.cxx supermen.hxx supermen-pimpl.hxx supermen-simpl.hxx
+supermen.obj: supermen.cxx
+supermen-pskel.obj: supermen-pskel.cxx
+supermen-pimpl.obj: supermen-pimpl.cxx
+supermen-sskel.obj: supermen-sskel.cxx
+supermen-simpl.obj: supermen-simpl.cxx
+
+supermen.cxx supermen.hxx \
+supermen-pskel.cxx supermen-pskel.hxx supermen-pimpl.cxx supermen-pimpl.hxx \
+supermen-sskel.cxx supermen-sskel.hxx supermen-simpl.cxx supermen-simpl.hxx \
+: supermen.xsd
+ $(root)\bin\xsde.exe cxx-hybrid $(XSDFLAGS) $(EXTRA_XSDFLAGS) \
+--generate-parser --generate-serializer --generate-aggregate \
+--generate-polymorphic --generate-typeinfo --root-element supermen supermen.xsd
+
+# Test.
+#
+test: driver.exe supermen.xml
+ .\driver.exe supermen.xml
+
+# Clean.
+#
+clean:
+ -del supermen-pimpl.?xx supermen-pskel.?xx supermen-simpl.?xx \
+supermen-sskel.?xx supermen.?xx supermen-pimpl.obj supermen-pskel.obj \
+supermen-simpl.obj supermen-sskel.obj supermen.obj driver.obj driver.exe
diff --git a/dist/examples/cxx/hybrid/polyroot/makefile b/dist/examples/cxx/hybrid/polyroot/makefile
new file mode 100644
index 0000000..d38f04c
--- /dev/null
+++ b/dist/examples/cxx/hybrid/polyroot/makefile
@@ -0,0 +1,58 @@
+root := ../../../..
+
+include $(root)/build/cxx/rules.make
+
+# Build.
+#
+EXTRA_CPPFLAGS := -I$(root)/libxsde
+
+ifeq ($(XSDE_STL),n)
+EXTRA_XSDFLAGS += --no-stl
+endif
+
+ifeq ($(XSDE_LONGLONG),n)
+EXTRA_XSDFLAGS += --no-long-long
+endif
+
+ifeq ($(XSDE_PARSER_VALIDATION),n)
+EXTRA_XSDFLAGS += --suppress-validation
+endif
+
+ifeq ($(XSDE_REUSE_STYLE),mixin)
+EXTRA_XSDFLAGS += --reuse-style-mixin
+endif
+
+driver: driver.o supermen.o supermen-pskel.o supermen-pimpl.o \
+supermen-sskel.o supermen-simpl.o $(root)/libxsde/xsde/libxsde.a
+
+driver.o: driver.cxx supermen.hxx supermen-pimpl.hxx supermen-simpl.hxx
+supermen.o: supermen.cxx supermen.hxx
+supermen-pskel.o: supermen-pskel.cxx
+supermen-pimpl.o: supermen-pimpl.cxx
+supermen-simpl.o: supermen-simpl.cxx
+supermen-simpl.o: supermen-simpl.cxx
+
+.PRECIOUS: %.hxx %.cxx %-pskel.hxx %-pskel.cxx %-pimpl.hxx %-pimpl.cxx \
+%-sskel.hxx %-sskel.cxx %-simpl.hxx %-simpl.cxx
+
+%.hxx %.cxx %-pskel.hxx %-pskel.cxx %-pimpl.hxx %-pimpl.cxx \
+%-sskel.hxx %-sskel.cxx %-simpl.hxx %-simpl.cxx: %.xsd
+ $(root)/bin/xsde cxx-hybrid $(XSDFLAGS) $(EXTRA_XSDFLAGS) \
+--generate-parser --generate-serializer --generate-aggregate \
+--generate-polymorphic --generate-typeinfo --root-element person $<
+
+# Test.
+#
+.PHONY: test
+test: driver person.xml batman.xml superman.xml
+ ./driver person.xml
+ ./driver batman.xml
+ ./driver superman.xml
+
+# Clean.
+#
+.PHONY: clean
+clean:
+ rm -f supermen-pimpl.?xx supermen-pskel.?xx supermen-simpl.?xx \
+supermen-sskel.?xx supermen.?xx supermen-pimpl.o supermen-pskel.o \
+supermen-simpl.o supermen-sskel.o supermen.o driver.o driver
diff --git a/dist/examples/cxx/hybrid/polyroot/nmakefile b/dist/examples/cxx/hybrid/polyroot/nmakefile
new file mode 100644
index 0000000..8d098bb
--- /dev/null
+++ b/dist/examples/cxx/hybrid/polyroot/nmakefile
@@ -0,0 +1,55 @@
+root = ..\..\..\..
+
+!include $(root)\build\cxx\rules.nmake
+
+# Build.
+#
+EXTRA_CPPFLAGS = /I$(root)\libxsde
+
+!if "$(XSDE_STL)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --no-stl
+!endif
+
+!if "$(XSDE_LONGLONG)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --no-long-long
+!endif
+
+!if "$(XSDE_PARSER_VALIDATION)" == "n"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
+!endif
+
+!if "$(XSDE_REUSE_STYLE)" == "mixin"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
+!endif
+
+driver.exe: driver.obj supermen.obj supermen-pskel.obj supermen-pimpl.obj \
+supermen-sskel.obj supermen-simpl.obj $(root)\libxsde\xsde\xsde.lib
+
+driver.obj: driver.cxx supermen.hxx supermen-pimpl.hxx supermen-simpl.hxx
+supermen.obj: supermen.cxx
+supermen-pskel.obj: supermen-pskel.cxx
+supermen-pimpl.obj: supermen-pimpl.cxx
+supermen-sskel.obj: supermen-sskel.cxx
+supermen-simpl.obj: supermen-simpl.cxx
+
+supermen.cxx supermen.hxx \
+supermen-pskel.cxx supermen-pskel.hxx supermen-pimpl.cxx supermen-pimpl.hxx \
+supermen-sskel.cxx supermen-sskel.hxx supermen-simpl.cxx supermen-simpl.hxx \
+: supermen.xsd
+ $(root)\bin\xsde.exe cxx-hybrid $(XSDFLAGS) $(EXTRA_XSDFLAGS) \
+--generate-parser --generate-serializer --generate-aggregate \
+--generate-polymorphic --generate-typeinfo --root-element person supermen.xsd
+
+# Test.
+#
+test: driver.exe person.xml batman.xml superman.xml
+ .\driver person.xml
+ .\driver batman.xml
+ .\driver superman.xml
+
+# Clean.
+#
+clean:
+ -del supermen-pimpl.?xx supermen-pskel.?xx supermen-simpl.?xx \
+supermen-sskel.?xx supermen.?xx supermen-pimpl.obj supermen-pskel.obj \
+supermen-simpl.obj supermen-sskel.obj supermen.obj driver.obj driver.exe
diff --git a/dist/examples/cxx/hybrid/streaming/makefile b/dist/examples/cxx/hybrid/streaming/makefile
index b4bff7a..7a7a440 100644
--- a/dist/examples/cxx/hybrid/streaming/makefile
+++ b/dist/examples/cxx/hybrid/streaming/makefile
@@ -22,6 +22,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o position.o position-pskel.o position-pimpl.o \
position-sskel.o position-simpl.o object-pimpl.o object-simpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/streaming/nmakefile b/dist/examples/cxx/hybrid/streaming/nmakefile
index c3ae34a..a981d82 100644
--- a/dist/examples/cxx/hybrid/streaming/nmakefile
+++ b/dist/examples/cxx/hybrid/streaming/nmakefile
@@ -22,6 +22,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj position.obj position-pskel.obj position-pimpl.obj \
position-sskel.obj position-simpl.obj object-pimpl.obj object-simpl.obj \
$(root)\libxsde\xsde\xsde.lib
diff --git a/dist/examples/cxx/hybrid/wildcard/makefile b/dist/examples/cxx/hybrid/wildcard/makefile
index 9d4dfa2..876003f 100644
--- a/dist/examples/cxx/hybrid/wildcard/makefile
+++ b/dist/examples/cxx/hybrid/wildcard/makefile
@@ -18,6 +18,10 @@ ifeq ($(XSDE_REUSE_STYLE),mixin)
EXTRA_XSDFLAGS += --reuse-style-mixin
endif
+ifeq ($(XSDE_POLYMORPHIC),y)
+EXTRA_XSDFLAGS += --runtime-polymorphic
+endif
+
driver: driver.o email.o body.o email-pskel.o email-pimpl.o \
email-sskel.o email-simpl.o envelope-pimpl.o envelope-simpl.o \
$(root)/libxsde/xsde/libxsde.a
diff --git a/dist/examples/cxx/hybrid/wildcard/nmakefile b/dist/examples/cxx/hybrid/wildcard/nmakefile
index acdb033..83e3ba0 100644
--- a/dist/examples/cxx/hybrid/wildcard/nmakefile
+++ b/dist/examples/cxx/hybrid/wildcard/nmakefile
@@ -18,6 +18,10 @@ EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --suppress-validation
EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --reuse-style-mixin
!endif
+!if "$(XSDE_POLYMORPHIC)" == "y"
+EXTRA_XSDFLAGS = $(EXTRA_XSDFLAGS) --runtime-polymorphic
+!endif
+
driver.exe: driver.obj email.obj body.obj email-pskel.obj email-pimpl.obj \
email-sskel.obj email-simpl.obj envelope-pimpl.obj envelope-simpl.obj \
$(root)\libxsde\xsde\xsde.lib
diff --git a/dist/libxsde/xsde/makefile b/dist/libxsde/xsde/makefile
index eb1abb3..142c269 100644
--- a/dist/libxsde/xsde/makefile
+++ b/dist/libxsde/xsde/makefile
@@ -49,6 +49,12 @@ endif
##
src += cxx/hybrid/sequence.cxx
+ifeq ($(XSDE_POLYMORPHIC),y)
+src += \
+cxx/hybrid/parser-map.cxx \
+cxx/hybrid/serializer-map.cxx
+endif
+
ifeq ($(XSDE_CDR),y)
src += \
cxx/hybrid/cdr/exceptions.cxx \
diff --git a/dist/libxsde/xsde/nmakefile b/dist/libxsde/xsde/nmakefile
index fb2789a..888ca15 100644
--- a/dist/libxsde/xsde/nmakefile
+++ b/dist/libxsde/xsde/nmakefile
@@ -51,6 +51,12 @@ src = $(src) cxx\xml\char-table.cxx cxx\xml\ncname.cxx
##
src = $(src) cxx\hybrid\sequence.cxx
+!if "$(XSDE_POLYMORPHIC)" == "y"
+src = $(src) \
+cxx\hybrid\parser-map.cxx \
+cxx\hybrid\serializer-map.cxx
+!endif
+
!if "$(XSDE_CDR)" == "y"
src = $(src) \
cxx\hybrid\cdr\exceptions.cxx \
diff --git a/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml
index 62603dc..5871593 100644
--- a/documentation/cxx/hybrid/guide/index.xhtml
+++ b/documentation/cxx/hybrid/guide/index.xhtml
@@ -256,6 +256,7 @@
<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>
+ <tr><th>3.7</th><td><a href="#3.7">Support for Polymorphism</a></td></tr>
</table>
</td>
</tr>
@@ -271,6 +272,7 @@
<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>
+ <tr><th>4.9</th><td><a href="#4.9">Polymorphic Object Models</a></td></tr>
</table>
</td>
</tr>
@@ -560,7 +562,7 @@
&lt;greeting>Hello&lt;/greeting>
&lt;name>sun&lt;/name>
- &lt;name>earth&lt;/name>
+ &lt;name>moon&lt;/name>
&lt;name>world&lt;/name>
&lt;/hello>
@@ -910,7 +912,7 @@ main (int argc, char* argv[])
&lt;hello>
&lt;greeting>Hi&lt;/greeting>
&lt;name>sun&lt;/name>
- &lt;name>earth&lt;/name>
+ &lt;name>moon&lt;/name>
&lt;name>world&lt;/name>
&lt;name>mars&lt;/name>
&lt;/hello>
@@ -1410,6 +1412,154 @@ namespace xml_schema
"Serializer Reuse"</a> in the Embedded C++/Serializer Mapping Getting
Started Guide for details.</p>
+ <h2><a name="3.7">3.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_pimpl</code> and
+ <code>xml_schema::document_simpl</code> constructors (see
+ <a href="#6">Chapter 6, "Parsing and Serialization"</a> for details).
+ 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>The XSD/e compiler can often automatically determine which types are
+ polymorphic based on the substitution group declarations. However,
+ if your XML vocabulary is not using substitution groups or if
+ substitution groups are defined in a separate schema, then you will
+ need to use the <code>--polymorphic-type</code> option to specify
+ which types are polymorphic. When using this option you only need
+ to specify the root of a polymorphic type hierarchy and the XSD/e
+ compiler will assume that all the derived types are also polymorphic.
+ Also note that you need to specify this option when compiling every
+ schema file that references the polymorphic type. Consider the following
+ two schemas as an example:</p>
+
+ <pre class="xml">
+&lt;!-- base.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="b" type="xs:int"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="base" type="base"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <pre class="xml">
+&lt;!-- derived.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;include schemaLocation="base.xsd"/>
+
+ &lt;xs:complexType name="derived">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="d" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="derived" type="derived" substitutionGroup="base"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>In this example we need to specify "<code>--polymorphic-type base</code>"
+ when compiling both schemas because the substitution group is declared
+ in a schema other than the one defining type <code>base</code>.</p>
+
+ <p>Another issue that may arise when compiling polymorphic schemas is
+ the situation where the XSD/e compiler is unaware of all the
+ derivations of a polymorphic type while generating parser and
+ serializer aggregates. As a result, the generated code may not
+ be able to parse and serialize these "invisible" to the compiler
+ types. The following example will help illustrate this case.
+ Consider a modified version of <code>base.xsd</code> from the
+ above example:</p>
+
+ <pre class="xml">
+&lt;!-- base.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="b" type="xs:int"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="base" type="base"/>
+
+ &lt;xs:complexType name="root">
+ &lt;xs:sequence>
+ &lt;xs:element ref="base" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- document root -->
+ &lt;xs:element name="root" type="root"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Suppose we compile this schema as follows:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root base.xsd
+ </pre>
+
+ <p>The resulting parser and serializer aggregates for the <code>root</code>
+ element will not include the parser and serializer for the
+ <code>derived</code> type that can be used instead of the
+ <code>base</code> type. This is because the XSD/e compiler
+ has no knowledge of the <code>derived</code>'s existence when
+ compiling <code>base.xsd</code>.</p>
+
+ <p>There are two ways to overcome this problem. The easier but
+ potentially slower approach is to compile all your schemas
+ at once, for example:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root base.xsd derived.xsd
+ </pre>
+
+ <p>This will make sure the XSD/e compiler "sees" all the derivations
+ of the polymorphic types. The other approach allows
+ you to explicitly specify, with the <code>--polymorphic-schema</code>
+ option, additional schemas that may contain derivations of the
+ polymorphic types. Using this approach we would compile
+ <code>base.xsd</code> and <code>derived.xsd</code> like this:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root \
+--polymorphic-schema derived.xsd base.xsd
+
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base derived.xsd
+ </pre>
+
+ <p>For information on how to use object models with polymorphic types,
+ refer to <a href="#4.9">Section 4.9, "Polymorphic Object Models"</a>.</p>
+
<!-- Chapater 4 -->
@@ -1672,6 +1822,9 @@ private:
<li>it is recursive (that is, one of its elements contains
a reference, directly or indirectly, to the type itself)</li>
+
+ <li>it is polymorphic (see <a href="#4.9">Section 4.9, "Polymorphic
+ Object Models"</a> for details)</li>
</ol>
<p>The following build-in XML Schema types are variable-length:
@@ -3536,6 +3689,246 @@ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
</pre>
+ <h2><a name="4.9">4.9 Polymorphic Object Models</a></h2>
+
+ <p>When generating polymorphism-aware code (see <a href="#3.7">Section
+ 3.7, "Support for Polymorphism"</a>), some objects
+ in the resulting object model will be polymorphic. By polymorphic
+ we mean that the object's (static) type as specified in the
+ object model's interface may differ from the object's actual
+ (dynamic) type. Because of this, it may be necessary to discover
+ the object's actual type at runtime and cast it to this type to
+ gain access to the object's extended interface. 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>When compiling the schema above with the
+ <code>--generate-polymorphic</code> option, the XSD/e compiler
+ automatically detects that the type hierarchy starting with
+ the <code>person</code> type is polymorphic. A polymorphic
+ type is always variable-length which means objects of polymorphic
+ types are allocated dynamically and are stored and passed around
+ as pointers or references. A polymorphic type also defines a
+ virtual destructor which allows you to delete an instance of a
+ polymorphic type via a pointer to its base. The following code
+ fragment shows how we can parse, access, modify, and serialize
+ the above XML document:</p>
+
+ <pre class="c++">
+// Parse.
+//
+supermen_paggr supermen_p;
+
+// The last argument to the document's constructor indicates that we
+// are parsing polymorphic XML documents.
+//
+xml_schema::document_pimpl doc_p (
+ supermen_p.root_parser (),
+ supermen_p.root_name (),
+ true);
+
+supermen_p.pre ();
+doc_p.parse ("supermen.xml");
+auto_ptr&lt;supermen> sm (supermen_p.post ());
+
+// Print what we've got.
+//
+for (supermen::person_iterator i = sm->person ().begin ();
+ i != sm->person ().end ();
+ ++i)
+{
+ person&amp; p = *i;
+
+ if (batman* b = dynamic_cast&lt;batman*> (&amp;p))
+ {
+ cerr &lt;&lt; b->name () &lt;&lt; ", batman, wing span " &lt;&lt;
+ b->wing_span () &lt;&lt; endl;
+ }
+ else if (superman* s = dynamic_cast&lt;superman*> (&amp;p))
+ {
+ cerr &lt;&lt; s->name () &lt;&lt; ", ";
+
+ if (s->can_fly ())
+ cerr &lt;&lt; "flying ";
+
+ cerr &lt;&lt; "superman" &lt;&lt; endl;
+ }
+ else
+ {
+ cerr &lt;&lt; p.name () &lt;&lt; ", ordinary person" &lt;&lt; endl;
+ }
+}
+
+// Add another superman entry.
+//
+auto_ptr&lt;superman> s (new superman);
+s->name ("Clark Kent");
+s->can_fly (true);
+sm->person ().push_back (s.release ());
+
+// Serialize.
+//
+supermen_saggr supermen_s;
+
+// The last argument to the document's constructor indicates that we
+// are serializing polymorphic XML documents.
+//
+xml_schema::document_simpl doc_s (
+ supermen_s.root_serializer (),
+ supermen_s.root_name (),
+ true);
+
+doc_s.add_no_namespace_schema ("supermen.xsd");
+
+supermen_s.pre (*sm);
+doc_s.serialize (cout);
+supermen_s.post ();
+ </pre>
+
+ <p>In the example above we used the standard C++ RTTI mechanism
+ to detect the object's actual (dynamic) type. If RTTI is not
+ available on your platform, then you can request the generation
+ of custom runtime type information for polymorphic types
+ with the <code>--generate-typeinfo</code> XSD/e compiler
+ option. When this option is specified, each polymorphic
+ type provides the following two public functions:</p>
+
+ <pre class="c++">
+virtual const std::string&amp;
+_dynamic_type () const;
+
+static const std::string&amp;
+_static_type ();
+ </pre>
+
+ <p>Or, if STL is disabled (<a href="#3.1">Section 3.1, "Standard Template
+ Library"</a>), the following two functions:</p>
+
+ <pre class="c++">
+virtual const char*
+_dynamic_type () const;
+
+static const char*
+_static_type ();
+ </pre>
+
+ <p>The <code>_dynamic_type()</code> function returns the object's
+ dynamic type id. The <code>_static_type()</code> function
+ returns the type's static id that can be compared to the
+ dynamic id. The following code fragment shows how
+ we can change the previous example to use custom type information
+ instead of C++ RTTI:</p>
+
+ <pre class="c++">
+for (supermen::person_iterator i = sm->person ().begin ();
+ i != sm->person ().end ();
+ ++i)
+{
+ person&amp; p = *i;
+ const string&amp; dt = p._dynamic_type ();
+
+ if (dt == batman::_static_type ())
+ {
+ batman&amp; b = static_cast&lt;batman&amp;> (p)
+ cerr &lt;&lt; b.name () &lt;&lt; ", batman, wing span " &lt;&lt;
+ b.wing_span () &lt;&lt; endl;
+ }
+ else if (dt == superman::_static_type ())
+ {
+ superman&amp; s = static_cast&lt;superman&amp;> (p)
+ cerr &lt;&lt; s.name () &lt;&lt; ", ";
+
+ if (s.can_fly ())
+ cerr &lt;&lt; "flying ";
+
+ cerr &lt;&lt; "superman" &lt;&lt; endl;
+ }
+ else
+ {
+ cerr &lt;&lt; p.name () &lt;&lt; ", ordinary person" &lt;&lt; endl;
+ }
+}
+ </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/hybrid/</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>
+
+
<!-- Built-in XML Schema Type Parsers -->
diff --git a/documentation/cxx/parser/guide/index.xhtml b/documentation/cxx/parser/guide/index.xhtml
index 85b5092..ac69845 100644
--- a/documentation/cxx/parser/guide/index.xhtml
+++ b/documentation/cxx/parser/guide/index.xhtml
@@ -522,7 +522,7 @@
&lt;greeting>Hello&lt;/greeting>
&lt;name>sun&lt;/name>
- &lt;name>earth&lt;/name>
+ &lt;name>moon&lt;/name>
&lt;name>world&lt;/name>
&lt;/hello>
@@ -2322,7 +2322,7 @@ protected:
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
+ <code>xml_schema::document_pimpl</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.
diff --git a/documentation/cxx/serializer/guide/index.xhtml b/documentation/cxx/serializer/guide/index.xhtml
index 4deacf0..bd681cc 100644
--- a/documentation/cxx/serializer/guide/index.xhtml
+++ b/documentation/cxx/serializer/guide/index.xhtml
@@ -529,7 +529,7 @@
&lt;greeting>Hello&lt;/greeting>
&lt;name>sun&lt;/name>
- &lt;name>earth&lt;/name>
+ &lt;name>moon&lt;/name>
&lt;name>world&lt;/name>
&lt;/hello>
diff --git a/documentation/xsde.1 b/documentation/xsde.1
index f9fe998..62cc55d 100644
--- a/documentation/xsde.1
+++ b/documentation/xsde.1
@@ -1005,6 +1005,43 @@ Suppress the generation of parser and serializer reset code.
Reset support allows you to reuse parsers and serializers
after an error.
+.IP "\fB\--generate-polymorphic\fR"
+Generate polymorphism-aware code. Specify this option if you use substitution
+groups or
+.BR xsi:type .
+Use the
+.B --polymorphic-type
+option to specify which type hierarchies are polymorphic.
+
+.IP "\fB\--runtime-polymorphic\fR"
+Generate non-polymorphic code that uses the runtime library configured with
+polymorphism support.
+
+.IP "\fB\--polymorphic-type \fItype\fR"
+Indicate that
+.I type
+is a root of a polymorphic type hierarchy. The compiler can often
+automatically determine which types are polymorphic based on the
+substitution group declarations. However, you may need to use this
+option if you are not using substitution groups or if substitution
+groups are defined in another schema. You need to specify this option
+when compiling every schema file that references
+.IR type .
+
+.IP "\fB\--generate-typeinfo\fR"
+Generate custom type information querying functions for polymorphic
+object model types. These functions can be used instead of the standard
+C++ RTTI mechanism to determine object's type at runtime.
+
+.IP "\fB\--polymorphic-schema \fIfile\fR"
+Indicate that
+.I file
+contains derivations of polymorphic types that are not otherwise visible
+from the schema being compiled. This option is used to make sure that
+during the generation of parser and serializer aggregates the compiler
+is aware of all possible derivations of polymorphic types. Repeat this
+option to specify more than one schema file.
+
.IP "\fB\--reuse-style-mixin\fR"
Generate code that supports the mixin base parser/serializer
implementation reuse style. Note that this reuse style
diff --git a/documentation/xsde.xhtml b/documentation/xsde.xhtml
index 312d5f9..c8f602a 100644
--- a/documentation/xsde.xhtml
+++ b/documentation/xsde.xhtml
@@ -870,6 +870,39 @@
Reset support allows you to reuse parsers and serializers
after an error.</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>. Use the
+ <code><b>--polymorphic-type</b></code> option to specify which
+ type hierarchies are polymorphic.</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>--polymorphic-type</b></code> <i>type</i></dt>
+ <dd>Indicate that <code><i>type</i></code> is a root of a polymorphic
+ type hierarchy. The compiler can often automatically determine
+ which types are polymorphic based on the substitution group
+ declarations. However, you may need to use this option if you are
+ not using substitution groups or if substitution groups are defined
+ in another schema. You need to specify this option when compiling
+ every schema file that references <code><i>type</i></code>.</dd>
+
+ <dt><code><b>--generate-typeinfo</b></code></dt>
+ <dd>Generate custom type information querying functions for
+ polymorphic object model types. These functions can be used
+ instead of the standard C++ RTTI mechanism to determine
+ object's type at runtime.</dd>
+
+ <dt><code><b>--polymorphic-schema</b></code> <i>file</i></dt>
+ <dd>Indicate that <code><i>file</i></code> contains derivations of
+ polymorphic types that are not otherwise visible from the schema
+ being compiled. This option is used to make sure that during the
+ generation of parser and serializer aggregates the compiler is
+ aware of all possible derivations of polymorphic types. Repeat
+ this option to specify more than one schema file.</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
@@ -877,7 +910,6 @@
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
diff --git a/examples/cxx/hybrid/README b/examples/cxx/hybrid/README
index d23c10d..7d9312d 100644
--- a/examples/cxx/hybrid/README
+++ b/examples/cxx/hybrid/README
@@ -36,6 +36,14 @@ compositors
Shows how to create, access, and modify object models with complex
nested choice and sequence compositors.
+polymorphism
+ Shows how to handle XML vocabularies that use XML Schema polymorphism
+ features such as the xsi:type attribute and substitution groups.
+
+polyroot
+ Shows how to handle XML vocabularies with polymorphic document root
+ elements.
+
custom/
A collection of examples that show how to customize the C++/Hybrid
object model by using custom C++ classes instead of or in addition
diff --git a/examples/cxx/hybrid/binary/xdr/driver.cxx b/examples/cxx/hybrid/binary/xdr/driver.cxx
index e629849..d587817 100644
--- a/examples/cxx/hybrid/binary/xdr/driver.cxx
+++ b/examples/cxx/hybrid/binary/xdr/driver.cxx
@@ -10,7 +10,6 @@
#include <iostream>
#include "library.hxx"
-
#include "library-pimpl.hxx"
#include "library-simpl.hxx"
diff --git a/examples/cxx/hybrid/custom/wildcard/driver.cxx b/examples/cxx/hybrid/custom/wildcard/driver.cxx
index 02870fa..f5b05ee 100644
--- a/examples/cxx/hybrid/custom/wildcard/driver.cxx
+++ b/examples/cxx/hybrid/custom/wildcard/driver.cxx
@@ -7,7 +7,6 @@
#include <iostream>
#include "email.hxx"
-
#include "email-pimpl.hxx"
#include "email-simpl.hxx"
diff --git a/examples/cxx/hybrid/filter/driver.cxx b/examples/cxx/hybrid/filter/driver.cxx
index 9bc9f64..5c15cef 100644
--- a/examples/cxx/hybrid/filter/driver.cxx
+++ b/examples/cxx/hybrid/filter/driver.cxx
@@ -6,7 +6,6 @@
#include <iostream>
#include "people.hxx"
-
#include "people-pimpl.hxx"
#include "people-simpl.hxx"
diff --git a/examples/cxx/hybrid/library/driver.cxx b/examples/cxx/hybrid/library/driver.cxx
index 2bde50d..628831a 100644
--- a/examples/cxx/hybrid/library/driver.cxx
+++ b/examples/cxx/hybrid/library/driver.cxx
@@ -6,7 +6,6 @@
#include <iostream>
#include "library.hxx"
-
#include "library-pimpl.hxx"
#include "library-simpl.hxx"
diff --git a/examples/cxx/hybrid/makefile b/examples/cxx/hybrid/makefile
index 2defdc5..cc886ec 100644
--- a/examples/cxx/hybrid/makefile
+++ b/examples/cxx/hybrid/makefile
@@ -5,8 +5,8 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
-all_examples := binary compositors custom hello multiroot streaming \
-library wildcard filter minimal
+all_examples := binary compositors custom hello multiroot polymorphism \
+polyroot streaming library wildcard filter minimal
build_examples := binary compositors custom
@@ -19,6 +19,10 @@ ifeq ($(xsde_stl),y)
build_examples += library wildcard filter
endif
+ifeq ($(xsde_polymorphic),y)
+build_examples += polymorphism polyroot
+endif
+
endif
endif
diff --git a/examples/cxx/hybrid/minimal/driver.cxx b/examples/cxx/hybrid/minimal/driver.cxx
index e876b6f..e8e8312 100644
--- a/examples/cxx/hybrid/minimal/driver.cxx
+++ b/examples/cxx/hybrid/minimal/driver.cxx
@@ -5,7 +5,6 @@
#include <stdio.h>
#include "people.hxx"
-
#include "people-pimpl.hxx"
#include "people-simpl.hxx"
diff --git a/examples/cxx/hybrid/polymorphism/README b/examples/cxx/hybrid/polymorphism/README
new file mode 100644
index 0000000..2e00636
--- /dev/null
+++ b/examples/cxx/hybrid/polymorphism/README
@@ -0,0 +1,57 @@
+This example shows how to handle XML vocabularies that use the XML
+Schema polymorphism features such as the xsi:type attribute and
+substitution groups in the Embedded C++/Hybrid mapping. The case
+where xsi:type or substitution groups are used on document 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.hxx
+supermen.cxx
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+supermen-pimpl.hxx
+supermen-pimpl.cxx
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+supermen-pimpl.hxx
+supermen-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
+ supermen.xsd. The --generate-parser, --generate-serializer, and
+ --generate-aggregate options were used to request the generation
+ of the parsing and serialization code. The --generate-polymorphic
+ option was used to request the generation of the polymorphism-aware
+ code. Since our vocabulary uses substitution groups, the XSD/e
+ compiler is able to automatically determine which type hierarchy is
+ polymorphic (otherwise we would have had to use the --polymorphic-type
+ option). The --generate-typeinfo option was used to request the
+ generation of custom type information for polymorphic object model
+ types. Finally, the --root-element option was used to specify the
+ document root element.
+
+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 at which point it determines the actual
+ (dynamic) types of polymorphic objects. Finally, the driver modifies
+ the object model by adding another polymorphic instance and calls the
+ serializer to serialize it back to XML.
+
+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/hybrid/polymorphism/driver.cxx b/examples/cxx/hybrid/polymorphism/driver.cxx
new file mode 100644
index 0000000..926bb91
--- /dev/null
+++ b/examples/cxx/hybrid/polymorphism/driver.cxx
@@ -0,0 +1,202 @@
+// file : examples/cxx/hybrid/polymorphism/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#include "supermen.hxx"
+#include "supermen-pimpl.hxx"
+#include "supermen-simpl.hxx"
+
+using namespace std;
+
+void
+check_load (); // Defined after main().
+
+int
+main (int argc, char* argv[])
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ check_load ();
+#endif
+
+ const char* input;
+
+ if (argc < 2)
+ {
+ input = "STDIN";
+ cerr << "XML file not specified, reading from STDIN" << endl;
+ }
+ else
+ input = argv[1];
+
+ try
+ {
+ // Parse.
+ //
+ supermen_paggr supermen_p;
+
+ // The last argument to the document's constructor indicates that we
+ // are parsing polymorphic XML documents.
+ //
+ xml_schema::document_pimpl doc_p (
+ supermen_p.root_parser (),
+ supermen_p.root_name (),
+ true);
+
+ supermen_p.pre ();
+
+ if (argc < 2)
+ doc_p.parse (cin);
+ else
+ doc_p.parse (argv[1]);
+
+ auto_ptr<supermen> sm (supermen_p.post ());
+
+ // Print what we've got.
+ //
+ for (supermen::person_iterator i = sm->person ().begin ();
+ i != sm->person ().end ();
+ ++i)
+ {
+ person& p = *i;
+
+ // You can use the standard C++ RTTI or custom type information
+ // provided by the object model (--generate-typeinfo option) to
+ // detect the object's actual (dynamic) type.
+ //
+ if (p._dynamic_type () == batman::_static_type ())
+ {
+ batman& b = static_cast<batman&> (p);
+ cerr << b.name () << ", batman, wing span " << b.wing_span () << endl;
+ }
+ else if (superman* s = dynamic_cast<superman*> (&p))
+ {
+ cerr << s->name () << ", ";
+
+ if (s->can_fly ())
+ cerr << "flying ";
+
+ cerr << "superman" << endl;
+ }
+ else
+ {
+ cerr << p.name () << ", ordinary person" << endl;
+ }
+ }
+
+ // Add another superman entry.
+ //
+ auto_ptr<superman> s (new superman);
+#ifdef XSDE_STL
+ s->name ("Clark Kent");
+#else
+ s->name (xml_schema::strdupx ("Clark Kent"));
+#endif
+ s->can_fly (true);
+ sm->person ().push_back (s.release ());
+
+ // Serialize.
+ //
+ supermen_saggr supermen_s;
+
+ // The last argument to the document's constructor indicates that we
+ // are serializing polymorphic XML documents.
+ //
+ xml_schema::document_simpl doc_s (
+ supermen_s.root_serializer (),
+ supermen_s.root_name (),
+ true);
+
+ doc_s.add_no_namespace_schema ("supermen.xsd");
+
+ supermen_s.pre (*sm);
+ doc_s.serialize (cout);
+ supermen_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;
+}
+
+#ifndef NDEBUG
+// Check that the load in substitution and inheritance hashmaps is not
+// too high. See the C++/Parser and C++/Serializer Mappings Getting
+// Started Guides for details.
+//
+void
+check_load ()
+{
+ // Parser.
+ //
+ 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
+
+ // Serializer.
+ //
+ 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
diff --git a/examples/cxx/hybrid/polymorphism/makefile b/examples/cxx/hybrid/polymorphism/makefile
new file mode 100644
index 0000000..5a137eb
--- /dev/null
+++ b/examples/cxx/hybrid/polymorphism/makefile
@@ -0,0 +1,113 @@
+# file : examples/cxx/hybrid/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
+
+obj := $(addprefix $(out_base)/,\
+$(cxx:.cxx=.o) \
+$(xsd:.xsd=.o) \
+$(xsd:.xsd=-pskel.o) \
+$(xsd:.xsd=-pimpl.o) \
+$(xsd:.xsd=-sskel.o) \
+$(xsd:.xsd=-simpl.o))
+
+dep := $(obj:.o=.o.d)
+
+xsde.l := $(out_root)/libxsde/xsde/xsde.l
+xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options
+
+driver := $(out_base)/driver
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+clean := $(out_base)/.clean
+
+# Build.
+#
+$(driver): $(obj) $(xsde.l)
+
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \
+ $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \
+ $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \
+ $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \
+ $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx)
+
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): $(out_root)/xsde/xsde
+$(gen): xsde := $(out_root)/xsde/xsde
+$(gen): xsde_options += --generate-parser --generate-serializer \
+--generate-aggregate --generate-polymorphic --generate-typeinfo \
+--root-element supermen
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Dist.
+#
+dist-common := $(out_base)/.dist-common
+
+.PHONY: $(dist) $(dist-win) $(dist-common)
+
+$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base))
+
+$(dist-common):
+ $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx)
+ $(call install-data,$(src_base)/supermen.xsd,$(dist_prefix)/$(path)/supermen.xsd)
+ $(call install-data,$(src_base)/supermen.xml,$(dist_prefix)/$(path)/supermen.xml)
+
+$(dist): $(dist-common)
+ $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README)
+
+$(dist-win): $(dist-common)
+ $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt)
+ $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(gen): | $(out_base)/.gitignore
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver $(genf)
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(bld_root)/install.make)
+$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/hybrid/polymorphism/supermen.xml b/examples/cxx/hybrid/polymorphism/supermen.xml
new file mode 100644
index 0000000..bfc9e00
--- /dev/null
+++ b/examples/cxx/hybrid/polymorphism/supermen.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/polymorphism/supermen.xsd b/examples/cxx/hybrid/polymorphism/supermen.xsd
new file mode 100644
index 0000000..208d560
--- /dev/null
+++ b/examples/cxx/hybrid/polymorphism/supermen.xsd
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/polyroot/README b/examples/cxx/hybrid/polyroot/README
new file mode 100644
index 0000000..3d690f5
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/README
@@ -0,0 +1,60 @@
+This example shows how to handle XML vocabularies with polymorphic document
+root elements in the Embedded C++/Hybrid mapping. For general coverage of
+XML Schema polymorphism handling 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.hxx
+supermen.cxx
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+supermen-pimpl.hxx
+supermen-pimpl.cxx
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+supermen-pimpl.hxx
+supermen-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
+ supermen.xsd. The --generate-parser, --generate-serializer, and
+ --generate-aggregate options were used to request the generation
+ of the parsing and serialization code. The --generate-polymorphic
+ option was used to request the generation of the polymorphism-aware
+ code. Since our vocabulary uses substitution groups, the XSD/e
+ compiler is able to automatically determine which type hierarchy is
+ polymorphic (otherwise we would have had to use the --polymorphic-type
+ option). The --generate-typeinfo option was used to request the
+ generation of custom type information for polymorphic object model
+ types. Finally, the --root-element option was used to specify the
+ document root element.
+
+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 at which point it determines the actual
+ (dynamic) types of polymorphic objects. Finally, the driver calls the
+ serializer to serialize the object model back to XML.
+
+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/hybrid/polyroot/batman.xml b/examples/cxx/hybrid/polyroot/batman.xml
new file mode 100644
index 0000000..96248ff
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/batman.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/polyroot/driver.cxx b/examples/cxx/hybrid/polyroot/driver.cxx
new file mode 100644
index 0000000..f41422c
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/driver.cxx
@@ -0,0 +1,322 @@
+// file : examples/cxx/hybrid/polyroot/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#include "supermen.hxx"
+#include "supermen-pimpl.hxx"
+#include "supermen-simpl.hxx"
+
+using namespace std;
+using xml_schema::ro_string;
+
+// Customize the xml_schema::document object to handle a polymorphic
+// root element. For more information see the polyroot and multiroot
+// examples in the examples/cxx/parser/ directory.
+//
+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 (person_paggr& paggr)
+ : xml_schema::document_pimpl (person_paggr::root_name ()),
+ paggr_ (paggr),
+ parser_used_ (0)
+ {
+ }
+
+ person*
+ result ()
+ {
+ return result_.release ();
+ }
+
+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_paggr::root_name () ||
+ ns != person_paggr::root_namespace ())
+ {
+ // 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 for the parser. If type is 0 then there is no xsi:type and
+ // static type should be used.
+ //
+ if (type == 0)
+ parser_used_ = &paggr_.root_parser ();
+ else
+ {
+ // 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.
+ //
+ xml_schema::parser_base* p = paggr_.root_map ().find (type);
+
+#ifdef XSDE_REUSE_STYLE_MIXIN
+ parser_used_ = dynamic_cast<person_pskel*> (p);
+#else
+ parser_used_ = static_cast<person_pskel*> (p);
+#endif
+ }
+
+ if (parser_used_ != 0)
+ parser_used_->pre ();
+
+ return parser_used_;
+ }
+
+ // 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_ != 0)
+ result_.reset (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_ != 0)
+ parser_used_->_reset ();
+ }
+
+private:
+ person_paggr& paggr_;
+ person_pskel* parser_used_;
+ std::auto_ptr<person> result_;
+};
+
+void
+check_load (); // Defined after main().
+
+int
+main (int argc, char* argv[])
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ check_load ();
+#endif
+
+ const char* input;
+
+ if (argc < 2)
+ {
+ input = "STDIN";
+ cerr << "XML file not specified, reading from STDIN" << endl;
+ }
+ else
+ input = argv[1];
+
+ try
+ {
+ // Parse.
+ //
+ person_paggr person_p;
+
+ // Use our customized document parser. It automatically calls
+ // pre() and post() on the chosen parser and stores the result.
+ //
+ document_pimpl doc_p (person_p);
+
+ if (argc < 2)
+ doc_p.parse (cin);
+ else
+ doc_p.parse (argv[1]);
+
+ auto_ptr<person> p (doc_p.result ());
+
+ // Print what we've got. You can use the standard C++ RTTI or custom
+ // type information provided by the object model (--generate-typeinfo
+ // option) to detect the object's actual (dynamic) type.
+ //
+ if (p->_dynamic_type () == batman::_static_type ())
+ {
+ batman& b = static_cast<batman&> (*p);
+ cerr << b.name () << ", batman, wing span " << b.wing_span () << endl;
+ }
+ else if (superman* s = dynamic_cast<superman*> (p.get ()))
+ {
+ cerr << s->name () << ", ";
+
+ if (s->can_fly ())
+ cerr << "flying ";
+
+ cerr << "superman" << endl;
+ }
+ else
+ {
+ cerr << p->name () << ", ordinary person" << endl;
+ }
+
+ // Serialize.
+ //
+ person_saggr person_s;
+ person_sskel* ps = 0;
+
+ // Determine the root element serializer to use based on the object's
+ // dynamic type.
+ //
+ const string& dt = p->_dynamic_type ();
+
+ if (dt == person::_static_type ())
+ ps = &person_s.root_serializer ();
+ else
+ {
+ // The map returns a generic serializer_base which we will cast to
+ // person_sskel in order to call the pre() and post() callbacks. If
+ // the runtime and the generated code are built with the mixin
+ // serializer reuse style then we have to use dynamic_cast because
+ // of the virtual inheritance.
+ //
+ xml_schema::serializer_base* s =
+ person_s.root_map ().find (dt.c_str ());
+
+#ifdef XSDE_REUSE_STYLE_MIXIN
+ ps = dynamic_cast<person_sskel*> (s);
+#else
+ ps = static_cast<person_sskel*> (s);
+#endif
+ }
+
+ // Create a document serializer for this object. 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_s.root_name (), true, person_sskel::_static_type ());
+
+ doc_s.add_no_namespace_schema ("supermen.xsd");
+
+ ps->pre (*p);
+ doc_s.serialize (std::cout);
+ ps->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;
+}
+
+#ifndef NDEBUG
+// Check that the load in substitution and inheritance hashmaps is not
+// too high. See the C++/Parser and C++/Serializer Mappings Getting
+// Started Guides for details.
+//
+void
+check_load ()
+{
+ // Parser.
+ //
+ 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
+
+ // Serializer.
+ //
+ 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
diff --git a/examples/cxx/hybrid/polyroot/makefile b/examples/cxx/hybrid/polyroot/makefile
new file mode 100644
index 0000000..6bcc4ee
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/makefile
@@ -0,0 +1,115 @@
+# file : examples/cxx/hybrid/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
+
+obj := $(addprefix $(out_base)/,\
+$(cxx:.cxx=.o) \
+$(xsd:.xsd=.o) \
+$(xsd:.xsd=-pskel.o) \
+$(xsd:.xsd=-pimpl.o) \
+$(xsd:.xsd=-sskel.o) \
+$(xsd:.xsd=-simpl.o))
+
+dep := $(obj:.o=.o.d)
+
+xsde.l := $(out_root)/libxsde/xsde/xsde.l
+xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options
+
+driver := $(out_base)/driver
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+clean := $(out_base)/.clean
+
+# Build.
+#
+$(driver): $(obj) $(xsde.l)
+
+$(obj) $(dep): $(xsde.l.cpp-options)
+
+genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \
+ $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \
+ $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \
+ $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \
+ $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx)
+
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): $(out_root)/xsde/xsde
+$(gen): xsde := $(out_root)/xsde/xsde
+$(gen): xsde_options += --generate-parser --generate-serializer \
+--generate-aggregate --generate-polymorphic --generate-typeinfo \
+--root-element person
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Dist.
+#
+dist-common := $(out_base)/.dist-common
+
+.PHONY: $(dist) $(dist-win) $(dist-common)
+
+$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base))
+
+$(dist-common):
+ $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx)
+ $(call install-data,$(src_base)/supermen.xsd,$(dist_prefix)/$(path)/supermen.xsd)
+ $(call install-data,$(src_base)/person.xml,$(dist_prefix)/$(path)/person.xml)
+ $(call install-data,$(src_base)/superman.xml,$(dist_prefix)/$(path)/superman.xml)
+ $(call install-data,$(src_base)/batman.xml,$(dist_prefix)/$(path)/batman.xml)
+
+$(dist): $(dist-common)
+ $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README)
+
+$(dist-win): $(dist-common)
+ $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt)
+ $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(gen): | $(out_base)/.gitignore
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver $(genf)
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(bld_root)/install.make)
+$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make)
+
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsde/makefile)
+$(call import,$(src_root)/libxsde/xsde/makefile)
diff --git a/examples/cxx/hybrid/polyroot/person.xml b/examples/cxx/hybrid/polyroot/person.xml
new file mode 100644
index 0000000..c6ab1ff
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/person.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/polyroot/superman.xml b/examples/cxx/hybrid/polyroot/superman.xml
new file mode 100644
index 0000000..94a4f0b
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/superman.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/polyroot/supermen.xsd b/examples/cxx/hybrid/polyroot/supermen.xsd
new file mode 100644
index 0000000..9178168
--- /dev/null
+++ b/examples/cxx/hybrid/polyroot/supermen.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/hybrid/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/hybrid/streaming/driver.cxx b/examples/cxx/hybrid/streaming/driver.cxx
index ab2cd3a..86d0b87 100644
--- a/examples/cxx/hybrid/streaming/driver.cxx
+++ b/examples/cxx/hybrid/streaming/driver.cxx
@@ -5,7 +5,6 @@
#include <iostream>
#include "position.hxx"
-
#include "position-pimpl.hxx"
#include "position-simpl.hxx"
diff --git a/examples/cxx/hybrid/wildcard/driver.cxx b/examples/cxx/hybrid/wildcard/driver.cxx
index eea5bc7..69b6e67 100644
--- a/examples/cxx/hybrid/wildcard/driver.cxx
+++ b/examples/cxx/hybrid/wildcard/driver.cxx
@@ -8,7 +8,6 @@
#include "email.hxx"
#include "body.hxx"
-
#include "email-pimpl.hxx"
#include "email-simpl.hxx"
diff --git a/examples/cxx/parser/README b/examples/cxx/parser/README
index eaf9342..8afc5f9 100644
--- a/examples/cxx/parser/README
+++ b/examples/cxx/parser/README
@@ -1,7 +1,7 @@
-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.
+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
@@ -30,3 +30,11 @@ multiroot
mixed
Shows how to handle raw, "type-less content" such as mixed content
models, anyType/anySimpleType, and any/anyAttribute.
+
+polymorphism
+ Shows how to handle XML vocabularies that use XML Schema polymorphism
+ features such as the xsi:type attribute and substitution groups.
+
+polyroot
+ Shows how to handle XML vocabularies with polymorphic document root
+ elements.
diff --git a/examples/cxx/parser/polymorphism/README b/examples/cxx/parser/polymorphism/README
index 0b3d749..88140de 100644
--- a/examples/cxx/parser/polymorphism/README
+++ b/examples/cxx/parser/polymorphism/README
@@ -1,7 +1,7 @@
-This example shows how to handle XML Schema polymorphism features such
+This example shows how to handle the 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.
+mapping. The case where xsi:type or substitution groups are used on document
+root elements is covered in the polyroot examples.
The example consists of the following files:
diff --git a/examples/cxx/serializer/README b/examples/cxx/serializer/README
index fa71ea3..f65f6b8 100644
--- a/examples/cxx/serializer/README
+++ b/examples/cxx/serializer/README
@@ -1,7 +1,7 @@
-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.
+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
@@ -18,3 +18,11 @@ minimal
wildcard
Shows how to serialize XML data matched by XML Schema wildcards
(any and anyAttribute).
+
+polymorphism
+ Shows how to handle XML vocabularies that use XML Schema polymorphism
+ features such as the xsi:type attribute and substitution groups.
+
+polyroot
+ Shows how to handle XML vocabularies with polymorphic document root
+ elements.
diff --git a/examples/cxx/serializer/polymorphism/README b/examples/cxx/serializer/polymorphism/README
index 0e2c5b8..2d1ff6e 100644
--- a/examples/cxx/serializer/polymorphism/README
+++ b/examples/cxx/serializer/polymorphism/README
@@ -1,7 +1,7 @@
-This example shows how to handle XML Schema polymorphism features such as
+This example shows how to handle the 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.
+mapping. The case where xsi:type or substitution groups are used on document
+root elements is covered in the polyroot examples.
The example consists of the following files:
diff --git a/libxsde/xsde/cxx/hybrid/any-type.cxx b/libxsde/xsde/cxx/hybrid/any-type.cxx
new file mode 100644
index 0000000..b16356c
--- /dev/null
+++ b/libxsde/xsde/cxx/hybrid/any-type.cxx
@@ -0,0 +1,53 @@
+// file : xsde/cxx/hybrid/any-type.cxx
+// author : 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/any-type.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ // any_type
+ //
+#ifdef XSDE_POLYMORPHIC
+ any_type::
+ ~any_type ()
+ {
+ }
+
+#ifdef XSDE_STL
+ const std::string& any_type::
+ _dynamic_type () const
+ {
+ return _static_type ();
+ }
+
+ static const std::string any_type_static_type_ =
+ "anyType http://www.w3.org/2001/XMLSchema";
+
+ const std::string& any_type::
+ _static_type ()
+ {
+ return any_type_static_type_;
+ }
+#else
+ const char* any_type::
+ _dynamic_type () const
+ {
+ return _static_type ();
+ }
+
+ const char* any_type::
+ _static_type ()
+ {
+ return "anyType http://www.w3.org/2001/XMLSchema";
+ }
+#endif
+#endif
+ }
+ }
+}
diff --git a/libxsde/xsde/cxx/hybrid/any-type.hxx b/libxsde/xsde/cxx/hybrid/any-type.hxx
index db512c2..f94f007 100644
--- a/libxsde/xsde/cxx/hybrid/any-type.hxx
+++ b/libxsde/xsde/cxx/hybrid/any-type.hxx
@@ -6,6 +6,14 @@
#ifndef XSDE_CXX_HYBRID_ANY_TYPE_HXX
#define XSDE_CXX_HYBRID_ANY_TYPE_HXX
+#include <xsde/cxx/config.hxx>
+
+/*
+#ifdef XSDE_STL
+# include <string>
+#endif
+*/
+
namespace xsde
{
namespace cxx
@@ -14,6 +22,26 @@ namespace xsde
{
struct any_type
{
+ /*
+#ifdef XSDE_POLYMORPHIC
+ virtual
+ ~any_type ();
+
+#ifdef XSDE_STL
+ virtual const std::string&
+ _dynamic_type () const;
+
+ static const std::string&
+ _static_type ();
+#else
+ virtual const char*
+ _dynamic_type () const;
+
+ static const char*
+ _static_type ();
+#endif
+#endif
+ */
};
struct any_simple_type
diff --git a/libxsde/xsde/cxx/hybrid/parser-map.cxx b/libxsde/xsde/cxx/hybrid/parser-map.cxx
new file mode 100644
index 0000000..c19325c
--- /dev/null
+++ b/libxsde/xsde/cxx/hybrid/parser-map.cxx
@@ -0,0 +1,59 @@
+// file : xsde/cxx/hybrid/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 <string.h> // strcmp
+
+#include <xsde/cxx/hybrid/parser-map.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ parser::parser_base* parser_map_impl::
+ find (const char* tid) const
+ {
+ // Binary search.
+ //
+ if (size_ == 0)
+ return 0;
+
+ size_t l = 0;
+ size_t h = size_ - 1;
+
+ while (l <= h)
+ {
+ size_t m = l + (h - l)/2;
+ int r = strcmp (entries_[m].type_id, tid);
+
+ if (r > 0)
+ h = m - 1;
+ else if (r < 0)
+ l = m + 1;
+ else
+ return entries_[m].parser;
+ }
+
+ return 0;
+ }
+
+ void parser_map_impl::
+ reset () const
+ {
+ if (resetting_)
+ return;
+
+ bool& r = const_cast<bool&> (resetting_);
+ r = true;
+
+ for (const entry* p = entries_; p != entries_ + size_; ++p)
+ p->parser->_reset ();
+
+ r = false;
+ }
+ }
+ }
+}
diff --git a/libxsde/xsde/cxx/hybrid/parser-map.hxx b/libxsde/xsde/cxx/hybrid/parser-map.hxx
new file mode 100644
index 0000000..df84f22
--- /dev/null
+++ b/libxsde/xsde/cxx/hybrid/parser-map.hxx
@@ -0,0 +1,52 @@
+// file : xsde/cxx/hybrid/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_HYBRID_PARSER_MAP_HXX
+#define XSDE_CXX_HYBRID_PARSER_MAP_HXX
+
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/parser/map.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ class parser_map_impl: public parser::parser_map
+ {
+ public:
+ struct entry
+ {
+ const char* type_id;
+ parser::parser_base* parser;
+ };
+
+ parser_map_impl (entry* entries, size_t size)
+ : entries_ (entries), size_ (size), resetting_ (false)
+ {
+ }
+
+ virtual parser::parser_base*
+ find (const char* type_id) const;
+
+ virtual void
+ reset () const;
+
+ private:
+ parser_map_impl (const parser_map_impl&);
+ parser_map_impl& operator= (const parser_map_impl&);
+
+ private:
+ entry* entries_;
+ size_t size_;
+ bool resetting_;
+ };
+ }
+ }
+}
+
+#endif // XSDE_CXX_HYBRID_PARSER_MAP_HXX
diff --git a/libxsde/xsde/cxx/hybrid/serializer-map.cxx b/libxsde/xsde/cxx/hybrid/serializer-map.cxx
new file mode 100644
index 0000000..7fce5fd
--- /dev/null
+++ b/libxsde/xsde/cxx/hybrid/serializer-map.cxx
@@ -0,0 +1,61 @@
+// file : xsde/cxx/hybrid/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 <string.h> // strcmp
+
+#include <xsde/cxx/hybrid/serializer-map.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ serializer::serializer_base* serializer_map_impl::
+ find (const void* v) const
+ {
+ const char* tid = static_cast<const char*> (v);
+
+ // Binary search.
+ //
+ if (size_ == 0)
+ return 0;
+
+ size_t l = 0;
+ size_t h = size_ - 1;
+
+ while (l <= h)
+ {
+ size_t m = l + (h - l)/2;
+ int r = strcmp (entries_[m].type_id, tid);
+
+ if (r > 0)
+ h = m - 1;
+ else if (r < 0)
+ l = m + 1;
+ else
+ return entries_[m].serializer;
+ }
+
+ return 0;
+ }
+
+ void serializer_map_impl::
+ reset () const
+ {
+ if (resetting_)
+ return;
+
+ bool& r = const_cast<bool&> (resetting_);
+ r = true;
+
+ for (const entry* p = entries_; p != entries_ + size_; ++p)
+ p->serializer->_reset ();
+
+ r = false;
+ }
+ }
+ }
+}
diff --git a/libxsde/xsde/cxx/hybrid/serializer-map.hxx b/libxsde/xsde/cxx/hybrid/serializer-map.hxx
new file mode 100644
index 0000000..5e3fb1a
--- /dev/null
+++ b/libxsde/xsde/cxx/hybrid/serializer-map.hxx
@@ -0,0 +1,52 @@
+// file : xsde/cxx/hybrid/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_HYBRID_SERIALIZER_MAP_HXX
+#define XSDE_CXX_HYBRID_SERIALIZER_MAP_HXX
+
+#include <stddef.h> // size_t
+
+#include <xsde/cxx/serializer/map.hxx>
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace hybrid
+ {
+ class serializer_map_impl: public serializer::serializer_map
+ {
+ public:
+ struct entry
+ {
+ const char* type_id;
+ serializer::serializer_base* serializer;
+ };
+
+ serializer_map_impl (entry* entries, size_t size)
+ : entries_ (entries), size_ (size), resetting_ (true)
+ {
+ }
+
+ virtual serializer::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:
+ entry* entries_;
+ size_t size_;
+ bool resetting_;
+ };
+ }
+ }
+}
+
+#endif // XSDE_CXX_HYBRID_SERIALIZER_MAP_HXX
diff --git a/libxsde/xsde/cxx/parser/map.cxx b/libxsde/xsde/cxx/parser/map.cxx
index b21c41e..1382c8d 100644
--- a/libxsde/xsde/cxx/parser/map.cxx
+++ b/libxsde/xsde/cxx/parser/map.cxx
@@ -23,12 +23,20 @@ namespace xsde
void parser_map_impl::
reset () const
{
+ if (resetting_)
+ return;
+
+ bool& r = const_cast<bool&> (resetting_);
+ r = true;
+
for (hashmap::const_iterator i (map_.begin ()), e (map_.end ());
i != e; ++i)
{
parser_base* p = *static_cast<parser_base* const*> (*i);
p->_reset ();
}
+
+ r = false;
}
}
}
diff --git a/libxsde/xsde/cxx/parser/map.hxx b/libxsde/xsde/cxx/parser/map.hxx
index 400de27..0a5c99c 100644
--- a/libxsde/xsde/cxx/parser/map.hxx
+++ b/libxsde/xsde/cxx/parser/map.hxx
@@ -77,6 +77,7 @@ namespace xsde
private:
hashmap map_;
+ bool resetting_;
};
}
}
diff --git a/libxsde/xsde/cxx/parser/map.ixx b/libxsde/xsde/cxx/parser/map.ixx
index 3a1f931..0f5e477 100644
--- a/libxsde/xsde/cxx/parser/map.ixx
+++ b/libxsde/xsde/cxx/parser/map.ixx
@@ -19,7 +19,7 @@ namespace xsde
inline parser_map_impl::
parser_map_impl (size_t buckets)
- : map_ (buckets, sizeof (parser_base*))
+ : map_ (buckets, sizeof (parser_base*)), resetting_ (false)
{
}
diff --git a/libxsde/xsde/cxx/serializer/map.cxx b/libxsde/xsde/cxx/serializer/map.cxx
index 1ace4ac..f3c88f6 100644
--- a/libxsde/xsde/cxx/serializer/map.cxx
+++ b/libxsde/xsde/cxx/serializer/map.cxx
@@ -23,12 +23,20 @@ namespace xsde
void serializer_map_impl::
reset () const
{
+ if (resetting_)
+ return;
+
+ bool& r = const_cast<bool&> (resetting_);
+ r = true;
+
for (hashmap::const_iterator i (map_.begin ()), e (map_.end ());
i != e; ++i)
{
serializer_base* s = *static_cast<serializer_base* const*> (*i);
s->_reset ();
}
+
+ r = false;
}
}
}
diff --git a/libxsde/xsde/cxx/serializer/map.hxx b/libxsde/xsde/cxx/serializer/map.hxx
index 2cfc755..1fe4eb0 100644
--- a/libxsde/xsde/cxx/serializer/map.hxx
+++ b/libxsde/xsde/cxx/serializer/map.hxx
@@ -86,6 +86,7 @@ namespace xsde
private:
hashmap map_;
+ bool resetting_;
};
}
}
diff --git a/libxsde/xsde/cxx/serializer/map.ixx b/libxsde/xsde/cxx/serializer/map.ixx
index 64eb19a..e1c2a28 100644
--- a/libxsde/xsde/cxx/serializer/map.ixx
+++ b/libxsde/xsde/cxx/serializer/map.ixx
@@ -19,7 +19,7 @@ namespace xsde
inline serializer_map_impl::
serializer_map_impl (size_t buckets)
- : map_ (buckets, sizeof (serializer_base*))
+ : map_ (buckets, sizeof (serializer_base*)), resetting_ (false)
{
}
diff --git a/libxsde/xsde/makefile b/libxsde/xsde/makefile
index f7d17ed..64368d0 100644
--- a/libxsde/xsde/makefile
+++ b/libxsde/xsde/makefile
@@ -45,6 +45,12 @@ endif
##
cxx_tun += cxx/hybrid/sequence.cxx
+ifeq ($(xsde_polymorphic),y)
+cxx_tun += \
+cxx/hybrid/parser-map.cxx \
+cxx/hybrid/serializer-map.cxx
+endif
+
ifeq ($(xsde_cdr),y)
cxx_tun += \
cxx/hybrid/cdr/exceptions.cxx \
diff --git a/tests/cxx/hybrid/makefile b/tests/cxx/hybrid/makefile
index 2ea9a3d..24ed1f0 100644
--- a/tests/cxx/hybrid/makefile
+++ b/tests/cxx/hybrid/makefile
@@ -5,7 +5,7 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
-tests := sequences
+tests := polymorphism sequences
ifeq ($(xsde_iostream),y)
tests += built-in list recursive test-template union
diff --git a/tests/cxx/hybrid/polymorphism/any-type/driver.cxx b/tests/cxx/hybrid/polymorphism/any-type/driver.cxx
new file mode 100644
index 0000000..555c145
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/any-type/driver.cxx
@@ -0,0 +1,59 @@
+// file : tests/cxx/hybrid/polymorphism/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 polymorphic parsing and serialization of anyType-based hierarchy.
+//
+
+#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 (),
+ true);
+
+ 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 (),
+ true);
+
+ doc_s.add_prefix ("t", "test");
+ doc_s.add_prefix ("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+
+ root_s.pre (*r);
+ doc_s.serialize (cout);
+ root_s.post ();
+
+ delete r;
+}
diff --git a/tests/cxx/hybrid/polymorphism/any-type/makefile b/tests/cxx/hybrid/polymorphism/any-type/makefile
new file mode 100644
index 0000000..57d58f6
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/any-type/makefile
@@ -0,0 +1,99 @@
+# file : tests/cxx/hybrid/polymorphism/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
+
+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)
+
+genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \
+ $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \
+ $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \
+ $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \
+ $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx)
+
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): $(out_root)/xsde/xsde
+$(gen): xsde := $(out_root)/xsde/xsde
+$(gen): xsde_options += --generate-parser --generate-serializer \
+--generate-aggregate --generate-polymorphic --generate-typeinfo \
+--root-element root --polymorphic-type anyType
+
+$(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))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(gen): | $(out_base)/.gitignore
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver $(genf)
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(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/polymorphism/any-type/test.xml b/tests/cxx/hybrid/polymorphism/any-type/test.xml
new file mode 100644
index 0000000..f0a8bcb
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/any-type/test.xml
@@ -0,0 +1,7 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <t:any><x>abc</x>junk<y>123</y></t:any>
+ <t:base ><a>123</a><b>abc</b></t:base>
+ <t:any xsi:type="t:derived"><a>123</a><b>abc</b><c>9</c><c>8</c><c>7</c></t:any>
+
+</t:root>
diff --git a/tests/cxx/hybrid/polymorphism/any-type/test.xsd b/tests/cxx/hybrid/polymorphism/any-type/test.xsd
new file mode 100644
index 0000000..33b5251
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/any-type/test.xsd
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <element name="any" type="anyType"/>
+
+ <complexType name="base">
+ <complexContent>
+ <restriction base="anyType">
+ <sequence>
+ <element name="a" type="int"/>
+ <element name="b" type="string"/>
+ </sequence>
+ </restriction>
+ </complexContent>
+ </complexType>
+
+ <element name="base" type="t:base" substitutionGroup="t:any"/>
+
+ <complexType name="derived">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="c" type="int" maxOccurs="unbounded"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element ref="t:any" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
diff --git a/tests/cxx/hybrid/polymorphism/makefile b/tests/cxx/hybrid/polymorphism/makefile
new file mode 100644
index 0000000..921ceae
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/makefile
@@ -0,0 +1,24 @@
+# file : tests/cxx/hybrid/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
+
+tests :=
+
+ifeq ($(xsde_iostream),y)
+tests += multischema
+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/polymorphism/multischema/driver.cxx b/tests/cxx/hybrid/polymorphism/multischema/driver.cxx
new file mode 100644
index 0000000..895d600
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/driver.cxx
@@ -0,0 +1,60 @@
+// file : tests/cxx/hybrid/polymorphism/multischema/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 polymorphic parsing and serialization with the type hierarchy
+// split into several schemas.
+//
+
+#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 (),
+ true);
+
+ 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 (),
+ true);
+
+ doc_s.add_prefix ("t", "test");
+ doc_s.add_prefix ("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+
+ root_s.pre (*r);
+ doc_s.serialize (cout);
+ root_s.post ();
+
+ delete r;
+}
diff --git a/tests/cxx/hybrid/polymorphism/multischema/makefile b/tests/cxx/hybrid/polymorphism/multischema/makefile
new file mode 100644
index 0000000..c0db0f2
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/makefile
@@ -0,0 +1,100 @@
+# file : tests/cxx/hybrid/polymorphism/multischema/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 type.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)
+
+genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \
+ $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \
+ $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \
+ $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \
+ $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx)
+
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): $(out_root)/xsde/xsde
+$(gen): xsde := $(out_root)/xsde/xsde
+$(gen): xsde_options += --generate-parser --generate-serializer \
+--generate-aggregate --generate-polymorphic --generate-typeinfo \
+--polymorphic-type base --polymorphic-schema $(src_base)/type.xsd \
+--include-regex '%.*/([^/]*)%$$$$1%'
+
+$(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))
+
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(gen): | $(out_base)/.gitignore
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver $(genf)
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(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/polymorphism/multischema/output b/tests/cxx/hybrid/polymorphism/multischema/output
new file mode 100644
index 0000000..341775b
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/output
@@ -0,0 +1 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><x xsi:type="t:foo"><a>abc</a><b>123</b></x><x xsi:type="t:bar"><a>abc</a><b>true</b></x><x xsi:type="t:baz"><a>abc</a><b>123</b><c>true</c></x></t:root> \ No newline at end of file
diff --git a/tests/cxx/hybrid/polymorphism/multischema/test.xml b/tests/cxx/hybrid/polymorphism/multischema/test.xml
new file mode 100644
index 0000000..d6e3e43
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/test.xml
@@ -0,0 +1,7 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <x xsi:type="t:foo"><a>abc</a><b>123</b></x>
+ <x xsi:type="t:bar"><a>abc</a><b>true</b></x>
+ <x xsi:type="t:baz"><a>abc</a><b>123</b><c>true</c></x>
+
+</t:root>
diff --git a/tests/cxx/hybrid/polymorphism/multischema/test.xsd b/tests/cxx/hybrid/polymorphism/multischema/test.xsd
new file mode 100644
index 0000000..ed5a666
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/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="base">
+ <sequence>
+ <element name="a" type="string"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="foo">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="int"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="x" type="t:base" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
diff --git a/tests/cxx/hybrid/polymorphism/multischema/type.xsd b/tests/cxx/hybrid/polymorphism/multischema/type.xsd
new file mode 100644
index 0000000..cb93000
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/multischema/type.xsd
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <include schemaLocation="test.xsd"/>
+
+ <complexType name="bar">
+ <complexContent>
+ <extension base="t:base">
+ <sequence>
+ <element name="b" type="boolean"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="baz">
+ <complexContent>
+ <extension base="t:foo">
+ <sequence>
+ <element name="c" type="boolean"/>
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+</schema>
diff --git a/xsde/cxx/elements.cxx b/xsde/cxx/elements.cxx
index 6116856..79fd6c5 100644
--- a/xsde/cxx/elements.cxx
+++ b/xsde/cxx/elements.cxx
@@ -194,8 +194,15 @@ namespace CXX
if (schema.used ())
{
+ // Here we need to detect a special multi-schema compilation
+ // case where the root schemas are imported into a special
+ // schema that doesn't have a namespace.
+ //
SemanticGraph::Uses& u (*schema.used_begin ());
- path = u.path ();
+ SemanticGraph::Schema& s (u.user ());
+
+ if (s.names_begin () != s.names_end ())
+ path = u.path ();
}
String pair;
diff --git a/xsde/cxx/hybrid/aggregate-elements.hxx b/xsde/cxx/hybrid/aggregate-elements.hxx
new file mode 100644
index 0000000..aa4c504
--- /dev/null
+++ b/xsde/cxx/hybrid/aggregate-elements.hxx
@@ -0,0 +1,31 @@
+// file : xsde/cxx/hybrid/aggregate-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_AGGREGATE_ELEMENTS_HXX
+#define CXX_HYBRID_AGGREGATE_ELEMENTS_HXX
+
+#include <cult/containers/map.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ struct InstanceInfo
+ {
+ SemanticGraph::Type* type;
+ String name;
+ };
+
+ typedef Cult::Containers::Map<String, InstanceInfo> TypeIdInstanceMap;
+ }
+}
+
+#endif // CXX_HYBRID_AGGREGATE_ELEMENTS_HXX
diff --git a/xsde/cxx/hybrid/aggregate-include.hxx b/xsde/cxx/hybrid/aggregate-include.hxx
new file mode 100644
index 0000000..9bd50bb
--- /dev/null
+++ b/xsde/cxx/hybrid/aggregate-include.hxx
@@ -0,0 +1,223 @@
+// file : xsde/cxx/hybrid/aggregate-include.hxx
+// author : 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_AGGREGATE_INCLUDE_HXX
+#define CXX_HYBRID_AGGREGATE_INCLUDE_HXX
+
+#include <cult/containers/set.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ // Parser/serializer implementation includes for additional
+ // schemas (polymorphic code).
+ //
+
+ // For base types we only want member's types, but not the
+ // base itself.
+ //
+ struct BaseInclude: Traversal::Complex, Context
+ {
+ BaseInclude (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ };
+
+ struct TypeInclude: Traversal::Type,
+ Traversal::Complex,
+ Context
+ {
+ TypeInclude (Context& c)
+ : Context (c), 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 (types_.find (&t) != types_.end ())
+ return;
+
+ types_.insert (&t);
+
+ if (polymorphic (t))
+ collect (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (types_.find (&c) != types_.end ())
+ return;
+
+ types_.insert (&c);
+
+ if (polymorphic (c))
+ collect (c);
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+
+ private:
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+ emit (d);
+ dispatch (d);
+ collect (d);
+ }
+ }
+
+ virtual Void
+ emit (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Schema;
+
+ Schema* s (&dynamic_cast<Schema&> (t.scope ().scope ()));
+
+ // If this is not a top-level schema, get one that
+ // includes/import/sources this schema. Top-level schema
+ // is either not used by any other schema or is imported
+ // into a special schema that doesn't have a namespace.
+ //
+ for (;;)
+ {
+ if (!s->used ())
+ break;
+
+ SemanticGraph::Uses& u (*s->used_begin ());
+ Schema& us (u.user ());
+
+ if (us.names_begin () == us.names_end ())
+ break;
+
+ s = &us;
+ }
+
+
+ if (s != &schema_root && schemas_.find (s) == schemas_.end ())
+ {
+ schemas_.insert (s);
+
+ SemanticGraph::Path path (s->used_begin ()->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 (hxx_expr->merge (path_str));
+ os << "#include " << process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+
+ private:
+ Cult::Containers::Set<SemanticGraph::Type*> types_;
+ Cult::Containers::Set<SemanticGraph::Schema*> schemas_;
+
+ BaseInclude 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 AggregateInclude: Traversal::Type,
+ Traversal::Element,
+ Context
+ {
+ AggregateInclude (Context& c, Char const* key)
+ : Context (c), key_ (key), type_include_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (t.context ().count (key_))
+ type_include_.dispatch (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.context ().count (key_))
+ type_include_.dispatch (e.type ());
+ }
+
+ private:
+ Char const* key_;
+ TypeInclude type_include_;
+ };
+ }
+}
+
+#endif // CXX_HYBRID_AGGREGATE_INCLUDE_HXX
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx
index 0d1ec70..80b91bc 100644
--- a/xsde/cxx/hybrid/cli.hxx
+++ b/xsde/cxx/hybrid/cli.hxx
@@ -41,6 +41,11 @@ namespace CXX
extern Key generate_xml_schema;
extern Key extern_xml_schema;
extern Key suppress_reset;
+ extern Key generate_polymorphic;
+ extern Key runtime_polymorphic;
+ extern Key polymorphic_type;
+ extern Key generate_typeinfo;
+ extern Key polymorphic_schema;
extern Key reuse_style_mixin;
extern Key custom_data;
extern Key custom_type;
@@ -123,6 +128,11 @@ namespace CXX
generate_xml_schema, Boolean,
extern_xml_schema, NarrowString,
suppress_reset, Boolean,
+ generate_polymorphic, Boolean,
+ runtime_polymorphic, Boolean,
+ polymorphic_type, Cult::Containers::Vector<NarrowString>,
+ generate_typeinfo, Boolean,
+ polymorphic_schema, Cult::Containers::Vector<NarrowString>,
reuse_style_mixin, Boolean,
custom_data, Cult::Containers::Vector<NarrowString>,
custom_type, Cult::Containers::Vector<NarrowString>,
diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx
index 80dc5c4..4edbc06 100644
--- a/xsde/cxx/hybrid/elements.cxx
+++ b/xsde/cxx/hybrid/elements.cxx
@@ -33,8 +33,7 @@ namespace CXX
options (ops),
exceptions (!ops.value<CLI::no_exceptions> ()),
stl (!ops.value<CLI::no_stl> ()),
- poly_code (false),
- poly_runtime (false),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
reset (!ops.value<CLI::suppress_reset> ()),
detach (ops.value<CLI::generate_detach> ()),
mixin (ops.value<CLI::reuse_style_mixin> ()),
@@ -55,6 +54,10 @@ namespace CXX
ixdrstream (ixdrstream_),
oxdrstream (oxdrstream_)
{
+ typeinfo = poly_code &&
+ (ops.value<CLI::generate_typeinfo> () ||
+ ops.value<CLI::generate_serializer> ());
+
String xs_ns (xs_ns_name ());
string_type = L"::xsde::cxx::ro_string";
diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx
index 7f3ba3a..8452976 100644
--- a/xsde/cxx/hybrid/elements.hxx
+++ b/xsde/cxx/hybrid/elements.hxx
@@ -42,9 +42,9 @@ namespace CXX
exceptions (c.exceptions),
stl (c.stl),
poly_code (c.poly_code),
- poly_runtime (c.poly_runtime),
reset (c.reset),
detach (c.detach),
+ typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
fwd_expr (c.fwd_expr),
@@ -71,9 +71,9 @@ namespace CXX
exceptions (c.exceptions),
stl (c.stl),
poly_code (c.poly_code),
- poly_runtime (c.poly_runtime),
reset (c.reset),
detach (c.detach),
+ typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
fwd_expr (c.fwd_expr),
@@ -534,6 +534,12 @@ namespace CXX
return t.context ().count ("recursive");
}
+ Boolean
+ polymorphic (SemanticGraph::Type& t)
+ {
+ return t.context ().count ("polymorphic");
+ }
+
public:
String
istream (NarrowString const& is) const;
@@ -559,9 +565,9 @@ namespace CXX
Boolean exceptions;
Boolean stl;
Boolean poly_code;
- Boolean poly_runtime;
Boolean reset;
Boolean detach;
+ Boolean typeinfo;
Boolean mixin;
Boolean tiein;
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
index 14afad6..3eba4ba 100644
--- a/xsde/cxx/hybrid/generator.cxx
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -129,6 +129,11 @@ namespace CXX
extern Key generate_xml_schema = "generate-xml-schema";
extern Key extern_xml_schema = "extern-xml-schema";
extern Key suppress_reset = "suppress-reset";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key runtime_polymorphic = "runtime-polymorphic";
+ extern Key polymorphic_type = "polymorphic-type";
+ extern Key generate_typeinfo = "generate-typeinfo";
+ extern Key polymorphic_schema = "polymorphic-schema";
extern Key reuse_style_mixin = "reuse-style-mixin";
extern Key custom_data = "custom-data";
extern Key custom_type = "custom-type";
@@ -285,6 +290,32 @@ namespace CXX
<< " reset 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 << "--polymorphic-type <type>" << endl
+ << " Indicate that <type> is a root of a polymorphic\n"
+ << " type hierarchy."
+ << endl;
+
+ e << "--generate-typeinfo" << endl
+ << " Generate type information functions for\n"
+ << " polymorphic object model types."
+ << endl;
+
+ e << "--polymorphic-schema <file>" << endl
+ << " Indicate that <file> contains derivations of\n"
+ << " polymorphic types."
+ << endl;
+
e << "--reuse-style-mixin" << endl
<< " Generate code that supports the mixin base\n"
<< " parser/serializer implementation reuse style."
@@ -783,6 +814,8 @@ namespace CXX
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::generate_polymorphic> () = h.value<H::generate_polymorphic> ();
+ r->value<P::runtime_polymorphic> () = h.value<H::runtime_polymorphic> ();
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> ();
@@ -862,6 +895,8 @@ namespace CXX
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::generate_polymorphic> () = h.value<H::generate_polymorphic> ();
+ r->value<S::runtime_polymorphic> () = h.value<H::runtime_polymorphic> ();
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> ();
@@ -924,16 +959,44 @@ namespace CXX
Void Hybrid::Generator::
calculate_size (CLI::Options const& ops,
XSDFrontend::SemanticGraph::Schema& schema,
- XSDFrontend::SemanticGraph::Path const& file)
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings)
{
// Determine which types are fixed/variable-sized.
//
TreeSizeProcessor proc;
- if (!proc.process (ops, schema, file))
+ if (!proc.process (ops, schema, file, disabled_warnings))
throw Failed ();
}
+ Void Hybrid::Generator::
+ process_tree_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ TreeNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
+ Void Hybrid::Generator::
+ process_parser_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ ParserNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
+ Void Hybrid::Generator::
+ process_serializer_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ SerializerNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
namespace
{
template <typename S>
@@ -1095,7 +1158,7 @@ namespace CXX
//
{
TreeNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
// Generate code.
@@ -1819,7 +1882,7 @@ namespace CXX
//
{
ParserNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
NarrowString name (file_path.leaf ());
@@ -1976,6 +2039,8 @@ namespace CXX
guard_prefix += '_';
+ Boolean aggr (ops.value<CLI::generate_aggregate> ());
+
// HXX
//
{
@@ -2012,6 +2077,14 @@ namespace CXX
hxx << "#include <xsde/cxx/pre.hxx>" << endl
<< endl;
+ // Define omit aggregate macro.
+ //
+ hxx << "#ifndef XSDE_OMIT_PAGGR" << endl
+ << "# define XSDE_OMIT_PAGGR" << endl
+ << "# define " << guard << "_CLEAR_OMIT_PAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
// Set auto-indentation.
//
Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
@@ -2021,9 +2094,24 @@ namespace CXX
generate_parser_header (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ // Clear omit aggregate macro.
+ //
+ hxx << "#ifdef " << guard << "_CLEAR_OMIT_PAGGR" << endl
+ << "# undef XSDE_OMIT_PAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
+ if (aggr)
+ {
+ hxx << "#ifndef XSDE_OMIT_PAGGR" << endl
+ << endl;
+
generate_parser_aggregate_header (ctx);
+ hxx << "#endif // XSDE_OMIT_PAGGR" << endl
+ << endl;
+ }
+
hxx << "#include <xsde/cxx/post.hxx>" << endl
<< endl;
}
@@ -2090,7 +2178,7 @@ namespace CXX
generate_parser_source (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ if (aggr)
generate_parser_aggregate_source (ctx);
}
@@ -2198,7 +2286,7 @@ namespace CXX
//
{
SerializerNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
NarrowString name (file_path.leaf ());
@@ -2342,6 +2430,7 @@ namespace CXX
if (guard_prefix)
guard_prefix += '_';
+ Boolean aggr (ops.value<CLI::generate_aggregate> ());
// HXX
//
@@ -2379,6 +2468,14 @@ namespace CXX
hxx << "#include <xsde/cxx/pre.hxx>" << endl
<< endl;
+ // Define omit aggregate macro.
+ //
+ hxx << "#ifndef XSDE_OMIT_SAGGR" << endl
+ << "# define XSDE_OMIT_SAGGR" << endl
+ << "# define " << guard << "_CLEAR_OMIT_SAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
// Set auto-indentation.
//
Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
@@ -2388,9 +2485,24 @@ namespace CXX
generate_serializer_header (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ // Clear omit aggregate macro.
+ //
+ hxx << "#ifdef " << guard << "_CLEAR_OMIT_SAGGR" << endl
+ << "# undef XSDE_OMIT_SAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
+ if (aggr)
+ {
+ hxx << "#ifndef XSDE_OMIT_SAGGR" << endl
+ << endl;
+
generate_serializer_aggregate_header (ctx);
+ hxx << "#endif // XSDE_OMIT_SAGGR" << endl
+ << endl;
+ }
+
hxx << "#include <xsde/cxx/post.hxx>" << endl
<< endl;
}
@@ -2457,7 +2569,7 @@ namespace CXX
generate_serializer_source (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ if (aggr)
generate_serializer_aggregate_source (ctx);
}
diff --git a/xsde/cxx/hybrid/generator.hxx b/xsde/cxx/hybrid/generator.hxx
index ff29750..6f506b2 100644
--- a/xsde/cxx/hybrid/generator.hxx
+++ b/xsde/cxx/hybrid/generator.hxx
@@ -44,42 +44,67 @@ namespace CXX
static Serializer::CLI::Options*
serializer_options (CLI::Options const&);
- struct Failed {};
-
+ // Calculate type sizes.
+ //
static Void
calculate_size (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings);
+
+ // Assign names to global declarations.
+ //
+ static Void
+ process_tree_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ static Void
+ process_parser_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ static Void
+ process_serializer_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
+ struct Failed {};
static UnsignedLong
generate_tree (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
TypeMap::Namespaces& parser_type_map,
TypeMap::Namespaces& serializer_type_map,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
static UnsignedLong
generate_parser (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
+ FileList&,
+ AutoUnlinks&);
static UnsignedLong
generate_serializer (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/hybrid/parser-aggregate-header.cxx b/xsde/cxx/hybrid/parser-aggregate-header.cxx
index a717c68..c75eb54 100644
--- a/xsde/cxx/hybrid/parser-aggregate-header.cxx
+++ b/xsde/cxx/hybrid/parser-aggregate-header.cxx
@@ -4,11 +4,12 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/parser-aggregate-header.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
+#include <cxx/hybrid/aggregate-include.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
-#include <cult/containers/map.hxx>
#include <cult/containers/set.hxx>
namespace CXX
@@ -17,10 +18,6 @@ namespace CXX
{
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
@@ -108,8 +105,15 @@ namespace CXX
Context
{
- ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
- : Context (c), map_ (map), set_ (set), base_ (c)
+ ParserDef (Context& c,
+ TypeInstanceMap& map,
+ TypeIdInstanceMap& tid_map,
+ InstanceSet& set)
+ : Context (c),
+ map_ (map),
+ tid_map_ (tid_map),
+ set_ (set),
+ base_ (c)
{
*this >> inherits_ >> base_ >> inherits_;
@@ -136,8 +140,10 @@ namespace CXX
{
if (map_.find (&t) == map_.end ())
{
- String inst (find_instance_name (t));
- map_[&t] = inst;
+ map_[&t] = find_instance_name (t);
+
+ if (polymorphic (t))
+ collect (t);
}
}
@@ -146,10 +152,12 @@ namespace CXX
{
if (map_.find (&l) == map_.end ())
{
- String inst (find_instance_name (l));
- map_[&l] = inst;
+ map_[&l] = find_instance_name (l);
dispatch (l.argumented ().type ());
+
+ if (polymorphic (l))
+ collect (l);
}
}
@@ -158,8 +166,7 @@ namespace CXX
{
if (map_.find (&c) == map_.end ())
{
- String inst (find_instance_name (c));
- map_[&c] = inst;
+ map_[&c] = find_instance_name (c);
// Use base type's parsers in case of a restriction
// since we are not capable of using a derived type
@@ -172,6 +179,38 @@ namespace CXX
names (c);
contains_compositor (c);
}
+
+ if (polymorphic (c))
+ collect (c);
+ }
+ }
+
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+
+ String id (d.name ());
+ if (String ns = xml_ns_name (d))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ dispatch (d);
+
+ if (tid_map_.find (id) == tid_map_.end ())
+ {
+ tid_map_[id].type = &d;
+ tid_map_[id].name = map_.find (&d)->second;
+ collect (d);
+ }
}
}
@@ -475,10 +514,7 @@ namespace CXX
fund_type (SemanticGraph::Type& t, String const& name)
{
if (map_.find (&t) == map_.end ())
- {
- String inst (find_instance_name (name));
- map_[&t] = inst;
- }
+ map_[&t] = find_instance_name (name);
}
String
@@ -504,6 +540,7 @@ namespace CXX
}
TypeInstanceMap& map_;
+ TypeIdInstanceMap& tid_map_;
InstanceSet& set_;
BaseType base_;
@@ -535,37 +572,65 @@ namespace CXX
if (!tc.count ("paggr"))
return;
+ Boolean poly (polymorphic (t));
String const& name (tc.get<String> ("paggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_parser (unclash (name, "root_parser"));
+ String root_map;
String error, reset;
+ String parser_map, parser_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_parser);
- if (!exceptions)
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ parser_map = unclash (name, "parser_map_");
+ parser_map_entries = unclash (name, "parser_map_entries_");
+
+ tc.set ("paggr-parser-map", parser_map);
+ tc.set ("paggr-parser-map-entries", parser_map_entries);
+ }
+
tc.set ("paggr-map", TypeInstanceMap ());
TypeInstanceMap& map (tc.get<TypeInstanceMap> ("paggr-map"));
+ TypeIdInstanceMap tid_map;
- ParserDef def (*this, map, set);
+ ParserDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ tc.set ("paggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Parser aggregate for the " << comment (t.name ()) <<
@@ -581,24 +646,27 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- os << "void" << endl
- << pre << " ()"
- << "{"
- << "this->" << root_member << ".pre ();"
- << "}";
+ if (!poly)
+ {
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
- // post ()
- //
- String const& ret (pret_type (t));
+ // post ()
+ //
+ String const& ret (pret_type (t));
- os << ret << endl
- << post << " ()"
- << "{"
- << (ret == L"void" ? "" : "return ") << "this->" <<
- root_member << "." << post_name (t) << " ();"
- << "}";
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+ }
// root_parser ()
//
@@ -608,9 +676,23 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::parser_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << parser_map << ";"
+ << "}";
+ }
+ }
+
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::parser_error" << endl
<< error << " ()"
@@ -626,8 +708,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << parser_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -636,6 +722,13 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::parser_map_impl " << parser_map << ";"
+ << "::xsde::cxx::hybrid::parser_map_impl::entry " <<
+ parser_map_entries << "[" << tid_map.size () << "UL];";
+ }
os << "};";
}
};
@@ -656,41 +749,70 @@ namespace CXX
return;
SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic (t));
String const& name (ec.get<String> ("paggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_parser (unclash (name, "root_parser"));
+ String root_map;
String root_name (unclash (name, "root_name"));
String root_namespace (unclash (name, "root_namespace"));
String error, reset;
+ String parser_map, parser_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_parser);
+
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
set.insert (root_name);
set.insert (root_namespace);
- if (!exceptions)
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ parser_map = unclash (name, "parser_map_");
+ parser_map_entries = unclash (name, "parser_map_entries_");
+
+ ec.set ("paggr-parser-map", parser_map);
+ ec.set ("paggr-parser-map-entries", parser_map_entries);
+ }
+
ec.set ("paggr-map", TypeInstanceMap ());
TypeInstanceMap& map (ec.get<TypeInstanceMap> ("paggr-map"));
+ TypeIdInstanceMap tid_map;
- ParserDef def (*this, map, set);
+ ParserDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ ec.set ("paggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Parser aggregate for the " << comment (e.name ()) <<
@@ -706,24 +828,27 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- os << "void" << endl
- << pre << " ()"
- << "{"
- << "this->" << root_member << ".pre ();"
- << "}";
+ if (!poly)
+ {
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
- // post ()
- //
- String const& ret (pret_type (t));
+ // post ()
+ //
+ String const& ret (pret_type (t));
- os << ret << endl
- << post << " ()"
- << "{"
- << (ret == L"void" ? "" : "return ") << "this->" <<
- root_member << "." << post_name (t) << " ();"
- << "}";
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+ }
// root_parser ()
//
@@ -733,6 +858,20 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::parser_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << parser_map << ";"
+ << "}";
+ }
+ }
+
// root_name ()
//
os << "static const char*" << endl
@@ -747,7 +886,7 @@ namespace CXX
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::parser_error" << endl
<< error << " ()"
@@ -763,8 +902,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << parser_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -773,6 +916,14 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::parser_map_impl " << parser_map << ";"
+ << "::xsde::cxx::hybrid::parser_map_impl::entry " <<
+ parser_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -801,6 +952,10 @@ namespace CXX
if (gen)
{
+ if (ctx.poly_code)
+ ctx.os << "#include <xsde/cxx/hybrid/parser-map.hxx>" << endl
+ << endl;
+
// Emit "weak" header includes that are used in the file-per-type
// compilation model.
//
@@ -813,6 +968,28 @@ namespace CXX
schema.dispatch (ctx.schema_root);
}
+ // Emit includes for additional schemas that define derived
+ // polymorphic types.
+ //
+ if (ctx.poly_code)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateInclude include (ctx, "paggr");
+
+ schema >> schema_names >> ns >> names >> include;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Generate code.
+ //
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/parser-aggregate-source.cxx b/xsde/cxx/hybrid/parser-aggregate-source.cxx
index 6e80318..055cffb 100644
--- a/xsde/cxx/hybrid/parser-aggregate-source.cxx
+++ b/xsde/cxx/hybrid/parser-aggregate-source.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/parser-aggregate-source.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -16,10 +17,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
//
//
struct ParticleArg: Traversal::Element, Context
@@ -186,6 +183,57 @@ namespace CXX
TypeInstanceMap& map_;
};
+ //
+ //
+ struct ParserMapConnect: Traversal::Complex,
+ Traversal::Element,
+ Context
+ {
+ ParserMapConnect (Context& c, String const& inst, String const& map)
+ : Context (c), inst_ (inst), map_ (map)
+ {
+ *this >> inherits_ >> *this;
+
+ *this >> contains_compositor_;
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ contains_compositor (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (polymorphic (t))
+ {
+ os << "this->" << inst_ << "." <<
+ e.context ().get<String> ("p:parser") << " (" << map_ << ");";
+ }
+ }
+
+ private:
+ String const& inst_;
+ String const& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+
struct GlobalType: Traversal::Type, Context
{
GlobalType (Context& c)
@@ -208,18 +256,67 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && tc.count ("paggr-tid-map"))
+ tid_map = &tc.get<TypeIdInstanceMap> ("paggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << tc.get<String> ("paggr-parser-map") << " (" <<
+ tc.get<String> ("paggr-parser-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+ // Populate the polymorphic parser map.
+ //
+ if (tid_map)
+ {
+ String const& entry (tc.get<String> ("paggr-parser-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "p:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].parser = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+
+ // Connect parsers.
+ //
ParserConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the parser map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ ParserMapConnect t (
+ *this, i->second, tc.get<String> ("paggr-parser-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
}
};
@@ -246,18 +343,67 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && ec.count ("paggr-tid-map"))
+ tid_map = &ec.get<TypeIdInstanceMap> ("paggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << ec.get<String> ("paggr-parser-map") << " (" <<
+ ec.get<String> ("paggr-parser-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+
+ // Populate the polymorphic parser map.
+ //
+ if (tid_map)
+ {
+ String const& entry (ec.get<String> ("paggr-parser-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "p:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].parser = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+ // Connect parsers.
+ //
ParserConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the parser map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ ParserMapConnect t (
+ *this, i->second, ec.get<String> ("paggr-parser-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
// root_name ()
diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx
index 72cc2e3..6a893c5 100644
--- a/xsde/cxx/hybrid/parser-header.cxx
+++ b/xsde/cxx/hybrid/parser-header.cxx
@@ -347,6 +347,34 @@ namespace CXX
}
};
+ //
+ //
+ struct PostOverride: Traversal::Complex, Context
+ {
+ PostOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ os << "virtual " << pret_type (b) << endl
+ << post_name (b) << " ();"
+ << endl;
+ }
+ }
+ }
+ };
//
//
@@ -354,6 +382,8 @@ namespace CXX
{
Complex (Context& c)
: Context (c),
+ post_override_ (c),
+
// State.
//
compositor_state_ (c),
@@ -472,6 +502,9 @@ namespace CXX
// post
//
+ if (polymorphic (c))
+ post_override_.dispatch (c);
+
os << "virtual " << ret << endl
<< post_name (c) << " ();"
<< endl;
@@ -546,6 +579,8 @@ namespace CXX
}
private:
+ PostOverride post_override_;
+
// State.
//
CompositorState compositor_state_;
diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx
index 740cf36..c635aec 100644
--- a/xsde/cxx/hybrid/parser-name-processor.cxx
+++ b/xsde/cxx/hybrid/parser-name-processor.cxx
@@ -657,7 +657,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -686,6 +687,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass two - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -717,9 +721,10 @@ namespace CXX
Void ParserNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/parser-name-processor.hxx b/xsde/cxx/hybrid/parser-name-processor.hxx
index ea3e985..d0e1970 100644
--- a/xsde/cxx/hybrid/parser-name-processor.hxx
+++ b/xsde/cxx/hybrid/parser-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx
index 4c4237c..505d661 100644
--- a/xsde/cxx/hybrid/parser-source.cxx
+++ b/xsde/cxx/hybrid/parser-source.cxx
@@ -904,11 +904,59 @@ namespace CXX
//
//
+ struct PostOverride: Traversal::Complex, Context
+ {
+ PostOverride (Context& c)
+ : Context (c), scope_ (0)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Boolean clear (false);
+
+ if (scope_ == 0)
+ {
+ scope_ = &c;
+ clear = true;
+ }
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ String const& scope (epimpl_custom (*scope_));
+
+ os << pret_type (b) << " " << scope << "::" << endl
+ << post_name (b) << " ()"
+ << "{"
+ << "return this->" << post_name (c) << " ();"
+ << "}";
+ }
+ }
+
+ if (clear)
+ scope_ = 0;
+ }
+
+ private:
+ SemanticGraph::Complex* scope_;
+ };
+
+ //
+ //
struct Complex: Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
base_name_ (c, TypeName::base),
+ post_override_ (c),
compositor_callback_ (c),
particle_callback_ (c),
attribute_callback_ (c)
@@ -1253,6 +1301,9 @@ namespace CXX
// post
//
+ if (polymorphic (c))
+ post_override_.dispatch (c);
+
os << ret << " " << name << "::" << endl
<< post_name (c) << " ()"
<< "{";
@@ -1350,6 +1401,7 @@ namespace CXX
private:
TypeName base_name_;
+ PostOverride post_override_;
CompositorCallback compositor_callback_;
ParticleCallback particle_callback_;
diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.cxx b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
index b697715..3e3260f 100644
--- a/xsde/cxx/hybrid/serializer-aggregate-header.cxx
+++ b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
@@ -4,6 +4,8 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
+#include <cxx/hybrid/aggregate-include.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -17,10 +19,6 @@ namespace CXX
{
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
@@ -108,8 +106,15 @@ namespace CXX
Context
{
- SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
- : Context (c), map_ (map), set_ (set), base_ (c)
+ SerializerDef (Context& c,
+ TypeInstanceMap& map,
+ TypeIdInstanceMap& tid_map,
+ InstanceSet& set)
+ : Context (c),
+ map_ (map),
+ tid_map_ (tid_map),
+ set_ (set),
+ base_ (c)
{
*this >> inherits_ >> base_ >> inherits_;
@@ -136,8 +141,10 @@ namespace CXX
{
if (map_.find (&t) == map_.end ())
{
- String inst (find_instance_name (t));
- map_[&t] = inst;
+ map_[&t] = find_instance_name (t);
+
+ if (polymorphic (t))
+ collect (t);
}
}
@@ -146,10 +153,11 @@ namespace CXX
{
if (map_.find (&l) == map_.end ())
{
- String inst (find_instance_name (l));
- map_[&l] = inst;
-
+ map_[&l] = find_instance_name (l);
dispatch (l.argumented ().type ());
+
+ if (polymorphic (l))
+ collect (l);
}
}
@@ -158,8 +166,7 @@ namespace CXX
{
if (map_.find (&c) == map_.end ())
{
- String inst (find_instance_name (c));
- map_[&c] = inst;
+ map_[&c] = find_instance_name (c);
// Use base type's serializers in case of a restriction
// since we are not capable of using a derived type
@@ -172,6 +179,38 @@ namespace CXX
names (c);
contains_compositor (c);
}
+
+ if (polymorphic (c))
+ collect (c);
+ }
+ }
+
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+
+ String id (d.name ());
+ if (String ns = xml_ns_name (d))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ dispatch (d);
+
+ if (tid_map_.find (id) == tid_map_.end ())
+ {
+ tid_map_[id].type = &d;
+ tid_map_[id].name = map_.find (&d)->second;
+ collect (d);
+ }
}
}
@@ -475,10 +514,7 @@ namespace CXX
fund_type (SemanticGraph::Type& t, String const& name)
{
if (map_.find (&t) == map_.end ())
- {
- String inst (find_instance_name (name));
- map_[&t] = inst;
- }
+ map_[&t] = find_instance_name (name);
}
String
@@ -504,6 +540,7 @@ namespace CXX
}
TypeInstanceMap& map_;
+ TypeIdInstanceMap& tid_map_;
InstanceSet& set_;
BaseType base_;
@@ -535,37 +572,65 @@ namespace CXX
if (!tc.count ("saggr"))
return;
+ Boolean poly (polymorphic (t));
String const& name (tc.get<String> ("saggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_serializer (unclash (name, "root_serializer"));
+ String root_map;
String error, reset;
+ String serializer_map, serializer_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_serializer);
- if (!exceptions)
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ serializer_map = unclash (name, "serializer_map_");
+ serializer_map_entries = unclash (name, "serializer_map_entries_");
+
+ tc.set ("saggr-serializer-map", serializer_map);
+ tc.set ("saggr-serializer-map-entries", serializer_map_entries);
+ }
+
tc.set ("saggr-map", TypeInstanceMap ());
TypeInstanceMap& map (tc.get<TypeInstanceMap> ("saggr-map"));
+ TypeIdInstanceMap tid_map;
- SerializerDef def (*this, map, set);
+ SerializerDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ tc.set ("saggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Serializer aggregate for the " << comment (t.name ()) <<
@@ -581,29 +646,32 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- String const& arg (sarg_type (t));
+ if (!poly)
+ {
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
- os << "void" << endl
- << pre << " (";
+ os << "void" << endl
+ << pre << " (";
- if (arg != L"void")
- os << arg << " x";
+ if (arg != L"void")
+ os << arg << " x";
- os <<")"
- << "{"
- << "this->" << root_member << ".pre (" <<
- (arg != L"void" ? "x" : "") << ");"
- << "}";
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
- // post ()
- //
- os << "void" << endl
- << post << " ()"
- << "{"
- << "this->" << root_member << ".post ();"
- << "}";
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+ }
// root_serializer ()
//
@@ -613,9 +681,23 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::serializer_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << serializer_map << ";"
+ << "}";
+ }
+ }
+
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::serializer_error" << endl
<< error << " ()"
@@ -631,8 +713,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << serializer_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -641,6 +727,15 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::serializer_map_impl " <<
+ serializer_map << ";"
+ << "::xsde::cxx::hybrid::serializer_map_impl::entry " <<
+ serializer_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -661,41 +756,70 @@ namespace CXX
return;
SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic (t));
String const& name (ec.get<String> ("saggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_serializer (unclash (name, "root_serializer"));
+ String root_map;
String root_name (unclash (name, "root_name"));
String root_namespace (unclash (name, "root_namespace"));
String error, reset;
+ String serializer_map, serializer_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_serializer);
+
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
set.insert (root_name);
set.insert (root_namespace);
- if (!exceptions)
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ serializer_map = unclash (name, "serializer_map_");
+ serializer_map_entries = unclash (name, "serializer_map_entries_");
+
+ ec.set ("saggr-serializer-map", serializer_map);
+ ec.set ("saggr-serializer-map-entries", serializer_map_entries);
+ }
+
ec.set ("saggr-map", TypeInstanceMap ());
TypeInstanceMap& map (ec.get<TypeInstanceMap> ("saggr-map"));
+ TypeIdInstanceMap tid_map;
- SerializerDef def (*this, map, set);
+ SerializerDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ ec.set ("saggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Serializer aggregate for the " << comment (e.name ()) <<
@@ -711,29 +835,32 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- String const& arg (sarg_type (t));
+ if (!poly)
+ {
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
- os << "void" << endl
- << pre << " (";
+ os << "void" << endl
+ << pre << " (";
- if (arg != L"void")
- os << arg << " x";
+ if (arg != L"void")
+ os << arg << " x";
- os <<")"
- << "{"
- << "this->" << root_member << ".pre (" <<
- (arg != L"void" ? "x" : "") << ");"
- << "}";
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
- // post ()
- //
- os << "void" << endl
- << post << " ()"
- << "{"
- << "this->" << root_member << ".post ();"
- << "}";
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+ }
// root_serializer ()
//
@@ -743,6 +870,20 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::serializer_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << serializer_map << ";"
+ << "}";
+ }
+ }
+
// root_name ()
//
os << "static const char*" << endl
@@ -757,7 +898,7 @@ namespace CXX
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::serializer_error" << endl
<< error << " ()"
@@ -773,8 +914,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << serializer_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -783,6 +928,15 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::serializer_map_impl " <<
+ serializer_map << ";"
+ << "::xsde::cxx::hybrid::serializer_map_impl::entry " <<
+ serializer_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -811,6 +965,10 @@ namespace CXX
if (gen)
{
+ if (ctx.poly_code)
+ ctx.os << "#include <xsde/cxx/hybrid/serializer-map.hxx>" << endl
+ << endl;
+
// Emit "weak" header includes that are used in the file-per-type
// compilation model.
//
@@ -823,6 +981,28 @@ namespace CXX
schema.dispatch (ctx.schema_root);
}
+ // Emit includes for additional schemas that define derived
+ // polymorphic types.
+ //
+ if (ctx.poly_code)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateInclude include (ctx, "saggr");
+
+ schema >> schema_names >> ns >> names >> include;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Generate code.
+ //
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.cxx b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
index 7e305b6..0422031 100644
--- a/xsde/cxx/hybrid/serializer-aggregate-source.cxx
+++ b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/serializer-aggregate-source.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -16,10 +17,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
//
//
struct ParticleArg: Traversal::Element, Context
@@ -186,6 +183,62 @@ namespace CXX
TypeInstanceMap& map_;
};
+ //
+ //
+ struct SerializerMapConnect: Traversal::Complex,
+ Traversal::Element,
+ Context
+ {
+ SerializerMapConnect (Context& c,
+ String const& inst,
+ String const& map)
+ : Context (c), inst_ (inst), map_ (map)
+ {
+ *this >> inherits_ >> *this;
+
+ *this >> contains_compositor_;
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ contains_compositor (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (polymorphic (t))
+ {
+ os << "this->" << inst_ << "." <<
+ e.context ().get<String> ("s:serializer") << " (" <<
+ map_ << ");";
+ }
+ }
+
+ private:
+ String const& inst_;
+ String const& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+
+ //
+ //
struct GlobalType: Traversal::Type, Context
{
GlobalType (Context& c)
@@ -208,18 +261,68 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && tc.count ("saggr-tid-map"))
+ tid_map = &tc.get<TypeIdInstanceMap> ("saggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << tc.get<String> ("saggr-serializer-map") << " (" <<
+ tc.get<String> ("saggr-serializer-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+ // Populate the polymorphic serializer map.
+ //
+ if (tid_map)
+ {
+ String const& entry (
+ tc.get<String> ("saggr-serializer-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "s:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].serializer = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+
+ // Connect parsers.
+ //
SerializerConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the serializer map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ SerializerMapConnect t (
+ *this, i->second, tc.get<String> ("saggr-serializer-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
}
};
@@ -246,18 +349,68 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && ec.count ("saggr-tid-map"))
+ tid_map = &ec.get<TypeIdInstanceMap> ("saggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << ec.get<String> ("saggr-serializer-map") << " (" <<
+ ec.get<String> ("saggr-serializer-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+
+ // Populate the polymorphic serializer map.
+ //
+ if (tid_map)
+ {
+ String const& entry (
+ ec.get<String> ("saggr-serializer-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "s:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].serializer = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+ // Connect parsers.
+ //
SerializerConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the serializer map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ SerializerMapConnect t (
+ *this, i->second, ec.get<String> ("saggr-serializer-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
// root_name ()
diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx
index 20f4e15..db0578f 100644
--- a/xsde/cxx/hybrid/serializer-header.cxx
+++ b/xsde/cxx/hybrid/serializer-header.cxx
@@ -343,10 +343,40 @@ namespace CXX
//
//
+ struct PreOverride: Traversal::Complex, Context
+ {
+ PreOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ os << "virtual void" << endl
+ << "pre (" << sarg_type (b) << ");"
+ << endl;
+ }
+ }
+ }
+ };
+
+ //
+ //
struct Complex : Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
+ pre_override_ (c),
// State.
//
@@ -422,6 +452,9 @@ namespace CXX
// pre
//
+ if (polymorphic (c))
+ pre_override_.dispatch (c);
+
os << "virtual void" << endl
<< "pre (" << arg << ");"
<< endl;
@@ -522,6 +555,8 @@ namespace CXX
}
private:
+ PreOverride pre_override_;
+
// State.
//
CompositorState compositor_state_;
diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx
index ba4a268..2f7d296 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.cxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.cxx
@@ -265,7 +265,7 @@ namespace CXX
if (!name)
return;
- String const& skel (lc.get<String> ("p:name"));
+ String const& skel (lc.get<String> ("s:name"));
NameSet set;
set.insert (name);
@@ -672,7 +672,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -701,6 +702,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass two - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -732,9 +736,10 @@ namespace CXX
Void SerializerNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/serializer-name-processor.hxx b/xsde/cxx/hybrid/serializer-name-processor.hxx
index f69dfe4..b607c24 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.hxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx
index 6e82bd0..540d742 100644
--- a/xsde/cxx/hybrid/serializer-source.cxx
+++ b/xsde/cxx/hybrid/serializer-source.cxx
@@ -783,12 +783,35 @@ namespace CXX
<< esname (e) << " ()"
<< "{";
+ if (polymorphic (t))
+ {
+ if (stl)
+ {
+ os << "const ::std::string& dt = " << access << iter <<
+ "->_dynamic_type ();"
+ << "if (dt != " << esskel (t) << "::_static_type ())" << endl
+ << "this->_context ().type_id (dt.c_str ());"
+ << endl;
+ }
+ else
+ {
+ os << "const char* dt = " << access << iter <<
+ "->_dynamic_type ();"
+ << "if (strcmp (dt, " << esskel (t) <<
+ "::_static_type ()) != 0)" << endl
+ << "this->_context ().type_id (dt);"
+ << endl;
+ }
+ }
+
if (ret != L"void")
{
os << "return ";
type_pass_.dispatch (t);
os << "*" << access << iter << "++;";
}
+ else
+ os << access << iter << "++;";
os << "}";
}
@@ -807,6 +830,27 @@ namespace CXX
<< esname (e) << " ()"
<< "{";
+ if (polymorphic (t))
+ {
+ if (stl)
+ {
+ os << "const ::std::string& dt = " << access << ename (e) <<
+ " ()._dynamic_type ();"
+ << "if (dt != " << esskel (t) << "::_static_type ())" << endl
+ << "this->_context ().type_id (dt.c_str ());"
+ << endl;
+ }
+ else
+ {
+ os << "const char* dt = " << access << ename (e) <<
+ " ()._dynamic_type ();"
+ << "if (strcmp (dt, " << esskel (t) <<
+ "::_static_type ()) != 0)" << endl
+ << "this->_context ().type_id (dt);"
+ << endl;
+ }
+ }
+
if (ret != L"void")
{
os << "return ";
@@ -870,11 +914,59 @@ namespace CXX
//
//
+ struct PreOverride: Traversal::Complex, Context
+ {
+ PreOverride (Context& c)
+ : Context (c), scope_ (0)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Boolean clear (false);
+
+ if (scope_ == 0)
+ {
+ scope_ = &c;
+ clear = true;
+ }
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ String const& scope (esimpl_custom (*scope_));
+
+ os << "void " << scope << "::" << endl
+ << "pre (" << sarg_type (b) << " x)"
+ << "{"
+ << "this->pre (static_cast< " << sarg_type (c) << " > (x));"
+ << "}";
+ }
+ }
+
+ if (clear)
+ scope_ = 0;
+ }
+
+ private:
+ SemanticGraph::Complex* scope_;
+ };
+
+ //
+ //
struct Complex: Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
type_pass_ (c),
+ pre_override_ (c),
// Initializers.
//
@@ -961,6 +1053,9 @@ namespace CXX
// pre
//
+ if (polymorphic (c))
+ pre_override_.dispatch (c);
+
String const& arg (sarg_type (c));
os << "void " << name << "::" << endl
@@ -1136,6 +1231,7 @@ namespace CXX
private:
TypePass type_pass_;
+ PreOverride pre_override_;
// Initializers.
//
@@ -1159,6 +1255,10 @@ namespace CXX
Void
generate_serializer_source (Context& ctx)
{
+ if (ctx.poly_code && !ctx.stl)
+ ctx.os << "#include <string.h>" << endl
+ << endl;
+
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx
index c2e8bf4..3003e4c 100644
--- a/xsde/cxx/hybrid/tree-header.cxx
+++ b/xsde/cxx/hybrid/tree-header.cxx
@@ -32,6 +32,9 @@ namespace CXX
//
if (name)
{
+ Boolean cd (lc.count ("cd-name"));
+ Boolean poly (polymorphic (l));
+
os << "// " << comment (l.name ()) << " (variable-length)" << endl
<< "//" << endl;
@@ -50,17 +53,23 @@ namespace CXX
os << "public:" << endl
<< name << " ();";
+ // d-tor
+ //
+ if (poly)
+ os << "virtual ~" << name << " ();";
+
+ os << endl;
+
// Custom data.
//
- if (lc.count ("cd-name"))
+ if (cd)
{
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
+ os << "// Custom data." << endl
<< "//" << endl;
// sequence & iterators
@@ -84,9 +93,28 @@ namespace CXX
os << sequence << "&" << endl
<< name << " ();"
<< endl;
+ }
+
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ if (cd)
+ {
os << "private:" << endl
- << sequence << " " << ecd_member (l) << ";";
+ << ecd_sequence (l) << " " << ecd_member (l) << ";";
}
os << "};";
@@ -128,15 +156,18 @@ namespace CXX
//
if (name)
{
+ Boolean fl (fixed_length (u));
+ Boolean poly (polymorphic (u));
Boolean cd (uc.count ("cd-name"));
- os << "// " << comment (u.name ()) << " (variable-length)" << endl
+ os << "// " << comment (u.name ()) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
<< "//" << endl;
os << "class " << name
<< "{";
- if (!fixed_length (u))
+ if (!fl)
os << "private:" << endl
<< name << " (const " << name << "&);"
<< name << "& operator= (const " << name << "&);"
@@ -148,13 +179,18 @@ namespace CXX
//
os << name << " ();";
+ // d-tor
+ //
+ if (!stl || poly)
+ os << (poly ? "virtual " : "") << "~" << name << " ();";
+
+ os << endl;
+
String const& value (uc.get<String> ("value"));
String const& member (uc.get<String> ("value-member"));
if (stl)
{
- os << endl;
-
// const std::string&
// name () const
//
@@ -178,11 +214,6 @@ namespace CXX
}
else
{
- // d-tor
- //
- os << "~" << name << " ();"
- << endl;
-
// const char*
// name () const
//
@@ -250,6 +281,22 @@ namespace CXX
<< endl;
}
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
if (stl)
{
os << "private:" << endl
@@ -2337,6 +2384,7 @@ namespace CXX
if (name)
{
Boolean fl (fixed_length (c));
+ Boolean poly (polymorphic (c));
Boolean restriction (restriction_p (c));
Boolean cd (cc.count ("cd-name"));
@@ -2361,8 +2409,8 @@ namespace CXX
// d-tor
//
- if (!restriction)
- os << "~" << name << " ();";
+ if (!restriction || poly)
+ os << (poly ? "virtual " : "") << "~" << name << " ();";
// copy c-tor & operator=
//
@@ -2421,6 +2469,22 @@ namespace CXX
<< endl;
}
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
if (!restriction || cd)
os << "private:" << endl;
diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx
index b1c60e6..7cb4b2c 100644
--- a/xsde/cxx/hybrid/tree-inline.cxx
+++ b/xsde/cxx/hybrid/tree-inline.cxx
@@ -150,15 +150,6 @@ namespace CXX
}
else
{
- // d-tor
- //
- os << inl
- << name << "::" << endl
- << "~" << name << " ()"
- << "{"
- << "delete[] this->" << member << ";"
- << "}";
-
// const char*
// name () const
//
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx
index a3a1dd3..9308598 100644
--- a/xsde/cxx/hybrid/tree-name-processor.cxx
+++ b/xsde/cxx/hybrid/tree-name-processor.cxx
@@ -2053,8 +2053,9 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
- SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -2120,6 +2121,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -2178,9 +2182,10 @@ namespace CXX
Void TreeNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/tree-name-processor.hxx b/xsde/cxx/hybrid/tree-name-processor.hxx
index 4d884bc..17becee 100644
--- a/xsde/cxx/hybrid/tree-name-processor.hxx
+++ b/xsde/cxx/hybrid/tree-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
index a3b2231..33d829a 100644
--- a/xsde/cxx/hybrid/tree-size-processor.cxx
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -242,11 +242,15 @@ namespace CXX
Type (Boolean& valid,
TypeSet& custom_data,
CustomTypeMap& custom_type_map,
- Boolean stl_)
+ TypeSet& poly_types,
+ Boolean stl_,
+ Boolean poly_)
: valid_ (valid),
custom_data_ (custom_data),
custom_type_map_ (custom_type_map),
- stl (stl_)
+ poly_types_ (poly_types),
+ stl (stl_),
+ poly (poly_)
{
}
@@ -364,9 +368,40 @@ namespace CXX
Void
set (SemanticGraph::Type& t, Boolean v)
{
+ using SemanticGraph::Complex;
+
+ String const& name (t.name ());
+
+ // Check if this type is polymorphic.
+ //
+ if (poly)
+ {
+ SemanticGraph::Context& ctx (t.context ());
+
+ if (!ctx.count ("polymorphic"))
+ {
+ // If our base is polymorphic then we are as well.
+ //
+ Boolean pb (false);
+ if (Complex* c = dynamic_cast<Complex*> (&t))
+ {
+ pb = c->inherits_p () &&
+ c->inherits ().base ().context ().count ("polymorphic");
+ }
+
+ if (pb || poly_types_.find (name) != poly_types_.end ())
+ {
+ ctx.set ("polymorphic", true);
+ v = false;
+ }
+ }
+ else
+ v = false;
+ }
+
// Check if this is a custom type.
//
- CustomTypeMap::Iterator i = custom_type_map_.find (t.name ());
+ CustomTypeMap::Iterator i = custom_type_map_.find (name);
if (i != custom_type_map_.end ())
{
@@ -390,7 +425,9 @@ namespace CXX
Boolean& valid_;
TypeSet& custom_data_;
CustomTypeMap& custom_type_map_;
+ TypeSet& poly_types_;
Boolean stl;
+ Boolean poly;
typedef Containers::Vector<SemanticGraph::Complex*> Path;
Path path_;
@@ -453,8 +490,8 @@ namespace CXX
Traversal::Fundamental::Entities
{
- FundType (Boolean stl_)
- : stl (stl_)
+ FundType (Boolean stl_, TypeSet& poly_types)
+ : stl (stl_), poly_types_ (poly_types)
{
}
@@ -463,7 +500,18 @@ namespace CXX
virtual Void
traverse (SemanticGraph::AnyType& t)
{
- set (t, true);
+ /*
+ @@ disabled
+ // Check if this type is marked polymorphic.
+ //
+ if (poly_types_.find (t.name ()) != poly_types_.end ())
+ {
+ t.context ().set ("polymorphic", true);
+ set (t, false);
+ }
+ else
+ */
+ set (t, true);
}
virtual Void
@@ -755,6 +803,130 @@ namespace CXX
private:
Boolean stl;
+ TypeSet& poly_types_;
+ };
+
+ struct GlobalElement: Traversal::Element
+ {
+ GlobalElement (TypeSet& poly_types,
+ Boolean& valid,
+ const WarningSet& disabled_warnings)
+ : poly_types_ (poly_types), valid_ (valid), warning_ (true)
+ {
+ if (disabled_warnings.find ("all") != disabled_warnings.end () ||
+ disabled_warnings.find ("H004") != disabled_warnings.end ())
+ warning_ = false;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ using SemanticGraph::Schema;
+
+ if (!e.substitutes_p ())
+ return;
+
+ // If we are a substitution for some element, then mark
+ // that element's type as polymorphic.
+ //
+ Type& r (e.substitutes ().root ());
+ SemanticGraph::Type& rt (r.type ());
+ SemanticGraph::Context& ctx (rt.context ());
+
+ if (ctx.count ("polymorphic"))
+ return;
+
+ // Only user-defined and anyType can be declared polymorphic.
+ //
+ /*
+ @@ disabled
+ if (rt.is_a<SemanticGraph::Fundamental::Type> () ||
+ rt.is_a<SemanticGraph::AnySimpleType> ())
+ */
+ if (rt.is_a<SemanticGraph::Fundamental::Type> () ||
+ rt.is_a<SemanticGraph::AnySimpleType> () ||
+ rt.is_a<SemanticGraph::AnyType> ())
+ {
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": error: built-in type '" << rt.name () << "' "
+ << "is expected to be polymorphic" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: because type '" << rt.name () << "' is "
+ << "used in a substitution group declared here" << endl;
+
+ /*
+ @@ disabled
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": info: only user-defined types and anyType can "
+ << "be polymorphic in this mapping" << endl;
+ */
+
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": info: only user-defined types can "
+ << "be polymorphic in this mapping" << endl;
+
+ valid_ = false;
+ return;
+ }
+
+ ctx.set ("polymorphic", true);
+
+ if (!warning_)
+ return;
+
+ Schema& es (dynamic_cast<Schema&> (e.scope ().scope ()));
+ Schema& rts (dynamic_cast<Schema&> (rt.scope ().scope ()));
+
+ // If the root type and this element are in different schemas
+ // and the root type is not explicitly marked as polymorphic,
+ // then issue a warning.
+ //
+ if (&es != &rts &&
+ !sources_p (es, rts) &&
+ poly_types_.find (rt.name ()) == poly_types_.end ())
+ {
+ wcerr << rt.file () << ":" << rt.line () << ":" << rt.column ()
+ << ": warning H004: assuming type '" << rt.name () << "' "
+ << "is polymorphic" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: because type '" << rt.name () << "' is "
+ << "used in a substitution group declared here" << endl;
+
+ wcerr << rt.file () << ":" << rt.line () << ":" << rt.column ()
+ << ": info: use --polymorphic-type to indicate this type "
+ << "is polymorphic when compiling schemas that "
+ << "reference it" << endl;
+ }
+ }
+
+ 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:
+ TypeSet& poly_types_;
+ Boolean& valid_;
+ Boolean warning_;
};
// Go into sourced/included/imported schemas while making sure
@@ -764,14 +936,19 @@ namespace CXX
Traversal::Includes,
Traversal::Imports
{
+ Uses (Char const* seen_key)
+ : seen_key_ (seen_key)
+ {
+ }
+
virtual Void
traverse (SemanticGraph::Sources& sr)
{
SemanticGraph::Schema& s (sr.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Sources::traverse (sr);
}
}
@@ -781,9 +958,9 @@ namespace CXX
{
SemanticGraph::Schema& s (i.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Includes::traverse (i);
}
}
@@ -793,21 +970,40 @@ namespace CXX
{
SemanticGraph::Schema& s (i.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Imports::traverse (i);
}
}
+
+ private:
+ Char const* seen_key_;
};
+ Char const* pass_one_key = "cxx-hybrid-size-processor-seen-one";
+ Char const* pass_two_key = "cxx-hybrid-size-processor-seen-two";
+
Boolean
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const&)
+ SemanticGraph::Path const&,
+ const WarningSet& disabled_warnings)
{
Boolean valid (true);
Boolean stl (!ops.value<CLI::no_stl> ());
+ Boolean poly (ops.value<CLI::generate_polymorphic> ());
+
+ // Prepare a set of polymorphic types.
+ //
+
+ TypeSet poly_types;
+ if (poly)
+ {
+ poly_types.insert (
+ ops.value<CLI::polymorphic_type> ().begin (),
+ ops.value<CLI::polymorphic_type> ().end ());
+ }
// Root schema in the file-per-type mode is just a bunch
// of includes without a namespace.
@@ -824,7 +1020,7 @@ namespace CXX
Traversal::Names schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- FundType fund_type (stl);
+ FundType fund_type (stl, poly_types);
schema >> schema_names >> ns >> ns_names >> fund_type;
@@ -832,7 +1028,7 @@ namespace CXX
}
else
{
- // Pass one - assign sizes to fundamental types.
+ // First assign sizes to fundamental types.
//
{
Traversal::Schema schema;
@@ -844,7 +1040,7 @@ namespace CXX
Traversal::Names xs_schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- FundType fund_type (stl);
+ FundType fund_type (stl, poly_types);
xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type;
@@ -855,7 +1051,7 @@ namespace CXX
// processed which may happen in the file-per-type compilation
// mode.
//
- if (!tu.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!tu.context ().count (pass_two_key))
{
// Prepare a set of types with custom data. Here we are
// only interested in detecting global types. If a type
@@ -877,8 +1073,7 @@ namespace CXX
}
}
- // Prepare a map of types custom types that specify type
- // size.
+ // Prepare a map of custom types that specify type length.
//
CustomTypeMap custom_type_map;
@@ -949,23 +1144,53 @@ namespace CXX
}
}
+ // Pass one - check substitution groups.
+ //
+ if (valid && poly)
+ {
+ Traversal::Schema schema;
+ Uses uses (pass_one_key);
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalElement element (poly_types, valid, disabled_warnings);
+
+ schema >> schema_names >> ns >> ns_names >> element;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set (pass_one_key, true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - process types.
+ //
if (valid)
{
Traversal::Schema schema;
- Uses uses;
+ Uses uses (pass_two_key);
schema >> uses >> schema;
Traversal::Names schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- Type type (valid, custom_data_types, custom_type_map, stl);
+ Type type (valid,
+ custom_data_types,
+ custom_type_map,
+ poly_types,
+ stl,
+ poly);
schema >> schema_names >> ns >> ns_names >> type;
// Some twisted schemas do recusive self-inclusion.
//
- tu.context ().set ("cxx-hybrid-size-processor-seen", true);
+ tu.context ().set (pass_two_key, true);
schema.dispatch (tu);
}
@@ -979,9 +1204,10 @@ namespace CXX
Boolean TreeSizeProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings)
{
- return process_impl (ops, tu, file);
+ return process_impl (ops, tu, file, disabled_warnings);
}
}
}
diff --git a/xsde/cxx/hybrid/tree-size-processor.hxx b/xsde/cxx/hybrid/tree-size-processor.hxx
index d9257a1..d82364f 100644
--- a/xsde/cxx/hybrid/tree-size-processor.hxx
+++ b/xsde/cxx/hybrid/tree-size-processor.hxx
@@ -12,6 +12,8 @@
#include <cxx/hybrid/cli.hxx>
+#include <xsde.hxx>
+
namespace CXX
{
namespace Hybrid
@@ -24,7 +26,8 @@ namespace CXX
Boolean
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings);
};
}
}
diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx
index 6de3e35..2723046 100644
--- a/xsde/cxx/hybrid/tree-source.cxx
+++ b/xsde/cxx/hybrid/tree-source.cxx
@@ -14,6 +14,161 @@ namespace CXX
{
namespace
{
+ struct List : Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename_custom (l));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ if (polymorphic (l))
+ {
+ os << "// " << comment (l.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ if (typeinfo)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "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_custom (u));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ Boolean poly (polymorphic (u));
+
+ if (!stl || poly)
+ {
+ os << "// " << comment (u.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{";
+
+ if (!stl)
+ os << "delete[] this->" <<
+ u.context ().get<String> ("value-member") << ";";
+
+ os << "}";
+
+ if (poly && typeinfo)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "char* ") <<
+ name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ }
+ };
+
struct ChoiceParticle: Traversal::Element,
Traversal::Compositor,
Context
@@ -1464,6 +1619,7 @@ namespace CXX
if (!name)
return;
+ Boolean poly (polymorphic (c));
Boolean restriction (restriction_p (c));
os << "// " << comment (c.name ()) << endl
@@ -1486,22 +1642,27 @@ namespace CXX
os << "}";
-
- if (!restriction)
+ // d-tor ()
+ //
+ if (!restriction || poly)
{
- // d-tor ()
- //
os << name << "::" << endl
<< "~" << name << " ()"
<< "{";
- Complex::names (c, attribute_names_dtor_);
+ if (!restriction)
+ {
+ Complex::names (c, attribute_names_dtor_);
- if (c.contains_compositor_p ())
- Complex::contains_compositor (c, contains_compositor_dtor_);
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_dtor_);
+ }
os << "}";
+ }
+ if (!restriction)
+ {
if (fixed_length (c))
{
// copy c-tor
@@ -1554,7 +1715,49 @@ namespace CXX
//
if (c.contains_compositor_p ())
Complex::contains_compositor (c, contains_compositor_func_);
+ }
+
+ if (poly && typeinfo)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "char* ") <<
+ name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+
+ if (!restriction)
+ {
// Nested c-tors, etc.
//
if (c.contains_compositor_p ())
@@ -1661,16 +1864,16 @@ namespace CXX
Namespace ns (ctx);
- //Union union_ (ctx);
+ List list (ctx);
+ Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
- //names >> union_;
+ names >> list;
+ names >> union_;
names >> complex;
- //names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/validator.cxx b/xsde/cxx/hybrid/validator.cxx
index 65dd3e2..c799563 100644
--- a/xsde/cxx/hybrid/validator.cxx
+++ b/xsde/cxx/hybrid/validator.cxx
@@ -20,6 +20,9 @@ namespace CXX
{
namespace
{
+ // H004 is used by tree-size-processor.
+ //
+
class ValidationContext: public Context
{
public:
@@ -34,6 +37,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public:
@@ -147,7 +152,6 @@ namespace CXX
}
}
- /*
virtual Void
traverse (SemanticGraph::Element& e)
{
@@ -165,11 +169,10 @@ namespace CXX
<< "--generate-polymorphic was not specified" << endl;
os << e.file () << ":" << e.line () << ":" << e.column ()
- << ": info: generated code may not be able to serialize "
+ << ": info: generated code may not be able to handle "
<< "some conforming instances" << endl;
}
}
- */
// Return true if root sources s.
//
diff --git a/xsde/cxx/parser/generator.cxx b/xsde/cxx/parser/generator.cxx
index e552c92..aed6e53 100644
--- a/xsde/cxx/parser/generator.cxx
+++ b/xsde/cxx/parser/generator.cxx
@@ -526,6 +526,14 @@ namespace CXX
return spec;
}
+ Void Parser::Generator::
+ process_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
namespace
{
@@ -646,7 +654,7 @@ namespace CXX
//
{
NameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
Boolean validation (!ops.value<CLI::suppress_validation> ());
diff --git a/xsde/cxx/parser/generator.hxx b/xsde/cxx/parser/generator.hxx
index a261eca..305d8b1 100644
--- a/xsde/cxx/parser/generator.hxx
+++ b/xsde/cxx/parser/generator.hxx
@@ -35,17 +35,26 @@ namespace CXX
static CLI::OptionsSpec
options_spec ();
+ // Assign names to global declarations.
+ //
+ static Void
+ process_names (CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
struct Failed {};
static UnsignedLong
- generate (CLI::Options const& options,
+ generate (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
+ XSDFrontend::SemanticGraph::Path const&,
TypeMap::Namespaces& type_map,
Boolean gen_driver,
const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/parser/name-processor.cxx b/xsde/cxx/parser/name-processor.cxx
index bc0e7a5..9c945b3 100644
--- a/xsde/cxx/parser/name-processor.cxx
+++ b/xsde/cxx/parser/name-processor.cxx
@@ -1224,7 +1224,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -1290,6 +1291,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -1318,9 +1322,10 @@ namespace CXX
Void NameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/parser/name-processor.hxx b/xsde/cxx/parser/name-processor.hxx
index 8d55f30..6a7af9f 100644
--- a/xsde/cxx/parser/name-processor.hxx
+++ b/xsde/cxx/parser/name-processor.hxx
@@ -22,9 +22,10 @@ namespace CXX
{
public:
Void
- process (CLI::Options const& options,
+ process (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/parser/validator.cxx b/xsde/cxx/parser/validator.cxx
index 570a0bf..842fc4e 100644
--- a/xsde/cxx/parser/validator.cxx
+++ b/xsde/cxx/parser/validator.cxx
@@ -34,6 +34,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public:
diff --git a/xsde/cxx/serializer/generator.cxx b/xsde/cxx/serializer/generator.cxx
index c27ef09..5e72d86 100644
--- a/xsde/cxx/serializer/generator.cxx
+++ b/xsde/cxx/serializer/generator.cxx
@@ -519,6 +519,14 @@ namespace CXX
return spec;
}
+ Void Serializer::Generator::
+ process_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
namespace
{
@@ -637,7 +645,7 @@ namespace CXX
//
{
NameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
//
diff --git a/xsde/cxx/serializer/generator.hxx b/xsde/cxx/serializer/generator.hxx
index a5b8558..eaa378d 100644
--- a/xsde/cxx/serializer/generator.hxx
+++ b/xsde/cxx/serializer/generator.hxx
@@ -35,17 +35,26 @@ namespace CXX
static CLI::OptionsSpec
options_spec ();
+ // Assign names to global declarations.
+ //
+ static Void
+ process_names (CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
struct Failed {};
static UnsignedLong
- generate (CLI::Options const& options,
+ generate (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
+ XSDFrontend::SemanticGraph::Path const&,
TypeMap::Namespaces& type_map,
Boolean gen_driver,
const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/serializer/name-processor.cxx b/xsde/cxx/serializer/name-processor.cxx
index d68b823..140ad06 100644
--- a/xsde/cxx/serializer/name-processor.cxx
+++ b/xsde/cxx/serializer/name-processor.cxx
@@ -1307,7 +1307,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -1373,6 +1374,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -1401,9 +1405,10 @@ namespace CXX
Void NameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/serializer/name-processor.hxx b/xsde/cxx/serializer/name-processor.hxx
index bf69ba6..f7cd63b 100644
--- a/xsde/cxx/serializer/name-processor.hxx
+++ b/xsde/cxx/serializer/name-processor.hxx
@@ -22,9 +22,10 @@ namespace CXX
{
public:
Void
- process (CLI::Options const& options,
+ process (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/serializer/validator.cxx b/xsde/cxx/serializer/validator.cxx
index d9cc724..189ccac 100644
--- a/xsde/cxx/serializer/validator.cxx
+++ b/xsde/cxx/serializer/validator.cxx
@@ -34,6 +34,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public:
diff --git a/xsde/xsde.cxx b/xsde/xsde.cxx
index 97224ca..800db93 100644
--- a/xsde/xsde.cxx
+++ b/xsde/xsde.cxx
@@ -583,6 +583,11 @@ main (Int argc, Char* argv[])
cmd == "cxx-serializer" ||
(gen_hybrid && h_ops->value<CXX::Hybrid::CLI::generate_serializer> ()));
+ Boolean poly_aggr (
+ gen_hybrid &&
+ h_ops->value<CXX::Hybrid::CLI::generate_polymorphic> () &&
+ h_ops->value<CXX::Hybrid::CLI::generate_aggregate> ());
+
if (!fpt)
{
// File-per-schema compilation mode.
@@ -592,6 +597,15 @@ main (Int argc, Char* argv[])
// Parse schema.
//
SemanticGraph::Path tu;
+ SemanticGraph::Paths paths;
+
+ XSDFrontend::Parser parser (
+ true,
+ !common_ops.value<CLI::disable_full_check> (),
+ loc_translator,
+ disabled_w);
+
+ Evptr<SemanticGraph::Schema> schema;
try
{
@@ -601,30 +615,22 @@ main (Int argc, Char* argv[])
{
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;
+ // 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);
+ NarrowString xml_schema_file;
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 =
@@ -632,10 +638,10 @@ main (Int argc, Char* argv[])
if (gen_xml_schema)
{
- if (NarrowString name =
+ if (xml_schema_file =
p_ops->value<CXX::Parser::CLI::extern_xml_schema> ())
{
- if (tu.native_file_string () != name)
+ if (tu.native_file_string () != xml_schema_file)
gen_xml_schema = false;
}
}
@@ -647,10 +653,10 @@ main (Int argc, Char* argv[])
if (gen_xml_schema)
{
- if (NarrowString name =
+ if (xml_schema_file =
s_ops->value<CXX::Serializer::CLI::extern_xml_schema> ())
{
- if (tu.native_file_string () != name)
+ if (tu.native_file_string () != xml_schema_file)
gen_xml_schema = false;
}
}
@@ -662,22 +668,81 @@ main (Int argc, Char* argv[])
if (gen_xml_schema)
{
- if (NarrowString name =
+ if (xml_schema_file =
h_ops->value<CXX::Hybrid::CLI::extern_xml_schema> ())
{
- if (tu.native_file_string () != name)
+ if (tu.native_file_string () != xml_schema_file)
gen_xml_schema = false;
}
}
}
+ }
+
+ // If we are generating polymorphic aggregates then we need
+ // to add all the schemas to the semantic graph in case they
+ // define derived polymorphic types, except for the fake XML
+ // Schema file.
+ //
+ Boolean multi (poly_aggr && !gen_xml_schema);
+
+ if (multi)
+ {
+ Size ai (1);
+ paths.push_back (tu);
+
+ try
+ {
+ for (; ai < args.size (); ++ai)
+ {
+ if (ai != i && args[ai] != xml_schema_file)
+ paths.push_back (
+ SemanticGraph::Path (args[ai], boost::filesystem::native));
+ }
+ }
+ catch (SemanticGraph::InvalidPath const&)
+ {
+ e << "error: '" << args[ai] << "' is not a valid "
+ << "filesystem path" << endl;
+ return 1;
+ }
- if (gen_xml_schema)
- schema = parser.xml_schema (tu);
+ // Also include additional schemas that may be specified with
+ // the --polymorphic-schema option.
+ //
+ NarrowStrings const& extra_files (
+ h_ops->value<CXX::Hybrid::CLI::polymorphic_schema> ());
+
+ NarrowStrings::ConstIterator i (extra_files.begin ());
+
+ try
+ {
+ for (; i != extra_files.end (); ++i)
+ {
+ paths.push_back (
+ SemanticGraph::Path (*i, boost::filesystem::native));
+ }
+ }
+ catch (SemanticGraph::InvalidPath const&)
+ {
+ e << "error: '" << i->c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+ return 1;
+ }
+
+
+ if (args.size () <= 1)
+ multi = false;
+ }
+
+ if (gen_xml_schema)
+ schema = parser.xml_schema (tu);
+ else
+ {
+ if (multi)
+ schema = parser.parse (paths);
else
schema = parser.parse (tu);
}
- else
- schema = parser.parse (tu);
// Morph anonymous types.
//
@@ -686,7 +751,11 @@ main (Int argc, Char* argv[])
try
{
Transformations::Anonymous trans (anon_translator);
- trans.transform (*schema, tu, true);
+
+ if (multi)
+ trans.transform (*schema, "", true);
+ else
+ trans.transform (*schema, tu, true);
}
catch (Transformations::Anonymous::Failed const&)
{
@@ -698,7 +767,11 @@ main (Int argc, Char* argv[])
//
{
Transformations::Simplifier trans;
- trans.transform (*schema, tu);
+
+ if (multi)
+ trans.transform (*schema, "");
+ else
+ trans.transform (*schema, tu);
}
// Calculate type sizes.
@@ -707,7 +780,12 @@ main (Int argc, Char* argv[])
{
try
{
- CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, tu);
+ if (multi)
+ CXX::Hybrid::Generator::calculate_size (
+ *h_ops, *schema, "", disabled_w);
+ else
+ CXX::Hybrid::Generator::calculate_size (
+ *h_ops, *schema, tu, disabled_w);
}
catch (CXX::Hybrid::Generator::Failed const&)
{
@@ -721,7 +799,11 @@ main (Int argc, Char* argv[])
try
{
Processing::Inheritance::Processor proc;
- proc.process (*schema, tu, gen_hybrid ? "fixed" : 0);
+
+ if (multi)
+ proc.process (*schema, "", gen_hybrid ? "fixed" : 0);
+ else
+ proc.process (*schema, tu, gen_hybrid ? "fixed" : 0);
}
catch (Processing::Inheritance::Processor::Failed const&)
{
@@ -735,7 +817,11 @@ main (Int argc, Char* argv[])
try
{
Transformations::Restriction trans;
- trans.transform (*schema, tu);
+
+ if (multi)
+ trans.transform (*schema, "");
+ else
+ trans.transform (*schema, tu);
}
catch (Transformations::Restriction::Failed const&)
{
@@ -743,6 +829,47 @@ main (Int argc, Char* argv[])
}
}
+ // Get the first schema and assign names in additional
+ // schemas.
+ //
+ SemanticGraph::Schema* root;
+
+ if (multi)
+ {
+ using SemanticGraph::Schema;
+
+ Schema::UsesIterator b (schema->uses_begin ());
+ ++b; // Implied XML Schema namespace.
+
+ // The first schema. Will be handled later.
+ //
+ root = &b->schema ();
+ ++b;
+
+ for (Schema::UsesIterator e (schema->uses_end ()); b != e; ++b)
+ {
+ SemanticGraph::Schema& s (b->schema ());
+ SemanticGraph::Path f (b->path ());
+
+ if (gen_hybrid)
+ CXX::Hybrid::Generator::process_tree_names (*h_ops, s, f);
+
+ if (gen_parser)
+ CXX::Parser::Generator::process_names (*p_ops, s, f);
+
+ if (gen_serializer)
+ CXX::Serializer::Generator::process_names (*s_ops, s, f);
+
+ if (gen_hybrid && gen_parser)
+ CXX::Hybrid::Generator::process_parser_names (*h_ops, s, f);
+
+ if (gen_hybrid && gen_serializer)
+ CXX::Hybrid::Generator::process_serializer_names (*h_ops, s, f);
+ }
+ }
+ else
+ root = schema.get ();
+
// Generate mapping.
//
TypeMap::Namespaces parser_type_map, serializer_type_map;
@@ -753,7 +880,7 @@ main (Int argc, Char* argv[])
{
sloc += CXX::Hybrid::Generator::generate_tree (
*h_ops,
- *schema,
+ *root,
tu,
disabled_w,
parser_type_map,
@@ -775,7 +902,7 @@ main (Int argc, Char* argv[])
{
sloc += CXX::Parser::Generator::generate (
*p_ops,
- *schema,
+ *root,
tu,
parser_type_map,
true,
@@ -797,7 +924,7 @@ main (Int argc, Char* argv[])
{
sloc += CXX::Serializer::Generator::generate (
*s_ops,
- *schema,
+ *root,
tu,
serializer_type_map,
true,
@@ -821,7 +948,7 @@ main (Int argc, Char* argv[])
{
sloc += CXX::Hybrid::Generator::generate_parser (
*h_ops,
- *schema,
+ *root,
tu,
disabled_w,
file_list,
@@ -841,7 +968,7 @@ main (Int argc, Char* argv[])
{
sloc += CXX::Hybrid::Generator::generate_serializer (
*h_ops,
- *schema,
+ *root,
tu,
disabled_w,
file_list,
@@ -925,7 +1052,8 @@ main (Int argc, Char* argv[])
{
try
{
- CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, "");
+ CXX::Hybrid::Generator::calculate_size (
+ *h_ops, *schema, "", disabled_w);
}
catch (CXX::Hybrid::Generator::Failed const&)
{