aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-10-27 10:10:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-10-27 10:10:46 +0200
commit3dcdc88b14aec626c87f8f480a1d07781a27c069 (patch)
tree3d64d4701e07441545ffaf3afe0050c4c9e35b41
parent8161144e7f3182d9dc66a811b4618a81232d4af3 (diff)
Implement schema enumeration to C++ enum mapping in C++/Hybrid
-rw-r--r--NEWS17
-rw-r--r--dist/tests/cxx/hybrid/makefile4
-rw-r--r--dist/tests/cxx/hybrid/nmakefile4
-rw-r--r--documentation/cxx/hybrid/guide/index.xhtml162
-rw-r--r--documentation/xsde.13
-rw-r--r--documentation/xsde.xhtml4
-rw-r--r--examples/cxx/hybrid/filter/driver.cxx6
-rw-r--r--examples/cxx/hybrid/library/driver.cxx6
-rw-r--r--examples/cxx/hybrid/minimal/driver.cxx7
-rw-r--r--tests/cxx/hybrid/enumeration/driver.cxx97
-rw-r--r--tests/cxx/hybrid/enumeration/makefile109
-rw-r--r--tests/cxx/hybrid/enumeration/test-000.std1
-rw-r--r--tests/cxx/hybrid/enumeration/test-000.xml24
-rw-r--r--tests/cxx/hybrid/enumeration/test.xsd88
-rw-r--r--tests/cxx/hybrid/polymorphism/enumeration/driver.cxx67
-rw-r--r--tests/cxx/hybrid/polymorphism/enumeration/makefile110
-rw-r--r--tests/cxx/hybrid/polymorphism/enumeration/test-000.std1
-rw-r--r--tests/cxx/hybrid/polymorphism/enumeration/test-000.xml13
-rw-r--r--tests/cxx/hybrid/polymorphism/enumeration/test.xsd58
-rw-r--r--tests/cxx/hybrid/polymorphism/makefile7
-rw-r--r--xsde/cxx/hybrid/cli.hxx2
-rw-r--r--xsde/cxx/hybrid/default-value.cxx47
-rw-r--r--xsde/cxx/hybrid/default-value.hxx8
-rw-r--r--xsde/cxx/hybrid/elements.cxx29
-rw-r--r--xsde/cxx/hybrid/elements.hxx128
-rw-r--r--xsde/cxx/hybrid/extraction-header.cxx43
-rw-r--r--xsde/cxx/hybrid/extraction-source.cxx56
-rw-r--r--xsde/cxx/hybrid/generator.cxx6
-rw-r--r--xsde/cxx/hybrid/insertion-header.cxx43
-rw-r--r--xsde/cxx/hybrid/insertion-source.cxx47
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx219
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx58
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx466
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx168
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx55
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx199
-rw-r--r--xsde/cxx/hybrid/tree-forward.cxx48
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx249
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx113
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx128
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx51
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx131
42 files changed, 2842 insertions, 240 deletions
diff --git a/NEWS b/NEWS
index 04dbd32..3eb2cf5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,15 +1,20 @@
Version 3.2.0
- * When built with Xerces-C++ 3-series, enable handling of multiple
- imports for the same namespace. Before, all subsequent imports for
- a namespace were ignored which caused error in some schemas.
+ * When built with Xerces-C++ 3-series, enable handling of multiple imports
+ for the same namespace. Before, all subsequent imports for a namespace
+ were ignored which caused error in some schemas.
C++/Hybrid
+ * String-based types that use XML Schema restriction by enumeration are
+ now mapped to C++ classes with semantics similar to C++ enum. You can
+ suppress this new mapping and instead get the old behavior (plain
+ inheritance) by specifying the --suppress-enum compiler option.
+
* New configuration parameter, XSDE_STL_ITERATOR, makes iterators
- provided by the mapping conform to the STL requirements. This
- feature requires working <iterator> header and allows you to use the
- standard algorithms such as find_if, etc.
+ provided by the mapping conform to the STL requirements. This feature
+ requires working <iterator> header and allows you to use the standard
+ algorithms such as find_if, etc.
* When the code is generated with the --generate-polymorphic or
--runtime-polymorphic option, the resulting parser and serializer
diff --git a/dist/tests/cxx/hybrid/makefile b/dist/tests/cxx/hybrid/makefile
index 8733e6b..3cd2d7d 100644
--- a/dist/tests/cxx/hybrid/makefile
+++ b/dist/tests/cxx/hybrid/makefile
@@ -5,7 +5,7 @@ include $(root)/build/config.make
dirs := sequences
ifeq ($(XSDE_POLYMORPHIC),y)
-dirs += polymorphism/multischema
+dirs += polymorphism/enumeration polymorphism/multischema
endif
ifeq ($(XSDE_STL),y)
@@ -15,7 +15,7 @@ endif
endif
ifeq ($(XSDE_IOSTREAM),y)
-dirs += built-in default list test-template union
+dirs += built-in default enumeration list test-template union
ifeq ($(XSDE_CDR),y)
dirs += binary/cdr
diff --git a/dist/tests/cxx/hybrid/nmakefile b/dist/tests/cxx/hybrid/nmakefile
index 0f42e79..9052637 100644
--- a/dist/tests/cxx/hybrid/nmakefile
+++ b/dist/tests/cxx/hybrid/nmakefile
@@ -5,7 +5,7 @@ root = ..\..\..
dirs = sequences
!if "$(XSDE_POLYMORPHIC)" == "y"
-dirs = $(dirs) polymorphism\multischema
+dirs = $(dirs) polymorphism\enumeration polymorphism\multischema
!endif
!if "$(XSDE_STL)" == "y"
@@ -15,7 +15,7 @@ dirs = $(dirs) iterator
!endif
!if "$(XSDE_IOSTREAM)" == "y"
-dirs = $(dirs) built-in default list test-template union
+dirs = $(dirs) built-in default enumeration list test-template union
!if "$(XSDE_CDR)" == "y"
dirs = $(dirs) binary/cdr
diff --git a/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml
index 6856e8c..5a4b33a 100644
--- a/documentation/cxx/hybrid/guide/index.xhtml
+++ b/documentation/cxx/hybrid/guide/index.xhtml
@@ -241,13 +241,14 @@
<table class="toc">
<tr><th>4.1</th><td><a href="#4.1">Namespaces</a></td></tr>
<tr><th>4.2</th><td><a href="#4.2">Memory Management</a></td></tr>
- <tr><th>4.3</th><td><a href="#4.3">Attributes and Elements</a></td></tr>
- <tr><th>4.4</th><td><a href="#4.4">Compositors</a></td></tr>
- <tr><th>4.5</th><td><a href="#4.5">Accessing the Object Model</a></td></tr>
- <tr><th>4.6</th><td><a href="#4.6">Modifying the Object Model</a></td></tr>
- <tr><th>4.7</th><td><a href="#4.7">Creating the Object Model from Scratch</a></td></tr>
- <tr><th>4.8</th><td><a href="#4.8">Customizing the Object Model</a></td></tr>
- <tr><th>4.9</th><td><a href="#4.9">Polymorphic Object Models</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Enumerations</a></td></tr>
+ <tr><th>4.4</th><td><a href="#4.4">Attributes and Elements</a></td></tr>
+ <tr><th>4.5</th><td><a href="#4.5">Compositors</a></td></tr>
+ <tr><th>4.6</th><td><a href="#4.6">Accessing the Object Model</a></td></tr>
+ <tr><th>4.7</th><td><a href="#4.7">Modifying the Object Model</a></td></tr>
+ <tr><th>4.8</th><td><a href="#4.8">Creating the Object Model from Scratch</a></td></tr>
+ <tr><th>4.9</th><td><a href="#4.9">Customizing the Object Model</a></td></tr>
+ <tr><th>4.10</th><td><a href="#4.10">Polymorphic Object Models</a></td></tr>
</table>
</td>
</tr>
@@ -1542,7 +1543,7 @@ $ xsde cxx-hybrid --generate-parser --generate-serializer \
</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>
+ refer to <a href="#4.10">Section 4.10, "Polymorphic Object Models"</a>.</p>
<!-- Chapater 4 -->
@@ -1626,12 +1627,30 @@ $ xsde cxx-hybrid --generate-parser --generate-serializer \
<pre class="c++">
// gender (fixed-length)
//
-class gender: public std::string
+class gender
{
public:
+ enum value_type
+ {
+ male,
+ female
+ };
+
gender ();
+ gender (value_type);
gender (const gender&amp;);
gender&amp; operator= (const gender&amp;);
+
+ void
+ value (value_type);
+
+ operator value_type () const;
+
+ const char*
+ string () const;
+
+private:
+ ...
};
// person (fixed-length)
@@ -1807,7 +1826,7 @@ 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
+ <li>it is polymorphic (see <a href="#4.10">Section 4.10, "Polymorphic
Object Models"</a> for details)</li>
</ol>
@@ -1827,10 +1846,9 @@ private:
variable-length because it contains a sequence of <code>person</code>
elements (<code>maxOccurs="unbounded"</code>). If we recompile
the <code>people.xsd</code> schema with the <code>--no-stl</code>
- option, the first two types will also become variable-length
- since <code>gender</code> inherits from and <code>person</code>
- contains elements of the <code>string</code> built-in type. And
- when STL is disabled, <code>string</code> is variable-length.</p>
+ option, the <code>person</code> type will also become variable-length
+ since it contains elements of the <code>string</code> built-in type.
+ And when STL is disabled, <code>string</code> is variable-length.</p>
<p>The object model uses different methods for storing and passing
around fixed-length and variable-length types. Instances of
@@ -1932,7 +1950,81 @@ s->permanent (per) // Assumes ownership or per.
s->contract (con) // Assumes ownership or con.
</pre>
- <h2><a name="4.3">4.3 Attributes and Elements</a></h2>
+ <h2><a name="4.3">4.3 Enumerations</a></h2>
+
+ <p>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 <code>--suppress-enum</code> compiler
+ option). The following code fragment again shows the C++ class that
+ was generated for the <code>gender</code> XML Schema type presented
+ at the beginning of this chapter:</p>
+
+ <pre class="c++">
+// gender (fixed-length)
+//
+class gender
+{
+public:
+ enum value_type
+ {
+ male,
+ female
+ };
+
+ gender ();
+ gender (value_type);
+ gender (const gender&amp;);
+ gender&amp; operator= (const gender&amp;);
+
+ void
+ value (value_type);
+
+ operator value_type () const;
+
+ const char*
+ string () const;
+
+private:
+ value_type v_;
+};
+</pre>
+
+ <p>The <code>gender</code> class defines the underlying C++ enum type
+ (<code>value_type</code>) with enumerators corresponding to the
+ <code>enumeration</code> 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 <code>gender</code> class also supports the implicit
+ conversion to the underlying enum type and the explicit conversion
+ to string via the <code>string()</code> function. Finally, it
+ provides the <code>value()</code> 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
+ <code>gender</code> class:</p>
+
+ <pre class="c++">
+gender g = gender::male;
+g = gender::female;
+g.value (gender::female); // Same as above.
+
+cerr &lt;&lt; g.string () &lt;&lt; endl;
+
+if (g != gender::male)
+ ...
+
+switch (g)
+{
+case gender::male:
+ ...
+case gender::female:
+ ...
+}
+ </pre>
+
+
+ <h2><a name="4.4">4.4 Attributes and Elements</a></h2>
<p>As we have seen before, XSD/e generates a different
set of member functions for elements with different cardinalities.
@@ -1945,7 +2037,7 @@ s->contract (con) // Assumes ownership or con.
example, the <code>first-name</code>, <code>last-name</code>,
<code>gender</code>, and <code>age</code> elements as well as
the <code>id</code> attribute belong to this cardinality class.
- The following code fragment shows again the accessor and modifier
+ The following code fragment again shows the accessor and modifier
functions that are generated for the <code>first-name</code> element
in the <code>person</code> class:</p>
@@ -1975,7 +2067,7 @@ class person
<p>The <em>optional</em> cardinality class covers all elements that
can occur zero or one time as well as optional attributes. In our
example, the <code>middle-name</code> element belongs to this
- cardinality class. The following code fragment shows again the
+ cardinality class. The following code fragment again shows the
accessor and modifier functions that are generated for this element
in the <code>person</code> class:</p>
@@ -2664,13 +2756,13 @@ namespace xml_schema
}
</pre>
- <h2><a name="4.4">4.4 Compositors</a></h2>
+ <h2><a name="4.5">4.5 Compositors</a></h2>
<p>The XML Schema language provides three compositor constructs that
are used to group elements: <code>all</code>, <code>sequence</code>,
and <code>choice</code>. If a compositor has an <em>optional</em>
- or <em>sequence</em> cardinality class (see <a href="#4.3">Section
- 4.3, "Attributes and Elements"</a>) or if a compositor is
+ or <em>sequence</em> cardinality class (see <a href="#4.4">Section
+ 4.4, "Attributes and Elements"</a>) or if a compositor is
inside <code>choice</code>, then the C++/Hybrid mapping generates
a nested class for such a compositor as well as a set of accessor
and modifier functions similar to the ones defined for elements
@@ -3082,7 +3174,7 @@ private:
};
</pre>
- <h2><a name="4.5">4.5 Accessing the Object Model</a></h2>
+ <h2><a name="4.6">4.6 Accessing the Object Model</a></h2>
<p>In this section we will examine how to get to the information
stored in the object model for the person records vocabulary
@@ -3131,7 +3223,7 @@ main ()
// Print gender, age, and id which are all required.
//
- cout &lt;&lt; "gender: " &lt;&lt; p.gender () &lt;&lt; endl
+ cout &lt;&lt; "gender: " &lt;&lt; p.gender ().string () &lt;&lt; endl
&lt;&lt; "age: " &lt;&lt; p.age () &lt;&lt; endl
&lt;&lt; "id: " &lt;&lt; p.id () &lt;&lt; endl
&lt;&lt; endl;
@@ -3174,7 +3266,7 @@ id: 2
</pre>
- <h2><a name="4.6">4.6 Modifying the Object Model</a></h2>
+ <h2><a name="4.7">4.7 Modifying the Object Model</a></h2>
<p>In this section we will examine how to modify the information
stored in the object model for our person records vocabulary.
@@ -3284,7 +3376,7 @@ main ()
&lt;/people>
</pre>
- <h2><a name="4.7">4.7 Creating the Object Model from Scratch</a></h2>
+ <h2><a name="4.8">4.8 Creating the Object Model from Scratch</a></h2>
<p>In this section we will examine how to create a new object model
for our person records vocabulary. The following application
@@ -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 ()
&lt;/people>
</pre>
- <h2><a name="4.8">4.8 Customizing the Object Model</a></h2>
+ <h2><a name="4.9">4.9 Customizing the Object Model</a></h2>
<p>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)
</pre>
- <h2><a name="4.9">4.9 Polymorphic Object Models</a></h2>
+ <h2><a name="4.10">4.10 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
@@ -4673,7 +4759,7 @@ namespace xml_schema
<p>The <code>NMTOKENS</code> and <code>IDREFS</code> built-in
XML Schema types are mapped to the string sequence type which
- is discussed in <a href="#4.3">Section 4.3, "Attributes and
+ is discussed in <a href="#4.4">Section 4.4, "Attributes and
Elements"</a>.</p>
<h2><a name="5.3">5.3 Mapping for <code>base64Binary</code> and <code>hexBinary</code></a></h2>
@@ -5783,7 +5869,7 @@ main (int argc, char* argv[])
{
cerr &lt;&lt; "first: " &lt;&lt; i->first_name () &lt;&lt; endl
&lt;&lt; "last: " &lt;&lt; i->last_name () &lt;&lt; endl
- &lt;&lt; "gender: " &lt;&lt; i->gender () &lt;&lt; endl
+ &lt;&lt; "gender: " &lt;&lt; i->gender ().string () &lt;&lt; endl
&lt;&lt; "age: " &lt;&lt; i->age () &lt;&lt; endl
&lt;&lt; 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 @@
<dd>Omit attributes with default and fixed values from serialized
XML documents.</dd>
+ <dt><code><b>--suppress-enum</b></code></dt>
+ <dd>Suppress the generation of the XML Schema enumeration to C++
+ enum mapping.</dd>
+
<dt><code><b>--generate-detach</b></code></dt>
<dd>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 <boris@codesynthesis.com>
+// 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 <cassert>
+#include <iostream>
+
+#include "test.hxx"
+#include "test-pimpl.hxx"
+#include "test-simpl.hxx"
+
+using namespace std;
+using namespace test;
+
+int
+main (int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " test.xml" << endl;
+ return 1;
+ }
+
+ // 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 <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
+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 @@
+<t:root xmlns:t="test" x="a" y="c" z="b"><simple>a</simple><simple>b</simple><derived>a</derived><derived>b</derived><final>a</final><final>c</final><complex x="a">a</complex><complex x="c">c</complex><simple-cd>a</simple-cd><simple-cd>b</simple-cd><fbvd>a</fbvd><fbvd>c</fbvd><vbvd>a</vbvd><vbvd>c</vbvd></t:root> \ 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 @@
+<t:root xmlns:t="test">
+
+ <simple>a</simple>
+ <simple>b</simple>
+
+ <derived>a</derived>
+ <derived>b</derived>
+
+ <final>a</final>
+ <final>c</final>
+
+ <complex x="a">a</complex>
+ <complex x="c">c</complex>
+
+ <simple-cd>a</simple-cd>
+ <simple-cd>b</simple-cd>
+
+ <fbvd>a</fbvd>
+ <fbvd>c</fbvd>
+
+ <vbvd>a</vbvd>
+ <vbvd>c</vbvd>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <simpleType name="base">
+ <restriction base="string"/>
+ </simpleType>
+
+ <simpleType name="simple">
+ <restriction base="string">
+ <enumeration value="a"/>
+ <enumeration value="b"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="derived">
+ <restriction base="t:base">
+ <enumeration value="a"/>
+ <enumeration value="b"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <simpleType name="interm">
+ <restriction base="t:simple"/>
+ </simpleType>
+
+ <simpleType name="final">
+ <restriction base="t:interm">
+ <enumeration value="a"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="complex">
+ <simpleContent>
+ <extension base="t:final">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <!-- Variable-length (custom data) -->
+
+ <simpleType name="simple-cd">
+ <restriction base="string">
+ <enumeration value="a"/>
+ <enumeration value="b"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <!-- fixed base, variable derived -->
+ <simpleType name="fbvd">
+ <restriction base="t:simple">
+ <enumeration value="a"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <!-- variable base, variable derived -->
+ <simpleType name="vbvd">
+ <restriction base="t:simple-cd">
+ <enumeration value="a"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+
+ <complexType name="type">
+ <sequence>
+ <element name="simple" type="t:simple" maxOccurs="unbounded"/>
+ <element name="derived" type="t:derived" maxOccurs="unbounded"/>
+ <element name="final" type="t:final" maxOccurs="unbounded"/>
+ <element name="complex" type="t:complex" maxOccurs="unbounded"/>
+
+ <element name="simple-cd" type="t:simple-cd" maxOccurs="unbounded"/>
+ <element name="fbvd" type="t:fbvd" maxOccurs="unbounded"/>
+ <element name="vbvd" type="t:vbvd" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="x" type="t:simple" default="a"/>
+ <attribute name="y" type="t:final" default="c"/>
+ <attribute name="z" type="t:simple-cd" default="b"/>
+ </complexType>
+
+ <element name="root" type="t:type"/>
+
+</schema>
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 <boris@codesynthesis.com>
+// 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 <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 ();
+
+ // 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 <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
+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 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><base xsi:type="t:derived">a</base><base xsi:type="t:derived">b</base><simple>a</simple><simple>b</simple><simple xsi:type="t:interm">b</simple><simple xsi:type="t:final">c</simple><simple x="c" xsi:type="t:complex">c</simple></t:root> \ 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 @@
+<t:root xmlns:t="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <base xsi:type="t:derived">a</base>
+ <base xsi:type="t:derived">b</base>
+
+ <simple>a</simple>
+ <simple>b</simple>
+
+ <simple xsi:type="t:interm">b</simple>
+ <simple xsi:type="t:final">c</simple>
+ <simple xsi:type="t:complex" x="c">c</simple>
+
+</t:root>
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 @@
+<?xml version="1.0"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:t="test" targetNamespace="test">
+
+ <!-- base is polymorphic -->
+
+ <simpleType name="base">
+ <restriction base="string"/>
+ </simpleType>
+
+ <simpleType name="derived">
+ <restriction base="t:base">
+ <enumeration value="a"/>
+ <enumeration value="b"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <!-- enum is polymorphic -->
+
+ <simpleType name="simple">
+ <restriction base="string">
+ <enumeration value="a"/>
+ <enumeration value="b"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <!-- base enum is polymorphic -->
+
+ <simpleType name="interm">
+ <restriction base="t:simple"/>
+ </simpleType>
+
+ <simpleType name="final">
+ <restriction base="t:interm">
+ <enumeration value="a"/>
+ <enumeration value="c"/>
+ </restriction>
+ </simpleType>
+
+ <complexType name="complex">
+ <simpleContent>
+ <extension base="t:final">
+ <attribute name="x" type="string"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="type">
+ <sequence>
+ <element name="base" type="t:base" maxOccurs="unbounded"/>
+ <element name="simple" type="t:simple" 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
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<NarrowString>,
generate_extraction, Cult::Containers::Vector<NarrowString>,
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<SemanticGraph::Complex&> (e));
+ return;
+ }
+
+ Enumeration& x (base_enum ? *base_enum : e);
+
+ os << member_ << x.context ().get<String> ("value") << "(";
+
+ Enumeration::NamesIteratorPair ip (x.find (value_));
+
+ if (ip.first != ip.second)
+ {
+ Enumerator& er (dynamic_cast<Enumerator&> (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<SemanticGraph::Complex&> (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<CLI::generate_detach> ()),
mixin (ops.value<CLI::reuse_style_mixin> ()),
tiein (!mixin),
+ enum_ (!ops.value<CLI::suppress_enum> ()),
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<String>
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<String> ("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<String> ("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 <cxx/elements.hxx>
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/parser-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -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<CLI::suppress_enum> () ||
+ !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<String> ("p:impl-base")
+ : ec.get<String> ("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<Enumeration&> (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<String> ("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<String> ("value-type"));
+
+ os << type << "::" << vt << " v = static_cast< " << type <<
+ "::" << vt << " > (0);"
+ << "const char* s = this->" << state << ".str_." <<
+ (stl ? "c_str" : "data") << " ();"
+ << endl;
+
+ names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+
+
+ /*
+ // @@ Cannot do error checking in post.
+
+ if (!options.value<CLI::suppress_validation> () &&
+ !options.value<CLI::suppress_parser_val> ())
+ {
+ 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<String> ("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<String> ("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 <cxx/elements.hxx>
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/serializer-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -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<CLI::suppress_enum> () ||
+ !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<String> ("s:impl-base")
+ : ec.get<String> ("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> ("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<SemanticGraph::AnyType> () &&
!b.is_a<SemanticGraph::AnySimpleType> ())
{
-
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<String> ("name-base"))
+ os << "class " << base << ";";
+ }
+
+ // Typedef or forward-declare the type.
+ //
+ if (ctx.count ("name-typedef"))
+ {
+ os << "typedef " << ctx.get<String> ("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<String> ("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<String> ("value-type") <<
+ " " << vt << ";"
+ << endl;
+ }
+ else
+ {
+ os << "enum " << vt
+ << "{";
+ names<Enumeration> (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<String> ("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<String> ("value-member") << ";"
+ << "}";
+
+ // string()
+ //
+ os << "const char*" << endl
+ << ec.get<String> ("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<String> ("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<String> ("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<String> ("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<String> ("value") <<
+ " (v);";
+ }
+ else
+ os << ec.get<String> ("value-member") << " = v;";
+
+ os << "}";
+
+ // value (value_type)
+ //
+ if (!base_enum)
+ {
+ os << inl
+ << "void " << name << "::" << endl
+ << ec.get<String> ("value") << " (" << vt << " v)"
+ << "{"
+ << ec.get<String> ("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 <cxx/elements.hxx>
+
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/tree-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -51,6 +53,7 @@ namespace CXX
schema_path (schema_path_),
stl (!ops.value<CLI::no_stl> ()),
detach (ops.value<CLI::generate_detach> ()),
+ enum_ (!ops.value<CLI::suppress_enum> ()),
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<SemanticGraph::Complex&> (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<String> ("name-base")
+ : ec.get<String> ("name"));
+ if (!name)
+ return;
+
+ if (!data_members_)
+ {
+ ec.set (member_set_key, NameSet ());
+ NameSet& set (ec.get<NameSet> (member_set_key));
+ set.insert (name);
+
+ String v (ec.get<String> ("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<NameSet> (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<String> ("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<SemanticGraph::Type&> (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<String> ("name-base")
+ : ec.get<String> ("name"));
+
+ if (!name)
+ name = ec.get<String> ("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<SemanticGraph::Complex&> (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<SemanticGraph::Complex*> Path;
Path path_;
@@ -1184,7 +1226,8 @@ namespace CXX
custom_type_map,
poly_types,
stl,
- poly);
+ poly,
+ !ops.value<CLI::suppress_enum> ());
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<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+ os << "};";
+
+ // string()
+ //
+ os << "const char* " << name << "::" << endl
+ << ec.get<String> ("string") << " () const"
+ << "{"
+ << "return _xsde_" << name << "_enumerators_[" <<
+ ec.get<String> ("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);
}