From 8336dd4c16d4885989a6d8f0c83a4b401f5cb63b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 2 Apr 2009 12:22:38 +0200 Subject: Add support for attributes with default and fixed values. tests/cxx/hybrid/default: new test tests/cxx/hybrid/binary: update to test default and fixed values --- NEWS | 5 + documentation/cxx/hybrid/guide/index.xhtml | 138 +++- documentation/xsde.1 | 4 + documentation/xsde.xhtml | 4 + libxsde/xsde/cxx/hybrid/any-type.hxx | 12 + libxsde/xsde/cxx/hybrid/base.hxx | 230 ++++++ tests/cxx/hybrid/binary/cdr/output.xml | 2 +- tests/cxx/hybrid/binary/cdr/test.xml | 4 +- tests/cxx/hybrid/binary/cdr/test.xsd | 12 + tests/cxx/hybrid/binary/custom/output.xml | 2 +- tests/cxx/hybrid/binary/custom/test.xml | 4 +- tests/cxx/hybrid/binary/custom/test.xsd | 12 + tests/cxx/hybrid/binary/xdr/output.xml | 2 +- tests/cxx/hybrid/binary/xdr/test.xml | 4 +- tests/cxx/hybrid/binary/xdr/test.xsd | 12 + tests/cxx/hybrid/default/driver.cxx | 56 ++ tests/cxx/hybrid/default/makefile | 98 +++ tests/cxx/hybrid/default/output | 1 + tests/cxx/hybrid/default/test.xml | 16 + tests/cxx/hybrid/default/test.xsd | 228 ++++++ tests/cxx/hybrid/makefile | 2 +- xsde/cxx/hybrid/cli.hxx | 2 + xsde/cxx/hybrid/default-value.cxx | 1210 ++++++++++++++++++++++++++++ xsde/cxx/hybrid/default-value.hxx | 366 +++++++++ xsde/cxx/hybrid/elements.hxx | 19 + xsde/cxx/hybrid/extraction-source.cxx | 62 +- xsde/cxx/hybrid/generator.cxx | 6 + xsde/cxx/hybrid/insertion-source.cxx | 38 +- xsde/cxx/hybrid/parser-header.cxx | 3 + xsde/cxx/hybrid/parser-source.cxx | 3 + xsde/cxx/hybrid/serializer-source.cxx | 23 +- xsde/cxx/hybrid/tree-forward.cxx | 5 +- xsde/cxx/hybrid/tree-header.cxx | 115 ++- xsde/cxx/hybrid/tree-inline.cxx | 216 +++-- xsde/cxx/hybrid/tree-name-processor.cxx | 43 +- xsde/cxx/hybrid/tree-source.cxx | 153 +++- xsde/makefile | 3 +- 37 files changed, 2942 insertions(+), 173 deletions(-) create mode 100644 tests/cxx/hybrid/default/driver.cxx create mode 100644 tests/cxx/hybrid/default/makefile create mode 100644 tests/cxx/hybrid/default/output create mode 100644 tests/cxx/hybrid/default/test.xml create mode 100644 tests/cxx/hybrid/default/test.xsd create mode 100644 xsde/cxx/hybrid/default-value.cxx create mode 100644 xsde/cxx/hybrid/default-value.hxx diff --git a/NEWS b/NEWS index c4c7628..d868cae 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,11 @@ Version 3.1.0 Started Guide as well as examples in the examples/cxx/hybrid/binary/ directory. + * Support for attributes with default and fixed values. For details see + Section 4.3, "Attributes and Elements" in the Getting Started Guide. + Use the new --omit-default-attributes option to omit the attributes + with default and fixed values from serialized XML documents. + * New option, --custom-type, allows customization of the object model classes. You have the option of either basing your custom implementation on the generated version or providing your own implementation from diff --git a/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml index 5871593..d497a14 100644 --- a/documentation/cxx/hybrid/guide/index.xhtml +++ b/documentation/cxx/hybrid/guide/index.xhtml @@ -2031,7 +2031,143 @@ if (p.middle_name_present ()) } -

Finally, the sequence cardinality class covers all elements +

There are two cases in the optional cardinality class that + are handled differently. These are optional attributes with default + and fixed values. When an optional attribute declaration in XML Schema + specifies a default or fixed value and such an attribute is not present + in the XML document, the attribute is assumed to have the default or + fixed value, respectively. Furthermore, if an attribute with the + fixed value is set in the XML document, then the attribute value + should be the same as its fixed value.

+ +

For an optional attribute with a default value, the functions for + querying and modifying the attribute's presence status are replaced + with functions that allow you to determine whether the attribute has + the default value. The accessor functions can be called at any time + since an optional attribute with a default value always has some + value. Also an extra static function is provided to allow you to + obtain the default value. Consider the following modification to + the person type which adds the verified + attribute with the default value:

+ +
+<xs:complexType name="person">
+  <xs:sequence>
+    <xs:element name="first-name" type="xs:string"/>
+    ...
+  </xs:sequence>
+  <xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+  <xs:attribute name="verified" type="xs:boolean" default="false"/>
+</xs:complexType>
+  
+ +

The code fragment below shows the accessor and modifier functions + that are generated for this new attribute in the person + class:

+ +
+class person
+{
+  // verified
+  //
+  bool
+  verified_default () const;
+
+  void
+  verified_default (bool);
+
+  bool
+  verified () const;
+
+  bool&
+  verified ();
+
+  void
+  verified (bool);
+
+  static bool
+  verified_default_value ();
+};
+  
+ +

When we create an object of the person class, the + verified member is automatically initialized to the + default value. The following example shows how we can manipulate + the verified attribute value:

+ +
+person p; // verified is set to the default value (false).
+
+if (p.verified_default ())
+  p.verified (true);
+else
+  p.verified_default (true); // Revert to the default value.
+
+bool v = p.verified (); // Ok, can always be called.
+bool vd = person::verified_default_value ();
+  
+ +

Note that modifying an attribute of a variable-length type via + the reference when the attribute is set to the default value is + illegal since this will modify the default value shared by all + instances. For example:

+ +
+type& x = ...
+
+if (x.foo_default ())
+{
+  foo& f = x.foo (); // foo is variable-length, for example NMTOKENS
+  f.push_back ("aaa"); // Illegal.
+}
+
+if (x.foo_default ())
+{
+  foo* f = new foo;
+  f->push_back ("aaa");
+  x.foo (f); // Ok.
+}
+  
+ +

Because an attribute with a fixed value can only be set to that + value, only the read-only (constant) accessor and the static + function for obtaining the fixed value are provided for such + attributes. Similar to the default values, members with fixed + values of a newly created object are automatically initialized + to their respective fixed values. Consider the following + modification to the verified attribute from the + schema above:

+ +
+<xs:complexType name="person">
+  ...
+  <xs:attribute name="verified" type="xs:boolean" fixed="true"/>
+</xs:complexType>
+  
+ +

The code fragment below shows the accessor functions that are + generated for this attribute in the person + class:

+ +
+class person
+{
+  // verified
+  //
+  bool
+  verified () const;
+
+  static bool
+  verified_fixed_value ();
+};
+  
+ +

During serialization, attributes that are set to default and fixed + values are explicitly specified in the resulting XML document. + You can use the --omit-default-attributes XSD/e + compiler option to omit such attributes from the serialized XML.

+ +

The sequence cardinality class covers all elements that can occur more than once. In our example, the person element in the people type belongs to this cardinality class. The following code fragment shows diff --git a/documentation/xsde.1 b/documentation/xsde.1 index 62cc55d..874a4de 100644 --- a/documentation/xsde.1 +++ b/documentation/xsde.1 @@ -944,6 +944,10 @@ Suppress the generation of validation code in parser. .IP "\fB\--suppress-serializer-val\fR" Suppress the generation of validation code in serializer. +.IP "\fB\--omit-default-attributes\fR" +Omit attributes with default and fixed values from serialized XML +documents. + .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 c8f602a..697c751 100644 --- a/documentation/xsde.xhtml +++ b/documentation/xsde.xhtml @@ -816,6 +816,10 @@

--suppress-serializer-val
Suppress the generation of validation code in serializer.
+
--omit-default-attributes
+
Omit attributes with default and fixed values from serialized + XML documents.
+
--generate-detach
Generate detach functions for elements and attributes of variable-length types. These functions, for example, allow diff --git a/libxsde/xsde/cxx/hybrid/any-type.hxx b/libxsde/xsde/cxx/hybrid/any-type.hxx index f94f007..5042115 100644 --- a/libxsde/xsde/cxx/hybrid/any-type.hxx +++ b/libxsde/xsde/cxx/hybrid/any-type.hxx @@ -47,6 +47,18 @@ namespace xsde struct any_simple_type { }; + + inline bool + operator== (const any_simple_type&, const any_simple_type&) + { + return true; + } + + inline bool + operator!= (const any_simple_type&, const any_simple_type&) + { + return false; + } } } } diff --git a/libxsde/xsde/cxx/hybrid/base.hxx b/libxsde/xsde/cxx/hybrid/base.hxx index ba5090d..fdfdeac 100644 --- a/libxsde/xsde/cxx/hybrid/base.hxx +++ b/libxsde/xsde/cxx/hybrid/base.hxx @@ -8,6 +8,10 @@ #include +#ifndef XSDE_STL +# include // strcmp +#endif + namespace xsde { namespace cxx @@ -31,6 +35,18 @@ namespace xsde bool x_; }; + inline bool + operator== (const boolean_base& x, const boolean_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const boolean_base& x, const boolean_base& y) + { + return !(x == y); + } + // byte // struct byte_base @@ -48,6 +64,18 @@ namespace xsde signed char x_; }; + inline bool + operator== (const byte_base& x, const byte_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const byte_base& x, const byte_base& y) + { + return !(x == y); + } + // unsigned_byte // struct unsigned_byte_base @@ -66,6 +94,18 @@ namespace xsde unsigned char x_; }; + inline bool + operator== (const unsigned_byte_base& x, const unsigned_byte_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const unsigned_byte_base& x, const unsigned_byte_base& y) + { + return !(x == y); + } + // short // struct short_base @@ -83,6 +123,18 @@ namespace xsde short x_; }; + inline bool + operator== (const short_base& x, const short_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const short_base& x, const short_base& y) + { + return !(x == y); + } + // unsigned_short // struct unsigned_short_base @@ -101,6 +153,18 @@ namespace xsde unsigned short x_; }; + inline bool + operator== (const unsigned_short_base& x, const unsigned_short_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const unsigned_short_base& x, const unsigned_short_base& y) + { + return !(x == y); + } + // int // struct int_base @@ -118,6 +182,18 @@ namespace xsde int x_; }; + inline bool + operator== (const int_base& x, const int_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const int_base& x, const int_base& y) + { + return !(x == y); + } + // unsigned_int // struct unsigned_int_base @@ -135,6 +211,18 @@ namespace xsde unsigned int x_; }; + inline bool + operator== (const unsigned_int_base& x, const unsigned_int_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const unsigned_int_base& x, const unsigned_int_base& y) + { + return !(x == y); + } + // long // #ifdef XSDE_LONGLONG @@ -169,6 +257,18 @@ namespace xsde }; #endif + inline bool + operator== (const long_base& x, const long_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const long_base& x, const long_base& y) + { + return !(x == y); + } + // unsigned_long // @@ -206,6 +306,18 @@ namespace xsde }; #endif + inline bool + operator== (const unsigned_long_base& x, const unsigned_long_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const unsigned_long_base& x, const unsigned_long_base& y) + { + return !(x == y); + } + // integer // struct integer_base @@ -223,6 +335,18 @@ namespace xsde long x_; }; + inline bool + operator== (const integer_base& x, const integer_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const integer_base& x, const integer_base& y) + { + return !(x == y); + } + // negative_integer // struct negative_integer_base @@ -240,6 +364,20 @@ namespace xsde long x_; }; + inline bool + operator== (const negative_integer_base& x, + const negative_integer_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const negative_integer_base& x, + const negative_integer_base& y) + { + return !(x == y); + } + // non_positive_integer // struct non_positive_integer_base @@ -257,6 +395,20 @@ namespace xsde long x_; }; + inline bool + operator== (const non_positive_integer_base& x, + const non_positive_integer_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const non_positive_integer_base& x, + const non_positive_integer_base& y) + { + return !(x == y); + } + // positive_integer // struct positive_integer_base @@ -275,6 +427,20 @@ namespace xsde unsigned long x_; }; + inline bool + operator== (const positive_integer_base& x, + const positive_integer_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const positive_integer_base& x, + const positive_integer_base& y) + { + return !(x == y); + } + // non_negative_integer // struct non_negative_integer_base @@ -293,6 +459,20 @@ namespace xsde unsigned long x_; }; + inline bool + operator== (const non_negative_integer_base& x, + const non_negative_integer_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const non_negative_integer_base& x, + const non_negative_integer_base& y) + { + return !(x == y); + } + // float // struct float_base @@ -310,6 +490,18 @@ namespace xsde float x_; }; + inline bool + operator== (const float_base& x, const float_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const float_base& x, const float_base& y) + { + return !(x == y); + } + // double // struct double_base @@ -327,6 +519,18 @@ namespace xsde double x_; }; + inline bool + operator== (const double_base& x, const double_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const double_base& x, const double_base& y) + { + return !(x == y); + } + // decimal // struct decimal_base @@ -344,6 +548,19 @@ namespace xsde double x_; }; + inline bool + operator== (const decimal_base& x, const decimal_base& y) + { + return x.base_value () == y.base_value (); + } + + inline bool + operator!= (const decimal_base& x, const decimal_base& y) + { + return !(x == y); + } + +#ifndef XSDE_STL // string // struct string_base @@ -364,6 +581,19 @@ namespace xsde protected: char* x_; }; + + inline bool + operator== (const string_base& x, const string_base& y) + { + return strcmp (x.base_value (), y.base_value ()) == 0; + } + + inline bool + operator!= (const string_base& x, const string_base& y) + { + return !(x == y); + } +#endif } } } diff --git a/tests/cxx/hybrid/binary/cdr/output.xml b/tests/cxx/hybrid/binary/cdr/output.xml index a484661..f36f755 100644 --- a/tests/cxx/hybrid/binary/cdr/output.xml +++ b/tests/cxx/hybrid/binary/cdr/output.xml @@ -1,2 +1,2 @@ -1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== +1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== 6865782052696E6172792001-10-26+02:002001-10-26T21:32:52+02:00P1Y2M3DT5H20M30S---01+02:00--11+02:00--02-11+02:002001+02:002001-11+02:00 \ No newline at end of file diff --git a/tests/cxx/hybrid/binary/cdr/test.xml b/tests/cxx/hybrid/binary/cdr/test.xml index acd75d2..1218c37 100644 --- a/tests/cxx/hybrid/binary/cdr/test.xml +++ b/tests/cxx/hybrid/binary/cdr/test.xml @@ -6,10 +6,10 @@ left - + aaa - + aaa bbb c diff --git a/tests/cxx/hybrid/binary/cdr/test.xsd b/tests/cxx/hybrid/binary/cdr/test.xsd index 7a92c7e..5a2ea34 100644 --- a/tests/cxx/hybrid/binary/cdr/test.xsd +++ b/tests/cxx/hybrid/binary/cdr/test.xsd @@ -35,6 +35,18 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/binary/custom/output.xml b/tests/cxx/hybrid/binary/custom/output.xml index a484661..f36f755 100644 --- a/tests/cxx/hybrid/binary/custom/output.xml +++ b/tests/cxx/hybrid/binary/custom/output.xml @@ -1,2 +1,2 @@ -1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== +1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== 6865782052696E6172792001-10-26+02:002001-10-26T21:32:52+02:00P1Y2M3DT5H20M30S---01+02:00--11+02:00--02-11+02:002001+02:002001-11+02:00 \ No newline at end of file diff --git a/tests/cxx/hybrid/binary/custom/test.xml b/tests/cxx/hybrid/binary/custom/test.xml index acd75d2..1218c37 100644 --- a/tests/cxx/hybrid/binary/custom/test.xml +++ b/tests/cxx/hybrid/binary/custom/test.xml @@ -6,10 +6,10 @@ left - + aaa - + aaa bbb c diff --git a/tests/cxx/hybrid/binary/custom/test.xsd b/tests/cxx/hybrid/binary/custom/test.xsd index 7a92c7e..5a2ea34 100644 --- a/tests/cxx/hybrid/binary/custom/test.xsd +++ b/tests/cxx/hybrid/binary/custom/test.xsd @@ -35,6 +35,18 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/binary/xdr/output.xml b/tests/cxx/hybrid/binary/xdr/output.xml index a484661..f36f755 100644 --- a/tests/cxx/hybrid/binary/xdr/output.xml +++ b/tests/cxx/hybrid/binary/xdr/output.xml @@ -1,2 +1,2 @@ -1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== +1 2 3abcleftaaaaaabbbcccccc123abcdef12.34false6566-22257005-570053735928559-21474836482147483647-2147483648-214748364821474836472147483647-2147483648true1234.1212345678.12345681234567812345678stringnormalized stringone two threenamename-tokenname tokensncnameen-usxsi:schemaLocationelements1elements2elements1elements1 elements2http://www.codesynthesis.comYmFzZTY0IGJpbmFyeQ== 6865782052696E6172792001-10-26+02:002001-10-26T21:32:52+02:00P1Y2M3DT5H20M30S---01+02:00--11+02:00--02-11+02:002001+02:002001-11+02:00 \ No newline at end of file diff --git a/tests/cxx/hybrid/binary/xdr/test.xml b/tests/cxx/hybrid/binary/xdr/test.xml index acd75d2..1218c37 100644 --- a/tests/cxx/hybrid/binary/xdr/test.xml +++ b/tests/cxx/hybrid/binary/xdr/test.xml @@ -6,10 +6,10 @@ left - + aaa - + aaa bbb c diff --git a/tests/cxx/hybrid/binary/xdr/test.xsd b/tests/cxx/hybrid/binary/xdr/test.xsd index 7a92c7e..5a2ea34 100644 --- a/tests/cxx/hybrid/binary/xdr/test.xsd +++ b/tests/cxx/hybrid/binary/xdr/test.xsd @@ -35,6 +35,18 @@ + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/default/driver.cxx b/tests/cxx/hybrid/default/driver.cxx new file mode 100644 index 0000000..1ab379f --- /dev/null +++ b/tests/cxx/hybrid/default/driver.cxx @@ -0,0 +1,56 @@ +// file : tests/cxx/hybrid/default/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +// Test default attribute values. +// + +#include + +#include "test.hxx" +#include "test-pimpl.hxx" +#include "test-simpl.hxx" + +using namespace std; +using namespace test; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " test.xml" << endl; + return 1; + } + + // Parse. + // + root_paggr root_p; + + xml_schema::document_pimpl doc_p ( + root_p.root_parser (), + root_p.root_namespace (), + root_p.root_name ()); + + root_p.pre (); + doc_p.parse (argv[1]); + type* r = root_p.post (); + + // Serialize. + // + root_saggr root_s; + + xml_schema::document_simpl doc_s ( + root_s.root_serializer (), + root_s.root_namespace (), + root_s.root_name ()); + + doc_s.add_prefix ("t", "test"); + + root_s.pre (*r); + doc_s.serialize (cout); + root_s.post (); + + delete r; +} diff --git a/tests/cxx/hybrid/default/makefile b/tests/cxx/hybrid/default/makefile new file mode 100644 index 0000000..a13db85 --- /dev/null +++ b/tests/cxx/hybrid/default/makefile @@ -0,0 +1,98 @@ +# file : tests/cxx/hybrid/default/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := test.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o) \ +$(xsd:.xsd=-sskel.o) \ +$(xsd:.xsd=-simpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) \ + $(xsd:.xsd=-sskel.hxx) $(xsd:.xsd=-sskel.cxx) \ + $(xsd:.xsd=-simpl.hxx) $(xsd:.xsd=-simpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-serializer \ +--generate-aggregate + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Test. +# +.PHONY: $(test) + +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/test.xml $(src_base)/output + $(call message,test $$1,$$1 $(src_base)/test.xml | diff -ubB $(src_base)/output -,$(driver)) + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/tests/cxx/hybrid/default/output b/tests/cxx/hybrid/default/output new file mode 100644 index 0000000..8d41894 --- /dev/null +++ b/tests/cxx/hybrid/default/output @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/cxx/hybrid/default/test.xml b/tests/cxx/hybrid/default/test.xml new file mode 100644 index 0000000..11bd0a7 --- /dev/null +++ b/tests/cxx/hybrid/default/test.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/tests/cxx/hybrid/default/test.xsd b/tests/cxx/hybrid/default/test.xsd new file mode 100644 index 0000000..366b37e --- /dev/null +++ b/tests/cxx/hybrid/default/test.xsd @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cxx/hybrid/makefile b/tests/cxx/hybrid/makefile index 24ed1f0..46fc06c 100644 --- a/tests/cxx/hybrid/makefile +++ b/tests/cxx/hybrid/makefile @@ -8,7 +8,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make tests := polymorphism sequences ifeq ($(xsde_iostream),y) -tests += built-in list recursive test-template union +tests += built-in default list recursive test-template union ifeq ($(xsde_cdr),y) tests += binary/cdr diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx index 80b91bc..509005a 100644 --- a/xsde/cxx/hybrid/cli.hxx +++ b/xsde/cxx/hybrid/cli.hxx @@ -33,6 +33,7 @@ namespace CXX extern Key suppress_validation; extern Key suppress_parser_val; extern Key suppress_serializer_val; + extern Key omit_default_attributes; extern Key generate_detach; extern Key generate_insertion; extern Key generate_extraction; @@ -120,6 +121,7 @@ namespace CXX suppress_validation, Boolean, suppress_parser_val, Boolean, suppress_serializer_val, Boolean, + omit_default_attributes, Boolean, generate_detach, Boolean, generate_insertion, Cult::Containers::Vector, generate_extraction, Cult::Containers::Vector, diff --git a/xsde/cxx/hybrid/default-value.cxx b/xsde/cxx/hybrid/default-value.cxx new file mode 100644 index 0000000..895c764 --- /dev/null +++ b/xsde/cxx/hybrid/default-value.cxx @@ -0,0 +1,1210 @@ +// file : xsde/cxx/hybrid/default-value.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace CXX +{ + namespace Hybrid + { + namespace + { + Void + normalize (String& s) + { + Size n (s.size ()); + + for (Size i (0); i < n; ++i) + { + WideChar& c (s[i]); + + if (c == 0x0D || // carriage return + c == 0x09 || // tab + c == 0x0A) + c = 0x20; + } + } + + Void + collapse (String& s) + { + Size n (s.size ()), j (0); + Boolean subs (false), trim (true); + + for (Size i (0); i < n; ++i) + { + WideChar c (s[i]); + + if (c == 0x20 || c == 0x09 || c == 0x0A) + subs = true; + else + { + if (subs) + { + subs = false; + + if (!trim) + s[j++] = 0x20; + } + + if (trim) + trim = false; + + s[j++] = c; + } + } + + s.resize (j); + } + + Void + strip_zeros (String& s) + { + Size n (s.size ()), i (0); + + if (n > 0 && s[i] == '-' || s[i] == '+') + i++; + + Size j (i); + + Boolean strip (true); + + for (; i < n; ++i) + { + WideChar c (s[i]); + + if (c == '0') + { + if (!strip) + s[j++] = c; + } + else + { + s[j++] = c; + + if (strip) + strip = false; + } + } + + if (strip && j < n) + s[j++] = '0'; // There was nothing except zeros so add one back. + + s.resize (j); + } + } + + // + // LiteralValue + // + LiteralValue:: + LiteralValue (Context& c) + : Context (c), str_ (!stl) + { + } + + LiteralValue:: + LiteralValue (Context& c, Boolean str) + : Context (c), str_ (str) + { + } + + String LiteralValue:: + dispatch (SemanticGraph::Node& type, String const& value) + { + literal_.clear (); + value_ = value; + Traversal::NodeBase::dispatch (type); + return literal_; + } + + // Boolean. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Boolean&) + { + collapse (value_); + literal_ = (value_ == L"true" || value_ == L"1") ? "true" : "false"; + } + + // Integral types. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Byte&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Short&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Int&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Long&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + literal_ += options.value () ? L"L" : L"LL"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + literal_ += options.value () ? L"UL" : L"ULL"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Integer&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"L"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"L"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"UL"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"UL"; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"L"; + } + + // Floats. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Float&) + { + collapse (value_); + + if (value_ == L"NaN") + { + literal_ = "static_cast< float > (strtod (\"NAN\", 0))"; + } + else if (value_ == L"INF") + { + literal_ = "static_cast< float > (strtod (\"INF\", 0))"; + } + else if (value_ == L"-INF") + { + literal_ = "static_cast< float > (strtod (\"-INF\", 0))"; + } + else + { + strip_zeros (value_); + literal_ = value_ + L"F"; + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Double&) + { + collapse (value_); + + if (value_ == L"NaN") + { + literal_ = "strtod (\"NAN\", 0)"; + } + else if (value_ == L"INF") + { + literal_ = "strtod (\"INF\", 0)"; + } + else if (value_ == L"-INF") + { + literal_ = "strtod (\"-INF\", 0)"; + } + else + { + strip_zeros (value_); + literal_ = value_; + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Decimal&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + // Strings. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::String&) + { + if (str_) + literal_ = strlit (value_); + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + if (str_) + { + normalize (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Token&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NameToken&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Name&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::NCName&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Language&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + + // ID/IDREF. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Id&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::IdRef&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + // URI. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::AnyURI&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + // Entity. + // + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Entity&) + { + if (str_) + { + collapse (value_); + literal_ = strlit (value_); + } + } + + // + // InitValue + // + + InitValue:: + InitValue (Context& c) + : Context (c), + member_ ("this->value_."), + var_ (c, TypeName::var), + var_value_ (c, TypeName::var_value), + literal_value_ (c, true), + literal_value_list_ (c) + { + } + + Void InitValue:: + dispatch (SemanticGraph::Node& type, String const& value) + { + value_ = value; + Traversal::NodeBase::dispatch (type); + } + + Void InitValue:: + traverse (SemanticGraph::List& l) + { + SemanticGraph::Type& t (l.argumented ().type ()); + Boolean fl (fixed_length (t)); + + collapse (value_); + + if (!value_) + return; + + String ov (value_); + String om (member_); + + Size b (0); + + for (Size e (ov.find (' ')); ; e = ov.find (' ', b)) + { + String v (ov, b, e != String::npos ? e - b : e); + + os << "{"; + var_.dispatch (t); + os << " tmp;"; + + String literal (literal_value_list_.dispatch (t, v)); + + if (literal) + { + // Variable-length literal is a string. + // + if (fl) + os << "tmp = " << literal << ";"; + else + { + os << "tmp = ::xsde::cxx::strdupx (" << literal << ");"; + + if (!exceptions) + { + os << endl + << "if (!tmp)" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + } + } + } + else + { + if (fl) + member_ = "tmp."; + else + { + os << "tmp = new " << fq_name (t) << ";"; + + if (!exceptions) + { + os << endl + << "if (!tmp)" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + } + + member_ = "tmp->"; + } + + value_ = v; + Traversal::NodeBase::dispatch (t); + } + + if (exceptions) + os << om << "push_back (tmp);"; + else + os << "if (" << om << "push_back (tmp))" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + + os << "}"; + + if (e == String::npos) + break; + + b = e + 1; + } + + member_ = om; + value_ = ov; + } + + Void InitValue:: + traverse (SemanticGraph::Union& u) + { + String const& value (u.context ().get ("value")); + + if (stl) + os << member_ << value << " (" << strlit (value_) << ");"; + else + { + if (exceptions) + os << member_ << value << " ("; + else + os << "char* v = "; + + os << "::xsde::cxx::strdupx (" << strlit (value_) << ")"; + + if (exceptions) + os << ");"; + else + { + os << ";" + << endl + << "if (!v)" + << "{" + << "assert (false);" + << "exit (1);" + << "}" + << member_ << value << " (v);"; + } + } + } + + Void InitValue:: + traverse (SemanticGraph::Complex& c) + { + Traversal::NodeBase::dispatch (ultimate_base (c)); + } + + Void InitValue:: + traverse (SemanticGraph::Type& t) + { + // This is a fall-back case where we handle all other (literal) + // types. + // + os << member_ << "base_value (" << + literal_value_.dispatch (t, value_) << ");"; + } + + // anySimpleType. + // + Void InitValue:: + traverse (SemanticGraph::AnySimpleType&) + { + } + + // Strings. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::String& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Token& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NameToken& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NameTokens&) + { + string_sequence_type (); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Name& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NCName& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Language& t) + { + string_type (t); + } + + // Qualified name. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::QName&) + { + collapse (value_); + + String prefix, name; + Size p (value_.find (':')); + + if (p != String::npos) + { + prefix.assign (value_, 0, p); + name.assign (value_, p + 1, String::npos); + } + else + name = value_; + + if (stl) + { + os << member_ << "prefix (" << strlit (prefix) << ");" + << member_ << "name (" << strlit (name) << ");"; + } + else + { + if (exceptions) + os << member_ << "prefix_copy (" << strlit (prefix) << ");" + << member_ << "name_copy (" << strlit (name) << ");"; + else + os << "if (" << member_ << "prefix_copy (" << strlit (prefix) << + ") || " << member_ << "name_copy (" << strlit (name) << "))" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + } + } + + // ID/IDREF. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Id& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::IdRef& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::IdRefs&) + { + string_sequence_type (); + } + + // URI. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + string_type (t); + } + + // Binary. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Base64Binary&) + { + collapse (value_); + + if (value_) + os << "#error base64Binary default values are not yet supported" + << endl; + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::HexBinary&) + { + collapse (value_); + + if (value_) + os << "#error hexBinary default values are not yet supported" + << endl; + } + + + // Date/time. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Date&) + { + // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] + // + collapse (value_); + + Size b (0); + Size e (value_.find ('-', value_[0] == '-' ? 5 : 4)); + String year (value_, 0, e); + + b = e + 1; + String month (value_, b, 2); + + b += 3; + String day (value_, b, 2); + + strip_zeros (year); + strip_zeros (month); + strip_zeros (day); + + os << member_ << "year (" << year << ");" + << member_ << "month (" << month << ");" + << member_ << "day (" << day << ");"; + + time_zone (b + 2); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::DateTime&) + { + // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] + // + collapse (value_); + + Size b (0); + Size e (value_.find ('-', value_[0] == '-' ? 5 : 4)); + String year (value_, 0, e); + b = e + 1; + + String month (value_, b, 2); + b += 3; + + String day (value_, b, 2); + b += 3; + + String hours (value_, b, 2); + b += 3; + + String minutes (value_, b, 2); + b += 3; + + e = b + 2; + for (; e < value_.size (); ++e) + { + WideChar c (value_[e]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String seconds (value_, b, e - b); + + strip_zeros (year); + strip_zeros (month); + strip_zeros (day); + strip_zeros (hours); + strip_zeros (minutes); + strip_zeros (seconds); + + os << member_ << "year (" << year << ");" + << member_ << "month (" << month << ");" + << member_ << "day (" << day << ");" + << member_ << "hours (" << hours << ");" + << member_ << "minutes (" << minutes << ");" + << member_ << "seconds (" << seconds << ");"; + + time_zone (e); + } + + namespace + { + Size + find_delim (String const& s, Size pos) + { + for (; pos < s.size (); ++pos) + { + WideChar c (s[pos]); + + if (c == 'Y' || c == 'D' || c == 'M' || c == 'H' || + c == 'M' || c == 'S' || c == 'T') + break; + } + + return pos; + } + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Duration&) + { + // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] + // + collapse (value_); + + Size b (1), e, n (value_.size ()); + + if (value_[0] == '-') + { + os << member_ << "negative (true);"; + b++; + } + + e = find_delim (value_, b); + + if (e < n && value_[e] == 'Y') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "years (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'M') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "months (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'D') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "days (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'T') + { + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'H') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "hours (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'M') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "minutes (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + + if (e < n && value_[e] == 'S') + { + String v (value_, b, e - b); + strip_zeros (v); + os << member_ << "seconds (" << v << ");"; + + b = e + 1; + e = find_delim (value_, b); + } + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Day&) + { + // gday := ---DD[Z|(+|-)HH:MM] + // + collapse (value_); + + String day (value_, 3, 2); + strip_zeros (day); + + os << member_ << "day (" << day << ");"; + + time_zone (5); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Month&) + { + // gmonth := --MM[Z|(+|-)HH:MM] + // + collapse (value_); + + String month (value_, 2, 2); + strip_zeros (month); + + os << member_ << "month (" << month << ");"; + + time_zone (4); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::MonthDay&) + { + // gmonth_day := --MM-DD[Z|(+|-)HH:MM] + // + collapse (value_); + + String month (value_, 2, 2); + String day (value_, 5, 2); + + strip_zeros (month); + strip_zeros (day); + + os << member_ << "month (" << month << ");"; + os << member_ << "day (" << day << ");"; + + time_zone (7); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Year&) + { + // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] + // + collapse (value_); + + Size pos (value_[0] == '-' ? 5 : 4); + for (; pos < value_.size (); ++pos) + { + WideChar c (value_[pos]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String year (value_, 0, pos); + strip_zeros (year); + + os << member_ << "year (" << year << ");"; + + time_zone (pos); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::YearMonth&) + { + // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] + // + collapse (value_); + + Size pos (value_.find ('-', value_[0] == '-' ? 5 : 4)); + + String year (value_, 0, pos); + String month (value_, pos + 1, 2); + + strip_zeros (year); + strip_zeros (month); + + os << member_ << "year (" << year << ");"; + os << member_ << "month (" << month << ");"; + + time_zone (pos + 3); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Time&) + { + // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] + // + collapse (value_); + + String hours (value_, 0, 2); + String minutes (value_, 3, 2); + + Size e (8); + for (; e < value_.size (); ++e) + { + WideChar c (value_[e]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String seconds (value_, 6, e - 6); + + strip_zeros (hours); + strip_zeros (minutes); + strip_zeros (seconds); + + os << member_ << "hours (" << hours << ");" + << member_ << "minutes (" << minutes << ");" + << member_ << "seconds (" << seconds << ");"; + + time_zone (e); + } + + Void InitValue:: + time_zone (Size pos) + { + // time_zone := Z|(+|-)HH:MM + // + if (pos < value_.size ()) + { + String h, m; + + if (value_[pos] == 'Z') + { + h = "0"; + m = "0"; + } + else + { + if (value_[pos] == '-') + { + h = "-"; + m = "-"; + } + + h.append (value_, pos + 1, 2); + m.append (value_, pos + 4, 2); + + strip_zeros (h); + strip_zeros (m); + } + + os << member_ << "zone_hours (" << h << ");" + << member_ << "zone_minutes (" << m << ");"; + } + } + + // Entity. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Entity& t) + { + string_type (t); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Entities&) + { + string_sequence_type (); + } + + Void InitValue:: + string_type (SemanticGraph::Fundamental::Type& t) + { + // In case STL is disabled, strings are returned as literals + // so we end up here only if the type is derived from a string. + // Otherwise, use assign() which handles both derivations as + // well as the straight std::string value. + // + if (stl) + os << member_ << "assign (" << literal_value_.dispatch (t, value_) << + ");"; + else + { + if (exceptions) + os << member_ << "base_value ("; + else + os << "char* v = "; + + os << "::xsde::cxx::strdupx (" << + literal_value_.dispatch (t, value_) << ")"; + + if (exceptions) + os << ");"; + else + { + os << ";" + << endl + << "if (!v)" + << "{" + << "assert (false);" + << "exit (1);" + << "}" + << member_ << "base_value (v);"; + } + } + } + + Void InitValue:: + string_sequence_type () + { + collapse (value_); + + if (!value_) + return; + + Size b (0); + + for (Size e (value_.find (' ')); ; e = value_.find (' ', b)) + { + String v (value_, b, e != String::npos ? e - b : e); + + os << "{"; + + if (stl) + os << "::std::string tmp ("; + else + os << "char* tmp = ::xsde::cxx::strdupx ("; + + os << strlit (v) << ");"; + + if (!exceptions && !stl) + { + os << endl + << "if (!tmp)" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + } + + if (exceptions) + os << member_ << "push_back (tmp);"; + else + os << "if (" << member_ << "push_back (tmp))" + << "{" + << "assert (false);" + << "exit (1);" + << "}"; + + os << "}"; + + if (e == String::npos) + break; + + b = e + 1; + } + } + + // + // CompareValue + // + + CompareValue:: + CompareValue (Context& c) + : Context (c) + { + } + + Void CompareValue:: + dispatch (SemanticGraph::Node& type, String const& lhs, String const& rhs) + { + lhs_ = &lhs; + rhs_ = &rhs; + Traversal::NodeBase::dispatch (type); + } + + Void CompareValue:: + traverse (SemanticGraph::Union& u) + { + String const& value (u.context ().get ("value")); + + os << *lhs_ << "." << value << " () == " << *rhs_ << "." << value << + " ()"; + } + + Void CompareValue:: + traverse (SemanticGraph::Complex& c) + { + Traversal::NodeBase::dispatch (ultimate_base (c)); + } + + Void CompareValue:: + traverse (SemanticGraph::Type& t) + { + // This is a fall-back case where we handle all other types. + // + os << *lhs_ << " == " << *rhs_; + } + } +} diff --git a/xsde/cxx/hybrid/default-value.hxx b/xsde/cxx/hybrid/default-value.hxx new file mode 100644 index 0000000..b9f902c --- /dev/null +++ b/xsde/cxx/hybrid/default-value.hxx @@ -0,0 +1,366 @@ +// file : xsde/cxx/hybrid/default-value.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_HYBRID_DEFAULT_VALUE_HXX +#define CXX_HYBRID_DEFAULT_VALUE_HXX + +#include +#include + +#include + +namespace CXX +{ + namespace Hybrid + { + struct LiteralValue: Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::AnyURI, + Traversal::Fundamental::Entity, + + Context + { + LiteralValue (Context&); + LiteralValue (Context&, Boolean str); + + String + dispatch (SemanticGraph::Node& type, String const& value); + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean&); + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte&); + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte&); + + virtual Void + traverse (SemanticGraph::Fundamental::Short&); + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort&); + + virtual Void + traverse (SemanticGraph::Fundamental::Int&); + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt&); + + virtual Void + traverse (SemanticGraph::Fundamental::Long&); + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong&); + + virtual Void + traverse (SemanticGraph::Fundamental::Integer&); + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&); + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&); + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger&); + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger&); + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float&); + + virtual Void + traverse (SemanticGraph::Fundamental::Double&); + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal&); + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&); + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&); + + virtual Void + traverse (SemanticGraph::Fundamental::Token&); + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&); + + virtual Void + traverse (SemanticGraph::Fundamental::Name&); + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&); + + virtual Void + traverse (SemanticGraph::Fundamental::Language&); + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&); + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&); + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&); + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&); + + private: + Boolean str_; + String value_; + String literal_; + }; + + struct InitValue: Traversal::List, + Traversal::Union, + Traversal::Complex, + Traversal::Type, + + Traversal::AnySimpleType, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + + Context + { + InitValue (Context&); + + Void + dispatch (SemanticGraph::Node& type, String const& value); + + virtual Void + traverse (SemanticGraph::List&); + + virtual Void + traverse (SemanticGraph::Union&); + + virtual Void + traverse (SemanticGraph::Complex&); + + virtual Void + traverse (SemanticGraph::Type& t); + + // anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnySimpleType&); + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&); + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&); + + virtual Void + traverse (SemanticGraph::Fundamental::Token&); + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&); + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens&); + + virtual Void + traverse (SemanticGraph::Fundamental::Name&); + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&); + + virtual Void + traverse (SemanticGraph::Fundamental::Language&); + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName&); + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&); + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&); + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs&); + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&); + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary&); + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary&); + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date&); + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime&); + + virtual Void + traverse (SemanticGraph::Fundamental::Duration&); + + virtual Void + traverse (SemanticGraph::Fundamental::Day&); + + virtual Void + traverse (SemanticGraph::Fundamental::Month&); + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay&); + + virtual Void + traverse (SemanticGraph::Fundamental::Year&); + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth&); + + virtual Void + traverse (SemanticGraph::Fundamental::Time&); + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&); + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&); + + private: + Void + string_type (SemanticGraph::Fundamental::Type&); + + Void + string_sequence_type (); + + Void + time_zone (Size pos); + + private: + String member_; + String value_; + TypeName var_; + TypeName var_value_; + LiteralValue literal_value_; + LiteralValue literal_value_list_; + }; + + struct CompareValue: Traversal::Union, + Traversal::Complex, + Traversal::Type, + Context + { + CompareValue (Context&); + + Void + dispatch (SemanticGraph::Node& type, + String const& lhs, + String const& rhs); + + virtual Void + traverse (SemanticGraph::Union&); + + virtual Void + traverse (SemanticGraph::Complex&); + + virtual Void + traverse (SemanticGraph::Type& t); + + private: + String const* lhs_; + String const* rhs_; + }; + } +} + +#endif // CXX_HYBRID_DEFAULT_VALUE_HXX diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx index 8452976..9faeb8d 100644 --- a/xsde/cxx/hybrid/elements.hxx +++ b/xsde/cxx/hybrid/elements.hxx @@ -161,6 +161,18 @@ namespace CXX } static String const& + edefault (SemanticGraph::Attribute& a) + { + return a.context ().get ("default"); + } + + static String const& + edefault_value (SemanticGraph::Attribute& a) + { + return a.context ().get ("default-value"); + } + + static String const& epresent_member (SemanticGraph::Particle& p) { return p.context ().get ("present-member"); @@ -922,6 +934,7 @@ namespace CXX ret, arg, var, + var_value, seq }; @@ -1368,6 +1381,11 @@ namespace CXX break; } + case var_value: + { + os << fq; + break; + } case seq: { os << (fixed_length (t) ? fix_seq : var_seq) << "< " << @@ -1437,6 +1455,7 @@ namespace CXX break; } case var: + case var_value: { if (stl) os << "::std::string"; diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx index 5945ce3..5460740 100644 --- a/xsde/cxx/hybrid/extraction-source.cxx +++ b/xsde/cxx/hybrid/extraction-source.cxx @@ -108,6 +108,11 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { + // Nothing is serialized for fixed attributes. + // + if (a.fixed ()) + return; + SemanticGraph::Type& t (a.type ()); Boolean fl (fixed_length (t)); @@ -125,21 +130,39 @@ namespace CXX if (a.optional ()) { - os << "bool p;"; + if (!a.default_ ()) + { + os << "bool p;"; + + if (exceptions) + os << "s >> p;"; + else + os << endl + << "if (!(s >> p))" << endl + << "return false;"; - if (exceptions) - os << "s >> p;"; - else os << endl - << "if (!(s >> p))" << endl - << "return false;"; + << "if (p)" + << "{"; - os << endl - << "if (p)" - << "{"; + if (fl) + os << "x." << epresent (a) << " (true);"; + } + else + { + os << "bool d;"; - if (fl) - os << "x." << epresent (a) << " (true);"; + if (exceptions) + os << "s >> d;"; + else + os << endl + << "if (!(s >> d))" << endl + << "return false;"; + + os << endl + << "if (!d)" + << "{"; + } } if (st) @@ -181,9 +204,20 @@ namespace CXX } if (a.optional ()) - os << "}" - << "else" << endl - << "x." << epresent (a) << " (false);"; + { + if (!a.default_ ()) + { + os << "}" + << "else" << endl + << "x." << epresent (a) << " (false);"; + } + else + { + os << "}" + << "else" << endl + << "x." << edefault (a) << " (true);"; + } + } os << "}"; } diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx index 3eba4ba..78b9142 100644 --- a/xsde/cxx/hybrid/generator.cxx +++ b/xsde/cxx/hybrid/generator.cxx @@ -121,6 +121,7 @@ namespace CXX extern Key suppress_validation = "suppress-validation"; 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 generate_detach = "generate-detach"; extern Key generate_insertion = "generate-insertion"; extern Key generate_extraction = "generate-extraction"; @@ -251,6 +252,11 @@ namespace CXX << " serializer." << endl; + e << "--omit-default-attributes" << endl + << " Omit attributes with default and fixed values\n" + << " from serialized XML documents." + << endl; + e << "--generate-detach" << endl << " Generate detach functions for elements and\n" << " attributes of variable-length types." diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx index b0b89c9..7dc6fcb 100644 --- a/xsde/cxx/hybrid/insertion-source.cxx +++ b/xsde/cxx/hybrid/insertion-source.cxx @@ -100,19 +100,41 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { + // Don't waste space on fixed attributes. + // + if (a.fixed ()) + return; + if (a.optional ()) { - String const& present (epresent (a)); + if (!a.default_ ()) + { + String const& present (epresent (a)); - if (exceptions) - os << "s << x." << present << " ();"; + if (exceptions) + os << "s << x." << present << " ();"; + else + os << "if (!(s << x." << present << " ()))" << endl + << "return false;"; + + os << endl + << "if (x." << present << " ())" + << "{"; + } else - os << "if (!(s << x." << present << " ()))" << endl - << "return false;"; + { + String const& default_ (edefault (a)); - os << endl - << "if (x." << present << " ())" - << "{"; + if (exceptions) + os << "s << x." << default_ << " ();"; + else + os << "if (!(s << x." << default_ << " ()))" << endl + << "return false;"; + + os << endl + << "if (!x." << default_ << " ())" + << "{"; + } } String const& name (ename (a)); diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx index 6a893c5..c174df4 100644 --- a/xsde/cxx/hybrid/parser-header.cxx +++ b/xsde/cxx/hybrid/parser-header.cxx @@ -334,6 +334,9 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { + if (a.fixed ()) + return; + String const& arg (parg_type (a.type ())); os << "virtual void" << endl diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx index 505d661..bfeb129 100644 --- a/xsde/cxx/hybrid/parser-source.cxx +++ b/xsde/cxx/hybrid/parser-source.cxx @@ -879,6 +879,9 @@ namespace CXX { using SemanticGraph::Complex; + if (a.fixed ()) + return; + String const& name (epname (a)); String const& arg (parg_type (a.type ())); Complex& c (dynamic_cast (a.scope ())); diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx index 540d742..b0c194e 100644 --- a/xsde/cxx/hybrid/serializer-source.cxx +++ b/xsde/cxx/hybrid/serializer-source.cxx @@ -886,9 +886,26 @@ namespace CXX { os << "bool " << s << "::" << endl << espresent (a) << " ()" - << "{" - << "return " << access << epresent (a) << " ();" - << "}"; + << "{"; + + if (a.default_ ()) + { + Boolean omit (options.value ()); + + if (a.fixed ()) + os << "return " << (omit ? "false" : "true") << ";"; + else + { + if (omit) + os << "return !" << access << edefault (a) << " ();"; + else + os << "return true;"; + } + } + else + os << "return " << access << epresent (a) << " ();"; + + os << "}"; } SemanticGraph::Type& t (a.type ()); diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx index 7b2cae6..9bcb6f5 100644 --- a/xsde/cxx/hybrid/tree-forward.cxx +++ b/xsde/cxx/hybrid/tree-forward.cxx @@ -350,7 +350,10 @@ namespace CXX traverse (SemanticGraph::Fundamental::String&) { gen_typedef ("string", string_type_); - gen_using ("::xsde::cxx::hybrid::string_base"); + + if (!stl) + gen_using ("::xsde::cxx::hybrid::string_base"); + os << endl; } diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx index 3003e4c..77a1c71 100644 --- a/xsde/cxx/hybrid/tree-header.cxx +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -369,6 +369,7 @@ namespace CXX Traversal::Fundamental::Token, Traversal::Fundamental::Name, Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, Traversal::Fundamental::NCName, Traversal::Fundamental::Language, @@ -376,6 +377,7 @@ namespace CXX Traversal::Fundamental::Id, Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, Traversal::Fundamental::AnyURI, @@ -390,6 +392,7 @@ namespace CXX Traversal::Fundamental::Time, Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, Context { @@ -636,6 +639,12 @@ namespace CXX } virtual Void + traverse (SemanticGraph::Fundamental::NameTokens&) + { + align_type ("size_t"); + } + + virtual Void traverse (SemanticGraph::Fundamental::Name&) { align_type ("size_t"); // std::string @@ -676,6 +685,12 @@ namespace CXX align_type ("size_t"); // std::string } + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs&) + { + align_type ("size_t"); + } + // URI. // virtual Void @@ -749,6 +764,12 @@ namespace CXX align_type ("size_t"); // std::string } + virtual Void + traverse (SemanticGraph::Fundamental::Entities&) + { + align_type ("size_t"); + } + private: Void align_type (Char const* t) @@ -767,7 +788,17 @@ namespace CXX private: Traversal::Inherits inherits_; - Traversal::Attribute attribute_; + struct Attribute: Traversal::Attribute + { + virtual Void + traverse (Type& a) + { + if (!a.fixed ()) + Traversal::Attribute::traverse (a); + } + }; + + Attribute attribute_; Traversal::Names attribute_names_; Traversal::Element particle_; @@ -787,13 +818,16 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { - SemanticGraph::Type& t (a.type ()); + if (!a.fixed ()) + { + SemanticGraph::Type& t (a.type ()); - var_.dispatch (t); - os << " " << emember (a) << ";"; + var_.dispatch (t); + os << " " << emember (a) << ";"; - if (a.optional () && fixed_length (t)) - os << "bool " << epresent_member (a) << ";"; + if (a.optional () && !a.default_ () && fixed_length (t)) + os << "bool " << epresent_member (a) << ";"; + } } private: @@ -1105,19 +1139,23 @@ namespace CXX os << "// " << comment (a.name ()) << endl << "// " << endl; + Boolean def (a.default_ ()); + Boolean fix (a.fixed ()); + String const& name (ename (a)); SemanticGraph::Type& t (a.type ()); - if (a.optional ()) + + if (a.optional () && !fix) { - String const& present (epresent (a)); + String const& name (def ? edefault (a) : epresent (a)); os << "bool" << endl - << present << " () const;" + << name << " () const;" << endl; os << "void" << endl - << present << " (bool);" + << name << " (bool);" << endl; } @@ -1129,32 +1167,49 @@ namespace CXX << name << " () const;" << endl; - // type& - // name () + // Do not generate modifiers for fixed attributes. // - ret_.dispatch (t); - os << endl - << name << " ();" - << endl; + if (!fix) + { + // type& + // name () + // + ret_.dispatch (t); + os << endl + << name << " ();" + << endl; - // void - // name (const type& | type*) - // - os << "void" << endl - << name << " ("; - arg_.dispatch (t); - os << ");" - << endl; + // void + // name (const type& | type*) + // + os << "void" << endl + << name << " ("; + arg_.dispatch (t); + os << ");" + << endl; - // type* - // detach () - // - if (detach && !fixed_length (t)) + // type* + // detach () + // + if (detach && !fixed_length (t)) + { + arg_.dispatch (t); + os << endl + << edetach (a) << " ();" + << endl; + } + } + + if (def) { - arg_.dispatch (t); + // static const type& + // name_{default|fixed}_value () + // + os << "static "; + ro_ret_.dispatch (t); os << endl - << edetach (a) << " ();" + << edefault_value (a) << " ();" << endl; } } diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx index 7cb4b2c..2783b5c 100644 --- a/xsde/cxx/hybrid/tree-inline.cxx +++ b/xsde/cxx/hybrid/tree-inline.cxx @@ -4,6 +4,7 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include +#include #include #include @@ -239,36 +240,58 @@ namespace CXX ret_ (c, TypeName::ret), arg_ (c, TypeName::arg), deref_ (c, TypeOps::deref), - delete_ (c, TypeOps::delete_) + delete_ (c, TypeOps::delete_), + compare_value_ (c) { } virtual Void traverse (SemanticGraph::Attribute& a) { + Boolean def (a.default_ ()); + Boolean fix (a.fixed ()); + String const& name (ename (a)); - String const& member (emember (a)); + String member; + + if (!fix) + member = emember (a); SemanticGraph::Type& t (a.type ()); Boolean fl (fixed_length (t)); String scope (Context::scope (a)); - if (a.optional ()) + if (a.optional () && !fix) { - String const& present (epresent (a)); + String const& name (def ? edefault (a) : epresent (a)); // bool // preset () const; // os << inl << "bool " << scope << "::" << endl - << present << " () const" + << name << " () const" << "{"; - if (fl) - os << "return this->" << epresent_member (a) << ";"; + if (def) + { + if (fl) + { + os << "return "; + compare_value_.dispatch ( + t, L"this->" + member, edefault_value (a) + L" ()"); + os << ";"; + } + else + os << "return this->" << member << " == 0;"; + } else - os << "return this->" << member << " != 0;"; + { + if (fl) + os << "return this->" << epresent_member (a) << ";"; + else + os << "return this->" << member << " != 0;"; + } os << "}"; @@ -277,19 +300,41 @@ namespace CXX // os << inl << "void " << scope << "::" << endl - << present << " (bool x)" + << name << " (bool x)" << "{"; - if (fl) - os << "this->" << epresent_member (a) << " = x;"; + if (def) + { + os << "if (x)"; + + if (fl) + { + os << endl + << "this->" << member << " = " << edefault_value (a) << + " ();"; + } + else + { + os << "{"; + delete_.dispatch (t); + os << " this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } + } else { - os << "if (!x)" - << "{"; - delete_.dispatch (t); - os << " this->" << member << ";" - << "this->" << member << " = 0;" - << "}"; + if (fl) + os << "this->" << epresent_member (a) << " = x;"; + else + { + os << "if (!x)" + << "{"; + delete_.dispatch (t); + os << " this->" << member << ";" + << "this->" << member << " = 0;" + << "}"; + } } os << "}"; @@ -302,65 +347,109 @@ namespace CXX ro_ret_.dispatch (t); os << " " << scope << "::" << endl << name << " () const" - << "{" - << "return "; - deref_.dispatch (t); - os << "this->" << member << ";" - << "}"; - - // type& - // name () - // - os << inl; - ret_.dispatch (t); - os << " " << scope << "::" << endl - << name << " ()" - << "{" - << "return "; - deref_.dispatch (t); - os << "this->" << member << ";" - << "}"; - - - // void - // name (const type& | type*) - // - os << inl - << "void " << scope << "::" << endl - << name << " ("; - arg_.dispatch (t); - os << " x)" << "{"; - if (!fl) + if (fix) { - delete_.dispatch (t); - os << " this->" << member << ";"; + os << "return " << edefault_value (a) << " ();"; + } + else if (def) + { + if (fl) + os << "return this->" << member << ";"; + else + { + os << "return this->" << member << " ? "; + deref_.dispatch (t); + os << "this->" << member << " : " << + edefault_value (a) << " ();"; + } + } + else + { + os << "return "; + deref_.dispatch (t); + os << "this->" << member << ";"; } - - os << "this->" << member << " = x;"; - - if (fl && a.optional ()) - os << "this->" << epresent_member (a) << " = true;"; os << "}"; - - // type* - // detach () + // Do not generate modifiers for fixed attributes. // - if (detach && !fl) + if (!fix) { + // type& + // name () + // os << inl; - arg_.dispatch (t); + ret_.dispatch (t); os << " " << scope << "::" << endl - << edetach (a) << " ()" + << name << " ()" << "{"; + + if (def) + { + if (fl) + os << "return this->" << member << ";"; + else + { + os << "return this->" << member << " ? "; + deref_.dispatch (t); + os << "this->" << member << " : const_cast< "; + ret_.dispatch (t); + os << " > (" << edefault_value (a) << " ());"; + } + } + else + { + os << "return "; + deref_.dispatch (t); + os << "this->" << member << ";"; + } + + os << "}"; + + + // void + // name (const type& | type*) + // + os << inl + << "void " << scope << "::" << endl + << name << " ("; arg_.dispatch (t); - os << " r = this->" << member << ";" - << "this->" << member << " = 0;" - << "return r;" - << "}"; + os << " x)" + << "{"; + + if (!fl) + { + delete_.dispatch (t); + os << " this->" << member << ";"; + } + + os << "this->" << member << " = x;"; + + if (fl && !def && a.optional ()) + os << "this->" << epresent_member (a) << " = true;"; + + os << "}"; + + + // type* + // detach () + // + if (detach && !fl) + { + os << inl; + arg_.dispatch (t); + os << " " << scope << "::" << endl + << edetach (a) << " ()" + << "{"; + arg_.dispatch (t); + os << " r = this->" << member << ";" + << "this->" << member << " = 0;" + << "return r;" + << "}"; + } } } @@ -370,6 +459,7 @@ namespace CXX TypeName arg_; TypeOps deref_; TypeOps delete_; + CompareValue compare_value_; }; struct ElementFunc: Traversal::Element, Context diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx index 9308598..da128c0 100644 --- a/xsde/cxx/hybrid/tree-name-processor.cxx +++ b/xsde/cxx/hybrid/tree-name-processor.cxx @@ -546,28 +546,41 @@ namespace CXX { SemanticGraph::Context& ac (a.context ()); + Boolean def (a.default_ ()); + Boolean fix (a.fixed ()); + + String const& base (ac.get ("name")); + if (!data_members_) { - if (a.optional ()) - ac.set ( - "present", - find_name (ac.get ("name") + L"_present", set_)); + if (a.optional () && !fix) + { + String n; + if (def) + n = find_name (base + L"_default", set_); + else + n = find_name (base + L"_present", set_); - if (detach && !fixed_length (a.type ())) - ac.set ( - "detach", - find_name (ac.get ("name") + L"_detach", set_)); + ac.set (def ? "default" : "present", n); + } + + if (detach && !fix && !fixed_length (a.type ())) + ac.set ("detach", find_name (base + L"_detach", set_)); + if (def) + { + ac.set ( + "default-value", + find_name (base + (fix ? L"_fixed_value" : L"_default_value"), + set_)); + } } - else + else if (!fix) { - String const& base (ac.get ("name")); - - if (a.optional ()) + if (a.optional () && !a.default_ () && fixed_length (a.type ())) { - if (fixed_length (a.type ())) - ac.set ("present-member", - find_name (ac.get ("present") + L"_", set_)); + ac.set ("present-member", + find_name (ac.get ("present") + L"_", set_)); } ac.set ("member", find_name (base + L"_", set_)); diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx index 2723046..eb83658 100644 --- a/xsde/cxx/hybrid/tree-source.cxx +++ b/xsde/cxx/hybrid/tree-source.cxx @@ -4,6 +4,7 @@ // license : GNU GPL v2 + exceptions; see accompanying LICENSE file #include +#include #include #include @@ -169,6 +170,73 @@ namespace CXX } }; + + struct AttributeFunc: Traversal::Attribute, Context + { + AttributeFunc (Context& c) + : Context (c), + var_ (c, TypeName::var_value), + ro_ret_ (c, TypeName::ro_ret), + literal_value_ (c), + init_value_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (a.default_ ()) + { + SemanticGraph::Type& t (a.type ()); + + String literal (literal_value_.dispatch (t, a.value ())); + String init; + + if (!literal) + { + String const& name (ename (a)); + String const& scope_name (ename (a.scope ())); + + init = L"_xsde_" + scope_name + L"_" + name + L"_default_value"; + + os << "struct " << init + << "{" + << init << " ()" + << "{"; + init_value_.dispatch (t, a.value ()); + os << "}"; + + var_.dispatch (t); + os << " value_;" + << "};" + << "static const " << init << " " << init << "_;" + << endl; + } + + // static const type& + // name_{default|fixed}_value () + // + ro_ret_.dispatch (t); + os << " " << scope (a) << "::" << endl + << edefault_value (a) << " ()" + << "{"; + + if (literal) + os << "return " << literal << ";"; + else + os << "return " << init << "_.value_;"; + + os << "}"; + } + } + + private: + TypeName var_; + TypeName ro_ret_; + LiteralValue literal_value_; + InitValue init_value_; + }; + struct ChoiceParticle: Traversal::Element, Traversal::Compositor, Context @@ -600,13 +668,24 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { - Boolean fl (fixed_length (a.type ())); + if (!a.fixed ()) + { + Boolean def (a.default_ ()); + Boolean fl (fixed_length (a.type ())); - if (!fl) - os << "this->" << emember (a) << " = 0;"; + if (!fl) + { + os << "this->" << emember (a) << " = 0;"; + } + else if (def) + { + os << "this->" << emember (a) << " = " << + edefault_value (a) << " ();"; + } - if (fl && a.optional ()) - os << "this->" << epresent_member (a) << " = false;"; + if (fl && !def && a.optional ()) + os << "this->" << epresent_member (a) << " = false;"; + } } }; @@ -726,12 +805,15 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { - SemanticGraph::Type& t (a.type ()); - - if (!fixed_length (t)) + if (!a.fixed ()) { - delete_.dispatch (t); - os << " this->" << emember (a) << ";"; + SemanticGraph::Type& t (a.type ()); + + if (!fixed_length (t)) + { + delete_.dispatch (t); + os << " this->" << emember (a) << ";"; + } } } @@ -852,17 +934,20 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { - String const& member (emember (a)); - - if (a.optional ()) + if (!a.fixed ()) { - String const& present_member (epresent_member (a)); + String const& member (emember (a)); - os << "this->" << present_member << " = x." << present_member << ";" - << "if (this->" << present_member << ")" << endl; - } + if (a.optional () && !a.default_ ()) + { + String const& present (epresent_member (a)); - os << "this->" << member << " = x." << member << ";"; + os << "this->" << present << " = x." << present << ";" + << "if (this->" << present << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } } }; @@ -993,17 +1078,20 @@ namespace CXX virtual Void traverse (SemanticGraph::Attribute& a) { - String const& member (emember (a)); - - if (a.optional ()) + if (!a.fixed ()) { - String const& present_member (epresent_member (a)); + String const& member (emember (a)); - os << "this->" << present_member << " = x." << present_member << ";" - << "if (this->" << present_member << ")" << endl; - } + if (a.optional () && !a.default_ ()) + { + String const& present (epresent_member (a)); - os << "this->" << member << " = x." << member << ";"; + os << "this->" << present << " = x." << present << ";" + << "if (this->" << present << ")" << endl; + } + + os << "this->" << member << " = x." << member << ";"; + } } }; @@ -1451,6 +1539,7 @@ namespace CXX // Functions. // + attribute_func_ (c), choice_in_choice_func_ (c, true), choice_in_sequence_func_ (c, false), sequence_in_choice_func_ (c, true), @@ -1516,6 +1605,8 @@ namespace CXX { // Functions. // + attribute_names_func_ >> attribute_func_; + sequence_in_choice_func_ >> sequence_contains_func_; sequence_in_sequence_func_ >> sequence_contains_func_; sequence_contains_func_ >> choice_in_sequence_func_; @@ -1713,6 +1804,8 @@ namespace CXX // Functions. // + Complex::names (c, attribute_names_func_); + if (c.contains_compositor_p ()) Complex::contains_compositor (c, contains_compositor_func_); } @@ -1770,6 +1863,9 @@ namespace CXX // Functions. // + AttributeFunc attribute_func_; + Traversal::Names attribute_names_func_; + ChoiceFunc choice_in_choice_func_; ChoiceFunc choice_in_sequence_func_; SequenceFunc sequence_in_choice_func_; @@ -1855,6 +1951,11 @@ namespace CXX { // Needed for placement new. // + ctx.os << "#include " << endl; // strtod, exit + + if (!ctx.exceptions) + ctx.os << "#include " << endl; + ctx.os << "#include " << endl << endl; diff --git a/xsde/makefile b/xsde/makefile index a8a4928..75a55a4 100644 --- a/xsde/makefile +++ b/xsde/makefile @@ -53,6 +53,7 @@ cxx_tun += cxx/serializer/elements.cxx \ cxx_tun += cxx/hybrid/elements.cxx \ cxx/hybrid/validator.cxx \ cxx/hybrid/generator.cxx \ + cxx/hybrid/default-value.cxx \ cxx/hybrid/tree-size-processor.cxx \ cxx/hybrid/tree-name-processor.cxx \ cxx/hybrid/tree-forward.cxx \ @@ -75,13 +76,11 @@ cxx_tun += cxx/hybrid/elements.cxx \ cxx/hybrid/serializer-aggregate-header.cxx \ cxx/hybrid/serializer-aggregate-source.cxx - # Type map # cxx_tun += type-map/lexer.cxx \ type-map/parser.cxx - # Processing # cxx_tun += processing/inheritance/processor.cxx -- cgit v1.1