Section 4.9, "Polymorphic
+ it is polymorphic (see Section 4.10, "Polymorphic
Object Models" for details)
@@ -1827,10 +1846,9 @@ private:
variable-length because it contains a sequence of person
elements (maxOccurs="unbounded"
). If we recompile
the people.xsd
schema with the --no-stl
- option, the first two types will also become variable-length
- since gender
inherits from and person
- contains elements of the string
built-in type. And
- when STL is disabled, string
is variable-length.
+ option, the person
type will also become variable-length
+ since it contains elements of the string
built-in type.
+ And when STL is disabled, string
is variable-length.
The object model uses different methods for storing and passing
around fixed-length and variable-length types. Instances of
@@ -1932,7 +1950,81 @@ s->permanent (per) // Assumes ownership or per.
s->contract (con) // Assumes ownership or con.
-
+
+
+ By default, string-based types that use XML Schema restriction by
+ enumeration are mapped to C++ classes with semantics similar to
+ C++ enum (you can suppress this mapping and instead get the plain
+ inheritance by specifying the --suppress-enum
compiler
+ option). The following code fragment again shows the C++ class that
+ was generated for the gender
XML Schema type presented
+ at the beginning of this chapter:
+
+
+// gender (fixed-length)
+//
+class gender
+{
+public:
+ enum value_type
+ {
+ male,
+ female
+ };
+
+ gender ();
+ gender (value_type);
+ gender (const gender&);
+ gender& operator= (const gender&);
+
+ void
+ value (value_type);
+
+ operator value_type () const;
+
+ const char*
+ string () const;
+
+private:
+ value_type v_;
+};
+
+
+ The gender
class defines the underlying C++ enum type
+ (value_type
) with enumerators corresponding to the
+ enumeration
elements in XML Schema. The class also
+ defines the default constructor, copy constructor, constructor
+ with the underlying enum type as its argument, and the assignment
+ operator. The gender
class also supports the implicit
+ conversion to the underlying enum type and the explicit conversion
+ to string via the string()
function. Finally, it
+ provides the value()
modifier function which allows you
+ to set the underlying enum value explicitly. Note also that such an
+ enumeration class is always fixed-length since it only contains the
+ C++ enum value. The following example shows how we can use the
+ gender
class:
+
+
+gender g = gender::male;
+g = gender::female;
+g.value (gender::female); // Same as above.
+
+cerr << g.string () << endl;
+
+if (g != gender::male)
+ ...
+
+switch (g)
+{
+case gender::male:
+ ...
+case gender::female:
+ ...
+}
+
+
+
+
As we have seen before, XSD/e generates a different
set of member functions for elements with different cardinalities.
@@ -1945,7 +2037,7 @@ s->contract (con) // Assumes ownership or con.
example, the first-name
, last-name
,
gender
, and age
elements as well as
the id
attribute belong to this cardinality class.
- The following code fragment shows again the accessor and modifier
+ The following code fragment again shows the accessor and modifier
functions that are generated for the first-name
element
in the person
class:
@@ -1975,7 +2067,7 @@ class person
The optional cardinality class covers all elements that
can occur zero or one time as well as optional attributes. In our
example, the middle-name
element belongs to this
- cardinality class. The following code fragment shows again the
+ cardinality class. The following code fragment again shows the
accessor and modifier functions that are generated for this element
in the person
class:
@@ -2664,13 +2756,13 @@ namespace xml_schema
}
-
+
The XML Schema language provides three compositor constructs that
are used to group elements: all
, sequence
,
and choice
. If a compositor has an optional
- or sequence cardinality class (see Section
- 4.3, "Attributes and Elements") or if a compositor is
+ or sequence cardinality class (see Section
+ 4.4, "Attributes and Elements") or if a compositor is
inside choice
, then the C++/Hybrid mapping generates
a nested class for such a compositor as well as a set of accessor
and modifier functions similar to the ones defined for elements
@@ -3082,7 +3174,7 @@ private:
};
-
+
In this section we will examine how to get to the information
stored in the object model for the person records vocabulary
@@ -3131,7 +3223,7 @@ main ()
// Print gender, age, and id which are all required.
//
- cout << "gender: " << p.gender () << endl
+ cout << "gender: " << p.gender ().string () << endl
<< "age: " << p.age () << endl
<< "id: " << p.id () << endl
<< endl;
@@ -3174,7 +3266,7 @@ id: 2
-
+
In this section we will examine how to modify the information
stored in the object model for our person records vocabulary.
@@ -3284,7 +3376,7 @@ main ()
</people>
-
+
In this section we will examine how to create a new object model
for our person records vocabulary. The following application
@@ -3311,13 +3403,10 @@ main ()
person p;
p.first_name ("John");
p.last_name ("Doe");
+ p.gender (gender::male);
p.age (32);
p.id (1);
- gender g;
- g.assign ("male");
- p.gender (g);
-
ps.push_back (p);
}
@@ -3328,13 +3417,10 @@ main ()
p.first_name ("Jane");
p.middle_name ("Mary");
p.last_name ("Doe");
+ p.gender (gender::female);
p.age (28);
p.id (2);
- gender g;
- g.assign ("male");
- p.gender (g);
-
ps.push_back (p);
}
@@ -3385,7 +3471,7 @@ main ()
</people>
-
+
Sometimes it is desirable to add extra, application-specific
data or functionality to some object model classes or
@@ -3809,7 +3895,7 @@ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
-
+
When generating polymorphism-aware code (see Section
3.7, "Support for Polymorphism"), some objects
@@ -4673,7 +4759,7 @@ namespace xml_schema
The NMTOKENS
and IDREFS
built-in
XML Schema types are mapped to the string sequence type which
- is discussed in Section 4.3, "Attributes and
+ is discussed in Section 4.4, "Attributes and
Elements".
@@ -5783,7 +5869,7 @@ main (int argc, char* argv[])
{
cerr << "first: " << i->first_name () << endl
<< "last: " << i->last_name () << endl
- << "gender: " << i->gender () << endl
+ << "gender: " << i->gender ().string () << endl
<< "age: " << i->age () << endl
<< endl;
}
@@ -5795,9 +5881,7 @@ main (int argc, char* argv[])
// Initialize the filter.
//
- gender g;
- g.assign ("female");
- root_s.gender_filter (g);
+ root_s.gender_filter (gender::female);
xml_schema::document_simpl doc_s (root_s, people_s.root_name ());
diff --git a/documentation/xsde.1 b/documentation/xsde.1
index 5d4d5cf..90637e0 100644
--- a/documentation/xsde.1
+++ b/documentation/xsde.1
@@ -948,6 +948,9 @@ Suppress the generation of validation code in serializer.
Omit attributes with default and fixed values from serialized XML
documents.
+.IP "\fB\--suppress-enum\fR"
+Suppress the generation of the XML Schema enumeration to C++ enum mapping.
+
.IP "\fB\--generate-detach\fR"
Generate detach functions for elements and attributes of variable-length
types. These functions, for example, allow you to move sub-trees in the
diff --git a/documentation/xsde.xhtml b/documentation/xsde.xhtml
index c4c8995..11a90f5 100644
--- a/documentation/xsde.xhtml
+++ b/documentation/xsde.xhtml
@@ -820,6 +820,10 @@
Omit attributes with default and fixed values from serialized
XML documents.
+ --suppress-enum
+ Suppress the generation of the XML Schema enumeration to C++
+ enum mapping.
+
--generate-detach
Generate detach functions for elements and attributes of
variable-length types. These functions, for example, allow
diff --git a/examples/cxx/hybrid/filter/driver.cxx b/examples/cxx/hybrid/filter/driver.cxx
index 67efb60..46017ab 100644
--- a/examples/cxx/hybrid/filter/driver.cxx
+++ b/examples/cxx/hybrid/filter/driver.cxx
@@ -54,7 +54,7 @@ main (int argc, char* argv[])
{
cerr << "first: " << i->first_name () << endl
<< "last: " << i->last_name () << endl
- << "gender: " << i->gender () << endl
+ << "gender: " << i->gender ().string () << endl
<< "age: " << i->age () << endl
<< endl;
}
@@ -66,9 +66,7 @@ main (int argc, char* argv[])
// Initialize the filter.
//
- gender g;
- g.assign ("female");
- root_s.gender_filter (g);
+ root_s.gender_filter (gender::female);
xml_schema::document_simpl doc_s (root_s, people_s.root_name ());
diff --git a/examples/cxx/hybrid/library/driver.cxx b/examples/cxx/hybrid/library/driver.cxx
index 5aa406e..41e3e1b 100644
--- a/examples/cxx/hybrid/library/driver.cxx
+++ b/examples/cxx/hybrid/library/driver.cxx
@@ -56,7 +56,7 @@ main (int argc, char* argv[])
{
cerr << "ISBN : " << i->isbn () << endl
<< "Title : " << i->title () << endl
- << "Genre : " << i->genre () << endl;
+ << "Genre : " << i->genre ().string () << endl;
for (book::author_const_iterator j = i->author ().begin ();
j != i->author ().end ();
@@ -108,9 +108,7 @@ main (int argc, char* argv[])
t.assign ("Dead Souls");
b->title (t);
- genre g;
- g.assign ("philosophy");
- b->genre (g);
+ b->genre (genre::philosophy);
author a;
a.name ("Nikolai Gogol");
diff --git a/examples/cxx/hybrid/minimal/driver.cxx b/examples/cxx/hybrid/minimal/driver.cxx
index 6573237..cb13edf 100644
--- a/examples/cxx/hybrid/minimal/driver.cxx
+++ b/examples/cxx/hybrid/minimal/driver.cxx
@@ -160,7 +160,7 @@ main (int argc, char* argv[])
printf ("first: %s\n" "last: %s\n" "gender: %s\n" "age: %hu\n\n",
i->first_name (),
i->last_name (),
- i->gender ().base_value (),
+ i->gender ().string (),
i->age ());
}
@@ -181,10 +181,7 @@ main (int argc, char* argv[])
p->first_name (strdupx ("Joe"));
p->last_name (strdupx ("Dirt"));
p->age (36);
-
- gender* g = new gender;
- g->base_value (strdupx ("male"));
- p->gender (g);
+ p->gender (gender::male);
ps.insert (ps.begin (), p);
}
diff --git a/tests/cxx/hybrid/enumeration/driver.cxx b/tests/cxx/hybrid/enumeration/driver.cxx
new file mode 100644
index 0000000..ffbbf0b
--- /dev/null
+++ b/tests/cxx/hybrid/enumeration/driver.cxx
@@ -0,0 +1,97 @@
+// file : tests/cxx/hybrid/enumeration/driver.cxx
+// author : Boris Kolpackov
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test XML Schema enumeration to C++ enum mapping.
+//
+
+#include
+#include
+
+#include "test.hxx"
+#include "test-pimpl.hxx"
+#include "test-simpl.hxx"
+
+using namespace std;
+using namespace test;
+
+int
+main (int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " test.xml" << endl;
+ return 1;
+ }
+
+ // Parse.
+ //
+ root_paggr root_p;
+
+ xml_schema::document_pimpl doc_p (
+ root_p.root_parser (),
+ root_p.root_namespace (),
+ root_p.root_name ());
+
+ root_p.pre ();
+ doc_p.parse (argv[1]);
+ type* r = root_p.post ();
+
+ // Test the mapping.
+ //
+ {
+ simple x;
+ x = simple::a;
+ assert (x == simple::a);
+
+ x.value (simple::b);
+ assert (x == simple::b);
+
+ simple y (simple::c);
+
+ switch (y)
+ {
+ case simple::c:
+ {
+ break;
+ }
+ default:
+ assert (false);
+ }
+ }
+
+ {
+ final x (final::c);
+ assert (x == final::c);
+
+ simple s = x;
+ assert (s == simple::c);
+ }
+
+ {
+ complex c;
+ c.value (complex::a);
+ assert (c == complex::a);
+
+ simple s = c;
+ assert (s == simple::a);
+ }
+
+ // Serialize.
+ //
+ root_saggr root_s;
+
+ xml_schema::document_simpl doc_s (
+ root_s.root_serializer (),
+ root_s.root_namespace (),
+ root_s.root_name ());
+
+ doc_s.add_prefix ("t", "test");
+
+ root_s.pre (*r);
+ doc_s.serialize (cout);
+ root_s.post ();
+
+ delete r;
+}
diff --git a/tests/cxx/hybrid/enumeration/makefile b/tests/cxx/hybrid/enumeration/makefile
new file mode 100644
index 0000000..a7a6b3c
--- /dev/null
+++ b/tests/cxx/hybrid/enumeration/makefile
@@ -0,0 +1,109 @@
+# file : tests/cxx/hybrid/enumeration/makefile
+# author : Boris Kolpackov
+# copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+xsd := test.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,\
+$(cxx:.cxx=.o) \
+$(xsd:.xsd=.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
+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) $(dist) $(dist-win): xsde_options += --generate-parser \
+--generate-serializer --generate-aggregate --custom-data simple-cd \
+--custom-data fbvd
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(driver)
+
+
+# Test.
+#
+$(test): driver := $(driver)
+$(test): $(driver) $(src_base)/test-000.xml $(src_base)/test-000.std
+ $(call message,test $$1,$$1 $(src_base)/test-000.xml | diff -u $(src_base)/test-000.std -,$(driver))
+
+
+# Dist.
+#
+$(dist) $(dist-win): opt := -src $(src_base) -cmd cxx-hybrid -xsd "$(xsd)" \
+-cxx "$(cxx)" -gen "$(genf)" -opt "$(xsde_options)" -out $(dist_prefix)
+
+$(dist):
+ $(call message,install $(src_base),$(scf_root)/dist $(opt))
+
+$(dist-win):
+ $(call message,install $(src_base),$(scf_root)/dist -win $(opt))
+
+
+# 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/enumeration/test-000.std b/tests/cxx/hybrid/enumeration/test-000.std
new file mode 100644
index 0000000..8bb771a
--- /dev/null
+++ b/tests/cxx/hybrid/enumeration/test-000.std
@@ -0,0 +1 @@
+ababacacabacac
\ No newline at end of file
diff --git a/tests/cxx/hybrid/enumeration/test-000.xml b/tests/cxx/hybrid/enumeration/test-000.xml
new file mode 100644
index 0000000..6db0a36
--- /dev/null
+++ b/tests/cxx/hybrid/enumeration/test-000.xml
@@ -0,0 +1,24 @@
+
+
+ a
+ b
+
+ a
+ b
+
+ a
+ c
+
+ a
+ c
+
+ a
+ b
+
+ a
+ c
+
+ a
+ c
+
+
diff --git a/tests/cxx/hybrid/enumeration/test.xsd b/tests/cxx/hybrid/enumeration/test.xsd
new file mode 100644
index 0000000..782c707
--- /dev/null
+++ b/tests/cxx/hybrid/enumeration/test.xsd
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/cxx/hybrid/polymorphism/enumeration/driver.cxx b/tests/cxx/hybrid/polymorphism/enumeration/driver.cxx
new file mode 100644
index 0000000..b2c9429
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/enumeration/driver.cxx
@@ -0,0 +1,67 @@
+// file : tests/cxx/hybrid/polymorphism/enumeration/driver.cxx
+// author : Boris Kolpackov
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+// Test XML Schema enumeration to C++ enum mapping.
+//
+
+#include
+
+#include "test.hxx"
+#include "test-pimpl.hxx"
+#include "test-simpl.hxx"
+
+using namespace std;
+using namespace test;
+
+int
+main (int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " test.xml" << endl;
+ return 1;
+ }
+
+ // Parse.
+ //
+ root_paggr root_p;
+
+ xml_schema::document_pimpl doc_p (
+ root_p.root_parser (),
+ root_p.root_namespace (),
+ root_p.root_name (),
+ true);
+
+ root_p.pre ();
+ doc_p.parse (argv[1]);
+ type* r = root_p.post ();
+
+ // Test the mapping.
+ //
+ simple s (simple::a);
+ s.value (simple::b);
+
+ complex c;
+ c.value (complex::a);
+
+ // 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/enumeration/makefile b/tests/cxx/hybrid/polymorphism/enumeration/makefile
new file mode 100644
index 0000000..fbd4337
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/enumeration/makefile
@@ -0,0 +1,110 @@
+# file : tests/cxx/hybrid/polymorphism/enumeration/makefile
+# author : Boris Kolpackov
+# copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make
+
+xsd := test.xsd
+cxx := driver.cxx
+
+obj := $(addprefix $(out_base)/,\
+$(cxx:.cxx=.o) \
+$(xsd:.xsd=.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
+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) $(dist) $(dist-win): xsde_options += --generate-parser \
+--generate-serializer --generate-aggregate --custom-data simple-cd \
+--custom-data fbvd --generate-polymorphic --generate-typeinfo \
+--polymorphic-type base --polymorphic-type simple
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(driver)
+
+
+# Test.
+#
+$(test): driver := $(driver)
+$(test): $(driver) $(src_base)/test-000.xml $(src_base)/test-000.std
+ $(call message,test $$1,$$1 $(src_base)/test-000.xml | diff -u $(src_base)/test-000.std -,$(driver))
+
+
+# Dist.
+#
+$(dist) $(dist-win): opt := -src $(src_base) -cmd cxx-hybrid -xsd "$(xsd)" \
+-cxx "$(cxx)" -gen "$(genf)" -opt "$(xsde_options)" -out $(dist_prefix)
+
+$(dist):
+ $(call message,install $(src_base),$(scf_root)/dist $(opt))
+
+$(dist-win):
+ $(call message,install $(src_base),$(scf_root)/dist -win $(opt))
+
+
+# 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/enumeration/test-000.std b/tests/cxx/hybrid/polymorphism/enumeration/test-000.std
new file mode 100644
index 0000000..ecb1b29
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/enumeration/test-000.std
@@ -0,0 +1 @@
+ababbcc
\ No newline at end of file
diff --git a/tests/cxx/hybrid/polymorphism/enumeration/test-000.xml b/tests/cxx/hybrid/polymorphism/enumeration/test-000.xml
new file mode 100644
index 0000000..b43342e
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/enumeration/test-000.xml
@@ -0,0 +1,13 @@
+
+
+ a
+ b
+
+ a
+ b
+
+ b
+ c
+ c
+
+
diff --git a/tests/cxx/hybrid/polymorphism/enumeration/test.xsd b/tests/cxx/hybrid/polymorphism/enumeration/test.xsd
new file mode 100644
index 0000000..235990c
--- /dev/null
+++ b/tests/cxx/hybrid/polymorphism/enumeration/test.xsd
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/cxx/hybrid/polymorphism/makefile b/tests/cxx/hybrid/polymorphism/makefile
index 72f0c87..703ef9a 100644
--- a/tests/cxx/hybrid/polymorphism/makefile
+++ b/tests/cxx/hybrid/polymorphism/makefile
@@ -5,12 +5,15 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
-all_tests := multischema
+# NOTE: remember to update dist/tests/cxx/hybrid/polymorphis/{makefile,
+# nmakefile} if you change anything here.
+#
+all_tests := enumeration multischema
build_tests :=
ifeq ($(xsde_iostream),y)
-build_tests += multischema
+build_tests += enumeration multischema
endif
default := $(out_base)/
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx
index 509005a..4e86e41 100644
--- a/xsde/cxx/hybrid/cli.hxx
+++ b/xsde/cxx/hybrid/cli.hxx
@@ -34,6 +34,7 @@ namespace CXX
extern Key suppress_parser_val;
extern Key suppress_serializer_val;
extern Key omit_default_attributes;
+ extern Key suppress_enum;
extern Key generate_detach;
extern Key generate_insertion;
extern Key generate_extraction;
@@ -122,6 +123,7 @@ namespace CXX
suppress_parser_val, Boolean,
suppress_serializer_val, Boolean,
omit_default_attributes, Boolean,
+ suppress_enum, Boolean,
generate_detach, Boolean,
generate_insertion, Cult::Containers::Vector,
generate_extraction, Cult::Containers::Vector,
diff --git a/xsde/cxx/hybrid/default-value.cxx b/xsde/cxx/hybrid/default-value.cxx
index e232eae..6abfb05 100644
--- a/xsde/cxx/hybrid/default-value.cxx
+++ b/xsde/cxx/hybrid/default-value.cxx
@@ -578,6 +578,38 @@ namespace CXX
}
Void InitValue::
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ using SemanticGraph::Enumerator;
+ using SemanticGraph::Enumeration;
+
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Enumeration* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast (e));
+ return;
+ }
+
+ Enumeration& x (base_enum ? *base_enum : e);
+
+ os << member_ << x.context ().get ("value") << "(";
+
+ Enumeration::NamesIteratorPair ip (x.find (value_));
+
+ if (ip.first != ip.second)
+ {
+ Enumerator& er (dynamic_cast (ip.first->named ()));
+ os << fq_name (e) << "::" << ename (er);
+ }
+
+ os << ");";
+ }
+
+ Void InitValue::
traverse (SemanticGraph::Type& t)
{
// This is a fall-back case where we handle all other (literal)
@@ -1213,6 +1245,21 @@ namespace CXX
}
Void CompareValue::
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ traverse (static_cast (e));
+ return;
+ }
+
+ os << *lhs_ << " == " << *rhs_;
+ }
+
+ Void CompareValue::
traverse (SemanticGraph::Type&)
{
// This is a fall-back case where we handle all other types.
diff --git a/xsde/cxx/hybrid/default-value.hxx b/xsde/cxx/hybrid/default-value.hxx
index b9f902c..46a6bf0 100644
--- a/xsde/cxx/hybrid/default-value.hxx
+++ b/xsde/cxx/hybrid/default-value.hxx
@@ -163,6 +163,7 @@ namespace CXX
struct InitValue: Traversal::List,
Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Traversal::Type,
Traversal::AnySimpleType,
@@ -217,6 +218,9 @@ namespace CXX
traverse (SemanticGraph::Complex&);
virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
traverse (SemanticGraph::Type& t);
// anySimpleType.
@@ -337,6 +341,7 @@ namespace CXX
struct CompareValue: Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Traversal::Type,
Context
{
@@ -354,6 +359,9 @@ namespace CXX
traverse (SemanticGraph::Complex&);
virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
traverse (SemanticGraph::Type& t);
private:
diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx
index 6db57ff..eba0880 100644
--- a/xsde/cxx/hybrid/elements.cxx
+++ b/xsde/cxx/hybrid/elements.cxx
@@ -39,6 +39,7 @@ namespace CXX
detach (ops.value ()),
mixin (ops.value ()),
tiein (!mixin),
+ enum_ (!ops.value ()),
fwd_expr (fe),
hxx_expr (he),
ixx_expr (ie),
@@ -495,6 +496,34 @@ namespace CXX
return os;
}
+ Boolean Context::
+ enum_mapping (SemanticGraph::Enumeration& e,
+ SemanticGraph::Enumeration** base)
+ {
+ Boolean gen (false);
+ StringBasedType t (gen);
+ t.dispatch (e);
+
+ if (gen)
+ {
+ // The first enumeration in the inheritance hierarchy breaks
+ // inheritance. If its base is polymorphic then generating
+ // the enum mapping will most likely break things.
+ //
+ SemanticGraph::Enumeration* b (0);
+ EnumBasedType t (b);
+ t.dispatch (e);
+
+ SemanticGraph::Enumeration& first (b ? *b : e);
+ gen = !polymorphic (first.inherits ().base ());
+
+ if (gen && base)
+ *base = b;
+ }
+
+ return gen;
+ }
+
// Namespace
//
Namespace::
diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx
index 5a94dda..77b91a2 100644
--- a/xsde/cxx/hybrid/elements.hxx
+++ b/xsde/cxx/hybrid/elements.hxx
@@ -48,6 +48,7 @@ namespace CXX
typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
+ enum_ (c.enum_),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
@@ -78,6 +79,7 @@ namespace CXX
typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
+ enum_ (c.enum_),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
@@ -572,6 +574,13 @@ namespace CXX
open_ns ();
public:
+ // Determine whether we are generating the enum mapping for this
+ // enumeration. Also optionally return the base enum.
+ //
+ static Boolean
+ enum_mapping (SemanticGraph::Enumeration& e,
+ SemanticGraph::Enumeration** base = 0);
+ public:
typedef
Cult::Containers::Deque
NamespaceStack;
@@ -588,6 +597,7 @@ namespace CXX
Boolean typeinfo;
Boolean mixin;
Boolean tiein;
+ Boolean enum_;
Regex const* fwd_expr;
Regex const* hxx_expr;
@@ -871,6 +881,124 @@ namespace CXX
Boolean& r_;
};
+ // Check whether this is a string-based type (excluding ID, IDFER,
+ // anyURI, and ENTITY).
+ //
+ struct StringBasedType: Traversal::Complex,
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language
+ {
+ StringBasedType (Boolean& r)
+ : r_ (r)
+ {
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ Traversal::Inherits inherits_;
+ };
+
+
+ // Check whether this is a enumeration-based type.
+ //
+ struct EnumBasedType: Traversal::Complex
+ {
+ EnumBasedType (SemanticGraph::Enumeration*& e)
+ : enum_ (e)
+ {
+ *this >> inherits_;
+
+ inherits_ >> *this;
+ inherits_ >> enum_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ private:
+ struct Enumeration: Traversal::Enumeration
+ {
+ Enumeration (SemanticGraph::Enumeration*& e)
+ : e_ (e)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e_ == 0)
+ e_ = &e;
+ }
+
+ private:
+ SemanticGraph::Enumeration*& e_;
+ };
+
+
+ private:
+ Enumeration enum_;
+ Traversal::Inherits inherits_;
+ };
+
//
//
diff --git a/xsde/cxx/hybrid/extraction-header.cxx b/xsde/cxx/hybrid/extraction-header.cxx
index dc729f6..e2ed714 100644
--- a/xsde/cxx/hybrid/extraction-header.cxx
+++ b/xsde/cxx/hybrid/extraction-header.cxx
@@ -14,6 +14,47 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (istreams.begin ());
+ i != istreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator>> (" << istream (*i) << "&," << endl
+ << name << "&);"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -256,6 +297,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -263,6 +305,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx
index 5460740..e829760 100644
--- a/xsde/cxx/hybrid/extraction-source.cxx
+++ b/xsde/cxx/hybrid/extraction-source.cxx
@@ -14,6 +14,60 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (istreams.begin ());
+ i != istreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator>> (" << istream (*i) << "& s," << endl
+ << name << "& x)"
+ << "{"
+ << "unsigned int i;";
+
+ if (exceptions)
+ os << "s >> i;";
+ else
+ os << "if (!(s >> i))" << endl
+ << "return false;";
+
+ os << "x = static_cast< " << name << "::" <<
+ e.context ().get ("value-type") << " > (i);"
+ << (exceptions ? "" : "return true;")
+ << "}"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -1102,6 +1156,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -1109,6 +1164,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
index 78b9142..c7dcb1d 100644
--- a/xsde/cxx/hybrid/generator.cxx
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -122,6 +122,7 @@ namespace CXX
extern Key suppress_parser_val = "suppress-parser-val";
extern Key suppress_serializer_val = "suppress-serializer-val";
extern Key omit_default_attributes = "omit-default-attributes";
+ extern Key suppress_enum = "suppress-enum";
extern Key generate_detach = "generate-detach";
extern Key generate_insertion = "generate-insertion";
extern Key generate_extraction = "generate-extraction";
@@ -257,6 +258,11 @@ namespace CXX
<< " from serialized XML documents."
<< endl;
+ e << "--suppress-enum" << endl
+ << " Suppress the generation of the XML Schema\n"
+ << " enumeration to C++ enum mapping."
+ << endl;
+
e << "--generate-detach" << endl
<< " Generate detach functions for elements and\n"
<< " attributes of variable-length types."
diff --git a/xsde/cxx/hybrid/insertion-header.cxx b/xsde/cxx/hybrid/insertion-header.cxx
index 4898c02..b1a4dbe 100644
--- a/xsde/cxx/hybrid/insertion-header.cxx
+++ b/xsde/cxx/hybrid/insertion-header.cxx
@@ -14,6 +14,47 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (ostreams.begin ());
+ i != ostreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator<< (" << ostream (*i) << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -256,6 +297,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -263,6 +305,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx
index 7dc6fcb..7fce9ee 100644
--- a/xsde/cxx/hybrid/insertion-source.cxx
+++ b/xsde/cxx/hybrid/insertion-source.cxx
@@ -14,6 +14,51 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (ostreams.begin ());
+ i != ostreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator<< (" << ostream (*i) << "& s," << endl
+ << "const " << name << "& x)"
+ << "{"
+ << "unsigned int i = x;"
+ << (exceptions ? "" : "return ") << "s << i;"
+ << "}"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -721,6 +766,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -728,6 +774,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx
index c174df4..d8948d7 100644
--- a/xsde/cxx/hybrid/parser-header.cxx
+++ b/xsde/cxx/hybrid/parser-header.cxx
@@ -14,6 +14,194 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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;
+ }
+ }
+ }
+ };
+
+ //
+ //
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), post_override_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (epimpl_custom (e));
+
+ // We may not need to generate the class if this parser is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean fl (fixed_length (e));
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << epskel (e);
+
+ // Derive from base pimpl even if base_enum == 0. This is done
+ // so that we have implementations for all the (otherwise pure
+ // virtual) post_*() functions.
+ //
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (b, "p:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (!fl || tiein)
+ os << name << " (" << (fl ? "" : "bool = false") << ");"
+ << endl;
+
+ if (!fl)
+ {
+ // d-tor
+ //
+ os << "~" << name << " ();"
+ << endl;
+
+ // reset
+ //
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // _characters
+ //
+ if (!base_enum)
+ os << "virtual void" << endl
+ << "_characters (const " << string_type << "&);"
+ << endl;
+
+ // post
+ //
+ String const& ret (pret_type (e));
+
+ if (polymorphic (e))
+ post_override_.dispatch (e);
+
+ os << "virtual " << ret << endl
+ << post_name (e) << " ();"
+ << endl;
+
+ String const& type (fq_name (e));
+
+ // pre_impl
+ //
+ if (!fl)
+ os << (tiein ? "public:" : "protected:") << endl
+ << "void" << endl
+ << pre_impl_name (e) << " (" << type << "*);"
+ << endl;
+
+ // Base implementation.
+ //
+ if (tiein && base_enum)
+ os << (tiein ? "public:" : "protected:") << endl
+ << fq_name (b, "p:impl") << " base_impl_;"
+ << endl;
+
+ // State.
+ //
+ if (!fl || !base_enum)
+ {
+ String const& state_type (epstate_type (e));
+
+ os << (tiein ? "public:" : "protected:") << endl
+ << "struct " << state_type
+ << "{";
+
+ if (!fl)
+ os << type << "* " << "x_;";
+
+ if (!base_enum)
+ {
+ if (stl)
+ os << "::std::string str_;";
+ else
+ os << "::xsde::cxx::string str_;";
+ }
+
+ os << "};"
+ << state_type << " " << epstate (e) << ";";
+ }
+
+ if (!fl)
+ os << "bool " << epstate_base (e) << ";";
+
+ os << "};";
+ }
+
+ // Generate include for custom parser.
+ //
+ if (e.context ().count ("p:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ e.context ().get ("p:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PostOverride post_override_;
+ };
+
struct List: Traversal::List, Context
{
List (Context& c)
@@ -352,35 +540,6 @@ 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;
- }
- }
- }
- };
-
- //
- //
struct Complex : Traversal::Complex, Context
{
Complex (Context& c)
@@ -624,10 +783,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx
index c635aec..819280f 100644
--- a/xsde/cxx/hybrid/parser-name-processor.cxx
+++ b/xsde/cxx/hybrid/parser-name-processor.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include
+#include
#include
#include
@@ -251,6 +252,61 @@ namespace CXX
//
//
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (options.value () ||
+ !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use p:impl-base instead of p:impl.
+ // If the name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("p:impl-base")
+ ? ec.get ("p:impl-base")
+ : ec.get ("p:impl"));
+ if (!name)
+ return;
+
+ Boolean fl (fixed_length (e));
+
+ NameSet set;
+ set.insert (name);
+
+ if (!fl || !base_enum)
+ {
+ String state_type (find_name (name + L"_state", set));
+ ec.set ("pstate-type", state_type);
+ ec.set ("pstate", find_name (state_type, "_", set));
+ }
+
+ if (!fl)
+ ec.set ("pstate-base", find_name (name + L"_base", "_", set));
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -708,10 +764,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
ns_names >> list;
ns_names >> union_;
ns_names >> complex;
+ ns_names >> enumeration;
schema.dispatch (tu);
}
diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx
index c877e1d..e5bbb90 100644
--- a/xsde/cxx/hybrid/parser-source.cxx
+++ b/xsde/cxx/hybrid/parser-source.cxx
@@ -14,6 +14,423 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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 Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ using SemanticGraph::Enumeration;
+
+ Enumeration& s (dynamic_cast (e.scope ()));
+
+ os << "if (strcmp (s, " <<
+ strlit (e.name ()) << ") == 0)" << endl
+ << "v = " << fq_name (s) << "::" << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ post_override_ (c),
+ enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (epimpl_custom (e));
+
+ if (!name)
+ return;
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ Boolean fl (fixed_length (e));
+
+ SemanticGraph::Context& ec (e.context ());
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ String const& type (fq_name (e));
+ String state;
+
+ if (!fl || !base_enum)
+ state = epstate (e);
+
+ // c-tor
+ //
+ if (!fl || tiein)
+ {
+ os << name << "::" << endl
+ << name << " (" << (fl ? "" : "bool b") << ")";
+
+ if (tiein)
+ os << endl
+ << ": " << epskel (e) << " (" <<
+ (base_enum ? "&base_impl_" : "0") << ")";
+
+ if (base_enum && !fixed_length (b))
+ {
+ if (tiein)
+ os << "," << endl
+ << " base_impl_" << " (true)";
+ else
+ os << endl
+ << ": " << fq_name (b, "p:impl") << " (true)";
+ }
+
+ os << "{";
+
+ if (!fl)
+ {
+ os << "this->" << epstate_base (e) << " = b;"
+ << "this->" << state << ".x_ = 0;";
+ }
+
+ os << "}";
+ }
+
+ if (!fl)
+ {
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "if (!this->" << epstate_base (e) << ")" << endl
+ << "delete this->" << state << ".x_;"
+ << "}";
+
+ // reset
+ //
+ if (reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ if (mixin && base_enum)
+ os << epimpl (b) << "::_reset ();";
+
+ os << epskel (e) << "::_reset ();"
+ << endl;
+
+ os << "if (!this->" << epstate_base (e) << ")"
+ << "{"
+ << "delete this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "}"
+ << "}";
+ }
+ }
+
+ // pre_impl
+ //
+ if (!fl)
+ {
+ os << "void " << name << "::" << endl
+ << pre_impl_name (e) << " (" << type << "* x)"
+ << "{"
+ << "this->" << state << ".x_ = x;";
+
+ // Call base pre_impl (var-length) or pre (fix-length).
+ //
+ if (base_enum)
+ {
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ if (fixed_length (b))
+ os << "pre ();";
+ else
+ os << pre_impl_name (b) << " (x);";
+ }
+
+ // Clear the string buffer.
+ //
+ if (!base_enum)
+ {
+ if (stl)
+ os << "this->" << state << ".str_.clear ();";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.assign (\"\", 0);";
+ else
+ {
+ os << endl
+ << "if (this->" << state << ".str_.assign (\"\", 0))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+ }
+
+ os << "}";
+ }
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (fl)
+ {
+ if (base_enum)
+ {
+ // Our base is also fixed-length so call its pre()
+ //
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << "pre ();";
+ }
+
+ // Clear the string buffer.
+ //
+ if (!base_enum)
+ {
+ if (stl)
+ os << "this->" << state << ".str_.clear ();";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.assign (\"\", 0);";
+ else
+ {
+ os << endl
+ << "if (this->" << state << ".str_.assign (\"\", 0))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+ }
+ }
+ else
+ {
+ if (exceptions)
+ os << "this->" << pre_impl_name (e) << " (new " << type << ");";
+ else
+ os << type << "* x = new " << type << ";"
+ << "if (x)" << endl
+ << "this->" << pre_impl_name (e) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+
+ // _characters
+ //
+ if (!base_enum)
+ {
+ os << "void " << name << "::" << endl
+ << "_characters (const " << string_type << "& s)"
+ << "{";
+
+ if (stl)
+ os << "this->" << state << ".str_.append (s.data (), s.size ());";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.append (s.data (), s.size ());";
+ else
+ {
+ os << "if (this->" << state << ".str_.append (" <<
+ "s.data (), s.size ()))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+
+ os << "}";
+ }
+
+ // post
+ //
+ String const& ret (pret_type (e));
+
+ if (polymorphic (e))
+ post_override_.dispatch (e);
+
+ os << ret << " " << name << "::" << endl
+ << post_name (e) << " ()"
+ << "{";
+
+ if (base_enum)
+ {
+ if (fl)
+ {
+ os << type << " r;"
+ << "static_cast< " << fq_name (b) << "& > (r) = ";
+
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << post_name (b) << " ();";
+ }
+ else
+ {
+ os << type << "* r = this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;";
+
+ Boolean flb (fixed_length (b));
+
+ // Copy the value if our base is fixed-length.
+ //
+ if (flb)
+ os << "r->" << base_enum->context ().get ("value") <<
+ " (";
+
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << post_name (b) << " ()";
+
+ if (flb)
+ os << ")";
+
+ os << ";";
+ }
+
+ //
+ // @@ TODO: check enumerators (switch)
+ //
+ }
+ else
+ {
+ String const& vt (ec.get ("value-type"));
+
+ os << type << "::" << vt << " v = static_cast< " << type <<
+ "::" << vt << " > (0);"
+ << "const char* s = this->" << state << ".str_." <<
+ (stl ? "c_str" : "data") << " ();"
+ << endl;
+
+ names (e, names_, 0, 0, 0, &Enumeration::comma);
+
+
+ /*
+ // @@ Cannot do error checking in post.
+
+ if (!options.value () &&
+ !options.value ())
+ {
+ os << "else" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::invalid_enumeration_value);";
+ }
+ */
+
+ os << endl;
+
+ if (fl)
+ os << type << " r (v);";
+ else
+ os << type << "* r = this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "r->" << ec.get ("value") << " (v);";
+ }
+
+ os << "return r;"
+ << "}";
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "else ";
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PostOverride post_override_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -907,53 +1324,6 @@ 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)
@@ -1444,10 +1814,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx
index 153da8d..b36b910 100644
--- a/xsde/cxx/hybrid/serializer-header.cxx
+++ b/xsde/cxx/hybrid/serializer-header.cxx
@@ -14,6 +14,141 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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 Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), pre_override_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (esimpl_custom (e));
+
+ // We may not need to generate the class if this serializer is
+ // being customized.
+ //
+ if (name)
+ {
+ String const& arg (sarg_type (e));
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << esskel (e);
+
+ // Derive from base simpl even if base_enum == 0. This is done
+ // so that we have implementations for all the (otherwise pure
+ // virtual) pre() functions.
+ //
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (b, "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ os << name << " ();"
+ << endl;
+
+ // pre
+ //
+ if (polymorphic (e))
+ pre_override_.dispatch (e);
+
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+
+ // _serialize_content
+ //
+ if (!base_enum)
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+
+ // State.
+ //
+ if (!base_enum)
+ {
+ os << (tiein ? "public:" : "protected:") << endl
+ << "const " << fq_name (e) << "* " << esstate (e) << ";";
+ }
+ else if (tiein)
+ {
+ os << "public:" << endl
+ << fq_name (b, "s:impl") << " base_impl_;";
+ }
+
+ os << "};";
+ }
+
+ // Generate include for custom serializer.
+ //
+ if (e.context ().count ("s:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ e.context ().get ("s:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PreOverride pre_override_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -343,35 +478,6 @@ 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)
@@ -511,7 +617,7 @@ namespace CXX
if (tiein && hb)
- os << (tiein ? "public:" : "protected:") << endl
+ os << "public:" << endl
<< fq_name (c.inherits ().base (), "s:impl") << " base_impl_;"
<< endl;
@@ -605,10 +711,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx
index 2f7d296..159e3b0 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.cxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include
+#include
#include
#include
@@ -244,6 +245,54 @@ namespace CXX
//
//
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (options.value () ||
+ !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use s:impl-base instead of s:impl.
+ // If the name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("s:impl-base")
+ ? ec.get ("s:impl-base")
+ : ec.get ("s:impl"));
+ if (!name)
+ return;
+
+ if (!base_enum)
+ {
+ NameSet set;
+ set.insert (name);
+
+ ec.set ("sstate", find_name (name + L"_state", "_", set));
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -288,9 +337,9 @@ namespace CXX
}
virtual Void
- traverse (Type& l)
+ traverse (Type& u)
{
- SemanticGraph::Context& uc (l.context ());
+ SemanticGraph::Context& uc (u.context ());
// In case of customization use s:impl-base instead of s:impl.
// If the name is empty then we are not generating anything.
@@ -723,10 +772,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
ns_names >> list;
ns_names >> union_;
ns_names >> complex;
+ ns_names >> enumeration;
schema.dispatch (tu);
}
diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx
index 0aeaf89..1268631 100644
--- a/xsde/cxx/hybrid/serializer-source.cxx
+++ b/xsde/cxx/hybrid/serializer-source.cxx
@@ -70,6 +70,155 @@ 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 Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ pre_override_ (c),
+ type_pass_(c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (esimpl_custom (e));
+
+ if (!name)
+ return;
+
+ String state;
+
+ if (!base_enum)
+ state = esstate (e);
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ {
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << esskel (e) << " (" <<
+ (base_enum ? "&base_impl_" : "0") << ")"
+ << "{"
+ << "}";
+ }
+
+ // pre
+ //
+ String const& arg (sarg_type (e));
+
+ if (polymorphic (e))
+ pre_override_.dispatch (e);
+
+ os << "void " << name << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{";
+
+ if (base_enum)
+ {
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ if (tiein)
+ os << "this->base_impl_.pre (";
+ else
+ os << esimpl (b) << "::pre (";
+
+ type_pass_.dispatch (b);
+
+ os << "x);";
+ }
+ else
+ os << "this->" << state << " = &x;";
+
+ os << "}";
+
+ // _serialize_content
+ //
+ if (!base_enum)
+ {
+ String const& string (e.context ().get ("string"));
+
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "this->_characters (this->" << state << "->" <<
+ string << " ());"
+ << "}";
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PreOverride pre_override_;
+ TypePass type_pass_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -931,53 +1080,6 @@ 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)
@@ -1125,7 +1227,6 @@ namespace CXX
if (!b.is_a () &&
!b.is_a ())
{
-
if (tiein)
os << "this->base_impl_.pre (";
else
@@ -1290,10 +1391,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx
index 17a4916..bd53f9d 100644
--- a/xsde/cxx/hybrid/tree-forward.cxx
+++ b/xsde/cxx/hybrid/tree-forward.cxx
@@ -14,6 +14,50 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ctx (e.context ());
+
+ // Forward-declare the base.
+ //
+ if (ctx.count ("name-base"))
+ {
+ if (String base = ctx.get ("name-base"))
+ os << "class " << base << ";";
+ }
+
+ // Typedef or forward-declare the type.
+ //
+ if (ctx.count ("name-typedef"))
+ {
+ os << "typedef " << ctx.get ("name-typedef") << " " <<
+ ename (e) << ";";
+ }
+ else
+ os << "class " << ename (e) << ";";
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -752,7 +796,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -760,7 +804,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx
index 929ea6e..aba65c7 100644
--- a/xsde/cxx/hybrid/tree-header.cxx
+++ b/xsde/cxx/hybrid/tree-header.cxx
@@ -14,6 +14,229 @@ namespace CXX
{
namespace
{
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << ename (e);
+ }
+ };
+
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ base_name_ (c, TypeName::base),
+ enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean fl (fixed_length (e));
+ Boolean cd (ec.count ("cd-name"));
+ Boolean poly (polymorphic (e));
+ String const& vt (ec.get ("value-type"));
+
+ os << "// " << comment (e.name ()) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "//" << endl;
+
+ os << "class " << name;
+
+ if (base_enum)
+ {
+ os << ": public ";
+ base_name_.dispatch (e.inherits ().base ());
+ }
+
+ os << "{";
+
+ if (!fl)
+ os << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
+ os << "public:" << endl;
+
+ // value_type
+ //
+ if (base_enum)
+ {
+ os << "typedef ";
+ base_name_.dispatch (*base_enum);
+ os << "::" << base_enum->context ().get ("value-type") <<
+ " " << vt << ";"
+ << endl;
+ }
+ else
+ {
+ os << "enum " << vt
+ << "{";
+ names (e, names_, 0, 0, 0, &Enumeration::comma);
+ os << "};";
+ }
+
+ // c-tors
+ //
+ os << name << " ();"
+ << name << " (" << vt << ");"
+ << endl;
+
+ // value (value_type)
+ //
+ if (!base_enum)
+ os << "void" << endl
+ << ec.get ("value") << " (" << vt << ");"
+ << endl;
+
+ // d-tor
+ //
+ if (poly)
+ os << "virtual" << endl
+ << "~" << name << " ();"
+ << endl;
+
+ if (!base_enum)
+ {
+ // operator value()
+ //
+ // Name lookup differences in various compilers make generation
+ // of this operator outside of the class a really hard task. So
+ // we are going to make it always inline.
+ //
+ os << "operator " << vt << " () const"
+ << "{"
+ << "return " << ec.get ("value-member") << ";"
+ << "}";
+
+ // string()
+ //
+ os << "const char*" << endl
+ << ec.get ("string") << " () const;"
+ << endl;
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (e));
+ String const& sequence (ecd_sequence (e));
+ String const& iterator (ecd_iterator (e));
+ String const& const_iterator (ecd_const_iterator (e));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef " << data_seq << " " << sequence << ";"
+ << "typedef " << sequence << "::iterator " << iterator << ";"
+ << "typedef " << sequence << "::const_iterator " <<
+ const_iterator << ";"
+ << endl;
+
+ // const seq&
+ // name () const
+ //
+ os << "const " << sequence << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // seq&
+ // name ()
+ //
+ os << sequence << "&" << endl
+ << name << " ();"
+ << endl;
+ }
+
+ if (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 (!base_enum || cd)
+ os << "private:" << endl;
+
+ if (!base_enum)
+ os << vt << " " << ec.get ("value-member") << ";";
+
+ if (cd)
+ os << ecd_sequence (e) << " " << ecd_member (e) << ";";
+
+ os << "};";
+ }
+
+ // Generate include for custom type.
+ //
+ if (ec.count ("name-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ ec.get ("name-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ TypeName base_name_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -2412,6 +2635,14 @@ namespace CXX
os << "{";
+ // copy c-tor & operator= (private)
+ //
+ if (!fl)
+ os << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
// c-tor
//
os << "public:" << endl
@@ -2422,19 +2653,13 @@ namespace CXX
if (!restriction || poly)
os << (poly ? "virtual\n" : "") << "~" << name << " ();";
- // copy c-tor & operator=
+ // copy c-tor & operator= (public)
//
- if (!fl)
- os << endl
- << "private:" << endl;
-
- if (!fl || !restriction)
+ if (fl && !restriction)
os << name << " (const " << name << "&);"
- << name << "& operator= (const " << name << "&);"
- << endl;
+ << name << "& operator= (const " << name << "&);";
- if ((!restriction && !fl) || cd)
- os << "public:" << endl;
+ os << endl;
if (!restriction)
{
@@ -2614,7 +2839,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -2622,7 +2847,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx
index 26b1a48..28a0582 100644
--- a/xsde/cxx/hybrid/tree-inline.cxx
+++ b/xsde/cxx/hybrid/tree-inline.cxx
@@ -15,6 +15,115 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ base_name_ (c, TypeName::base)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ SemanticGraph::Context& ec (e.context ());
+ String const& vt (ec.get ("value-type"));
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // c-tors
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()"
+ << "{"
+ << "}";
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << vt << " v)"
+ << "{";
+
+ if (base_enum)
+ {
+ os << "this->" << base_enum->context ().get ("value") <<
+ " (v);";
+ }
+ else
+ os << ec.get ("value-member") << " = v;";
+
+ os << "}";
+
+ // value (value_type)
+ //
+ if (!base_enum)
+ {
+ os << inl
+ << "void " << name << "::" << endl
+ << ec.get ("value") << " (" << vt << " v)"
+ << "{"
+ << ec.get ("value-member") << " = v;"
+ << "}";
+ }
+
+ // Custom data.
+ //
+ if (ec.count ("cd-name"))
+ {
+ String const& cd_name (ecd_name (e));
+ String const& member (ecd_member (e));
+ String const& sequence (ecd_sequence (e));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << name << "::" << sequence << "& " <<
+ name << "::" << endl
+ << cd_name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << name << "::" << sequence << "& " << name << "::" << endl
+ << cd_name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ TypeName base_name_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -2029,7 +2138,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -2037,7 +2146,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx
index 240da59..e5c55db 100644
--- a/xsde/cxx/hybrid/tree-name-processor.cxx
+++ b/xsde/cxx/hybrid/tree-name-processor.cxx
@@ -4,6 +4,8 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include
+
+#include
#include
#include
@@ -51,6 +53,7 @@ namespace CXX
schema_path (schema_path_),
stl (!ops.value ()),
detach (ops.value ()),
+ enum_ (!ops.value ()),
custom_data_map (custom_data_map_),
custom_type_map (custom_type_map_),
global_type_names (global_type_names_)
@@ -179,6 +182,7 @@ namespace CXX
schema_path (c.schema_path),
stl (c.stl),
detach (c.detach),
+ enum_ (c.enum_),
custom_data_map (c.custom_data_map),
custom_type_map (c.custom_type_map),
global_type_names (c.global_type_names)
@@ -279,6 +283,7 @@ namespace CXX
Boolean stl;
Boolean detach;
+ Boolean enum_;
CustomDataMap& custom_data_map;
CustomTypeMap& custom_type_map;
@@ -1140,9 +1145,29 @@ namespace CXX
//
//
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ e.context ().set ("name", find_name (e.name (), set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
struct GlobalTypeMembers: Traversal::List,
Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Context
{
GlobalTypeMembers (Context& c, Boolean data_members)
@@ -1151,6 +1176,82 @@ namespace CXX
}
virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ // First see if we should delegate this one to Complex.
+ //
+ SemanticGraph::Enumeration* base_enum (0);
+
+ if (!enum_ || !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast (e));
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use name-base instead of name.
+ // If name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("name-base")
+ ? ec.get ("name-base")
+ : ec.get ("name"));
+ if (!name)
+ return;
+
+ if (!data_members_)
+ {
+ ec.set (member_set_key, NameSet ());
+ NameSet& set (ec.get (member_set_key));
+ set.insert (name);
+
+ String v (ec.get ("value-type")); // Set by GlobalTypeName.
+ set.insert (v);
+
+ Enumerator enumerator (*this, set);
+ Traversal::Names names (enumerator);
+ Enumeration::names (e, names);
+
+ if (!base_enum)
+ {
+ ec.set ("value", find_name ("value", set));
+ ec.set ("string", find_name ("string", set));
+ }
+
+ // Check if this type has custom data.
+ //
+ CustomDataMap::Iterator i (custom_data_map.find (e.name ()));
+
+ if (i != custom_data_map.end () &&
+ i->second->find (L"") != i->second->end ())
+ {
+ String name (find_name ("custom_data", set));
+
+ ec.set ("cd-name", name);
+ ec.set ("cd-sequence", find_name (name + L"_sequence", set));
+ ec.set ("cd-iterator", find_name (name + L"_iterator", set));
+ ec.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", set));
+ }
+ }
+ else
+ {
+ NameSet& set (ec.get (member_set_key));
+
+ if (!base_enum)
+ ec.set ("value-member", find_name ("value_", set));
+
+ // Custom data.
+ //
+ if (ec.count ("cd-name"))
+ {
+ String const& base (ec.get ("cd-name"));
+ ec.set ("cd-member", find_name (base + L"_", set));
+ }
+ }
+ }
+
+ virtual Void
traverse (SemanticGraph::List& l)
{
SemanticGraph::Context& lc (l.context ());
@@ -1531,6 +1632,7 @@ namespace CXX
//
struct GlobalTypeName: Traversal::Type,
Traversal::Union,
+ Traversal::Enumeration,
Context
{
GlobalTypeName (Context& c, NameSet& set)
@@ -1591,6 +1693,32 @@ namespace CXX
uc.set ("value", find_name ("value", set));
}
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ traverse (static_cast (e));
+
+ if (enum_ && Hybrid::Context::enum_mapping (e))
+ {
+ // We need to assign the value type name for enumerations
+ // even in included/imported schemas since we may need this
+ // information when generating derived enums. We need to do
+ // this even if the type is completely customized.
+ //
+ SemanticGraph::Context& ec (e.context ());
+ String name (ec.count ("name-base")
+ ? ec.get ("name-base")
+ : ec.get ("name"));
+
+ if (!name)
+ name = ec.get ("name");
+
+ NameSet set;
+ set.insert (name);
+ ec.set ("value-type", find_name ("value_type", set));
+ }
+ }
+
private:
NameSet& set_;
};
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
index 33d829a..c6b347e 100644
--- a/xsde/cxx/hybrid/tree-size-processor.cxx
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -237,20 +237,23 @@ namespace CXX
//
struct Type: Traversal::List,
Traversal::Union,
- Traversal::Complex
+ Traversal::Complex,
+ Traversal::Enumeration
{
Type (Boolean& valid,
TypeSet& custom_data,
CustomTypeMap& custom_type_map,
TypeSet& poly_types,
Boolean stl_,
- Boolean poly_)
+ Boolean poly_,
+ Boolean enum_mapping)
: valid_ (valid),
custom_data_ (custom_data),
custom_type_map_ (custom_type_map),
poly_types_ (poly_types),
stl (stl_),
- poly (poly_)
+ poly (poly_),
+ enum_ (enum_mapping)
{
}
@@ -281,6 +284,44 @@ namespace CXX
}
virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ if (!test (e))
+ {
+ // First process our base since enum_mapping() needs the
+ // polymorphic property determined.
+ //
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ if (!test (b))
+ dispatch (b);
+
+ SemanticGraph::Enumeration* base_enum (0);
+
+ if (!enum_ || !Context::enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast (e));
+ return;
+ }
+
+ Boolean fixed (true);
+
+ if (base_enum && !get (b))
+ fixed = false;
+
+ // Check for custom data.
+ //
+ if (fixed)
+ {
+ if (custom_data_.find (e.name ()) != custom_data_.end ())
+ fixed = false;
+ }
+
+ set (e, fixed);
+ }
+ }
+
+ virtual Void
traverse (SemanticGraph::Complex& c)
{
SemanticGraph::Context& ctx (c.context ());
@@ -428,6 +469,7 @@ namespace CXX
TypeSet& poly_types_;
Boolean stl;
Boolean poly;
+ Boolean enum_;
typedef Containers::Vector Path;
Path path_;
@@ -1184,7 +1226,8 @@ namespace CXX
custom_type_map,
poly_types,
stl,
- poly);
+ poly,
+ !ops.value ());
schema >> schema_names >> ns >> ns_names >> type;
diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx
index eb83658..61186b5 100644
--- a/xsde/cxx/hybrid/tree-source.cxx
+++ b/xsde/cxx/hybrid/tree-source.cxx
@@ -15,6 +15,135 @@ namespace CXX
{
namespace
{
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << strlit (e.name ());
+ }
+ };
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ if (!base_enum)
+ {
+ os << "static const char* _xsde_" << name << "_enumerators_[] = {";
+ names (e, names_, 0, 0, 0, &Enumeration::comma);
+ os << "};";
+
+ // string()
+ //
+ os << "const char* " << name << "::" << endl
+ << ec.get ("string") << " () const"
+ << "{"
+ << "return _xsde_" << name << "_enumerators_[" <<
+ ec.get ("value-member") << "];"
+ << "}";
+ }
+
+ if (polymorphic (e))
+ {
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ if (typeinfo)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ 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 ();"
+ << "}";
+ }
+ }
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Complex& complex_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -1968,6 +2097,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -1975,6 +2105,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
--
cgit v1.1