aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-01-08 17:03:18 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-01-08 17:03:18 +0200
commitd0743458695eb2bb764bc308a9496db30f74f17a (patch)
tree27d33348bb9299b8460c0cebda9a8ed9031cdadd
parente6d52ecfa2379b1f7f3007e65ded5e4076abc5e9 (diff)
Add support for binary (base64 and hex) default/fixed values
-rw-r--r--tests/cxx/tree/default/general/output2
-rw-r--r--tests/cxx/tree/default/general/test.xsd6
-rw-r--r--xsd/cxx/tree/default-value.cxx293
-rw-r--r--xsd/cxx/tree/default-value.hxx44
-rw-r--r--xsd/cxx/tree/tree-source.cxx70
5 files changed, 364 insertions, 51 deletions
diff --git a/tests/cxx/tree/default/general/output b/tests/cxx/tree/default/general/output
index 89b4bb3..72a8fa4 100644
--- a/tests/cxx/tree/default/general/output
+++ b/tests/cxx/tree/default/general/output
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
-<t:root xmlns:t="test" bool1="true" bool2="true" bool3="false" bool4="false" byte="-99" decimal1="1.12345" decimal2="-0.456" double1="1.12345" double2="1123.45" double3="-0.00012345" double4="NaN" double5="-INF" fix1="123" fix2="123" fix3="abc" fix4="abc" fix5="aaa bbb ccc" fix6="aaa bbb ccc" float1="1.123" float2="1123" float3="-0.000123" float4="NaN" float5="-INF" id="this" idref="this" idrefs="this" int="-99999" integer="-99999" language="en-us" long="-99999" ncname="abcd" ninteger="-99999" nmtoken="ab:cd" nmtokens1="a:b efg aaa" nmtokens2="abc" nninteger="99999" npinteger="-99999" nstring=" a b " pinteger="99999" qname1="foo" qname2="t:bar" short="-999" string1="" string2=" a b " token="a b" ubyte="99" uint="99999" ulong="99999" uri="http://example.com" ushort="999">
+<t:root xmlns:t="test" base64_bin1="" base64_bin2="YmFzZTY0IGJpbmFyeQ==&#xA;" bool1="true" bool2="true" bool3="false" bool4="false" byte="-99" decimal1="1.12345" decimal2="-0.456" double1="1.12345" double2="1123.45" double3="-0.00012345" double4="NaN" double5="-INF" fix1="123" fix2="123" fix3="abc" fix4="abc" fix5="aaa bbb ccc" fix6="aaa bbb ccc" float1="1.123" float2="1123" float3="-0.000123" float4="NaN" float5="-INF" hex_bin1="" hex_bin2="6865782052696E617279" id="this" idref="this" idrefs="this" int="-99999" integer="-99999" language="en-us" long="-99999" ncname="abcd" ninteger="-99999" nmtoken="ab:cd" nmtokens1="a:b efg aaa" nmtokens2="abc" nninteger="99999" npinteger="-99999" nstring=" a b " pinteger="99999" qname1="foo" qname2="t:bar" short="-999" string1="" string2=" a b " token="a b" ubyte="99" uint="99999" ulong="99999" uri="http://example.com" ushort="999">
<union a="abc"/>
diff --git a/tests/cxx/tree/default/general/test.xsd b/tests/cxx/tree/default/general/test.xsd
index ef7feb0..9d9cd38 100644
--- a/tests/cxx/tree/default/general/test.xsd
+++ b/tests/cxx/tree/default/general/test.xsd
@@ -219,6 +219,12 @@
<xs:attribute name="qname1" type="xs:QName" default="foo"/>
<xs:attribute name="qname2" type="xs:QName" default="t:bar"/>
+ <xs:attribute name="base64_bin1" type="xs:base64Binary" default=""/>
+ <xs:attribute name="base64_bin2" type="xs:base64Binary" default="YmFzZTY0IGJpbmFyeQ=="/>
+
+ <xs:attribute name="hex_bin1" type="xs:hexBinary" default=""/>
+ <xs:attribute name="hex_bin2" type="xs:hexBinary" default="6865782052696E617279"/>
+
<!-- fixed -->
<xs:attribute name="fix1" type="xs:int" fixed="123"/>
diff --git a/xsd/cxx/tree/default-value.cxx b/xsd/cxx/tree/default-value.cxx
index 05679f7..35c5e49 100644
--- a/xsd/cxx/tree/default-value.cxx
+++ b/xsd/cxx/tree/default-value.cxx
@@ -5,6 +5,8 @@
#include <cxx/tree/default-value.hxx>
+using std::hex;
+
namespace CXX
{
namespace Tree
@@ -333,44 +335,56 @@ namespace CXX
}
//
- // InitValue
+ // InitKind
//
- IsSimpleInit::
- IsSimpleInit (Boolean& r)
+ InitKind::
+ InitKind (Kind& r)
: r_ (r)
{
*this >> inherits_ >> *this;
}
- Void IsSimpleInit::
+ Void InitKind::
traverse (SemanticGraph::List&)
{
- r_ = false;
+ r_ = function;
}
- Void IsSimpleInit::
+ Void InitKind::
traverse (SemanticGraph::Complex& c)
{
inherits (c);
}
- Void IsSimpleInit::
+ Void InitKind::
+ traverse (SemanticGraph::Fundamental::Base64Binary&)
+ {
+ r_ = data;
+ }
+
+ Void InitKind::
+ traverse (SemanticGraph::Fundamental::HexBinary&)
+ {
+ r_ = data;
+ }
+
+ Void InitKind::
traverse (SemanticGraph::Fundamental::NameTokens&)
{
- r_ = false;
+ r_ = function;
}
- Void IsSimpleInit::
+ Void InitKind::
traverse (SemanticGraph::Fundamental::IdRefs&)
{
- r_ = false;
+ r_ = function;
}
- Void IsSimpleInit::
+ Void InitKind::
traverse (SemanticGraph::Fundamental::Entities&)
{
- r_ = false;
+ r_ = function;
}
//
@@ -581,26 +595,263 @@ namespace CXX
// Binary.
//
+ static unsigned char
+ base64_decode (unsigned char c)
+ {
+ unsigned char r = 0xFF;
+
+ if (c >= 'A' && c <= 'Z')
+ r = static_cast<unsigned char> (c - 'A');
+ else if (c >= 'a' && c <= 'z')
+ r = static_cast<unsigned char> (c - 'a' + 26);
+ else if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (c - '0' + 52);
+ else if (c == '+')
+ r = 62;
+ else if (c == '/')
+ r = 63;
+
+ return r;
+ }
+
Void InitValue::
- traverse (SemanticGraph::Fundamental::Base64Binary&)
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
{
collapse (value_);
- if (value_)
- os << "#error base64Binary default values are not yet supported"
- << endl;
+ if (dispatch_count_++ == 0)
+ {
+ if (value_)
+ {
+ os << "unsigned char " << data_ << "[] = {";
+
+ // Decode.
+ //
+ Size size (value_.size ());
+
+ // Remove all whitespaces.
+ //
+ {
+ Size j (0);
+ Boolean subs (false);
+
+ for (Size i (0); i < size; ++i)
+ {
+ WideChar c (value_[i]);
+
+ if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09)
+ subs = true;
+ else
+ {
+ if (subs)
+ subs = false;
+
+ value_[j++] = c;
+ }
+ }
+
+ size = j;
+ value_.resize (size, '\0');
+ }
+
+ // Our length should be a multiple of four.
+ //
+ Size quad_count (size / 4);
+
+ // Source and destination indexes.
+ //
+ Size si (0), di (0);
+
+ // Process all quads except the last one.
+ //
+ unsigned short v;
+ unsigned char b1, b2, b3, b4;
+
+ WideChar prev_fill (os.fill ('0'));
+
+ for (Size q (0); q < quad_count - 1; ++q)
+ {
+ b1 = base64_decode (value_[si++]);
+ b2 = base64_decode (value_[si++]);
+ b3 = base64_decode (value_[si++]);
+ b4 = base64_decode (value_[si++]);
+
+ if (q != 0)
+ os << ", ";
+
+ if (di % 9 == 0)
+ os << endl;
+
+ v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4));
+ os.width (2);
+ os << "0x" << hex << v;
+
+ v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2));
+ os.width (2);
+ os << ", 0x" << hex << v;
+
+ v = static_cast<unsigned char> ((b3 << 6) | b4);
+ os.width (2);
+ os << ", 0x" << hex << v;
+
+ di += 3;
+ }
+
+ // Process the last quad. The first two octets are always there.
+ //
+ b1 = base64_decode (value_[si++]);
+ b2 = base64_decode (value_[si++]);
+
+ WideChar e3 (value_[si++]), e4 (value_[si++]);
+
+ if (quad_count != 1)
+ os << ", ";
+
+ if (di % 9 == 0)
+ os << endl;
+
+ if (e4 == '=')
+ {
+ if (e3 == '=')
+ {
+ // Two pads. Last 4 bits in b2 should be zero.
+ //
+ v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4));
+ os << "0x" << hex << v;
+ di++;
+ }
+ else
+ {
+ // One pad. Last 2 bits in b3 should be zero.
+ //
+ b3 = base64_decode (e3);
+
+ v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4));
+ os.width (2);
+ os << "0x" << hex << v;
+
+ v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2));
+ os.width (2);
+ os << ", 0x" << hex << v;
+
+ di += 2;
+ }
+ }
+ else
+ {
+ // No pads.
+ //
+ b3 = base64_decode (e3);
+ b4 = base64_decode (e4);
+
+ v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4));
+ os.width (2);
+ os << "0x" << hex << v;
+
+ v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2));
+ os.width (2);
+ os << ", 0x" << hex << v;
+
+ v = static_cast<unsigned char> ((b3 << 6) | b4);
+ os.width (2);
+ os << ", 0x" << hex << v;
+
+ di += 3;
+ }
+
+ os.fill (prev_fill);
+
+ os << "};";
+ }
+ }
+ else
+ {
+ os << fq_name (t) << " (";
+
+ if (value_)
+ os << data_ << "," << endl
+ << "sizeof (" << data_ << ")," << endl
+ << "sizeof (" << data_ << ")," << endl
+ << "false";
+ else
+ os << "0";
+
+
+ os << ")";
+ }
+ }
+
+ static unsigned char
+ hex_decode (unsigned char c)
+ {
+ unsigned char r = 0xFF;
+
+ if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ r = static_cast<unsigned char> (10 + (c - 'A'));
+ else if (c >= 'a' && c <= 'f')
+ r = static_cast<unsigned char> (10 + (c - 'a'));
+
+ return r;
}
Void InitValue::
- traverse (SemanticGraph::Fundamental::HexBinary&)
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
{
collapse (value_);
- if (value_)
- os << "#error hexBinary default values are not yet supported"
- << endl;
- }
+ if (dispatch_count_++ == 0)
+ {
+ if (value_)
+ {
+ os << "unsigned char " << data_ << "[] = {";
+
+ // Decode.
+ //
+ Size n (value_.size () / 2);
+ WideChar prev_fill (os.fill ('0'));
+ for (Size i (0); i < n; ++i)
+ {
+ unsigned char h (hex_decode (value_[2 * i]));
+ unsigned char l (hex_decode (value_[2 * i + 1]));
+
+ if (h == 0xFF || l == 0xFF)
+ break;
+
+ if (i != 0)
+ os << ", ";
+
+ if (i % 9 == 0)
+ os << endl;
+
+ unsigned short v = static_cast<unsigned char> ((h << 4) | l);
+ os.width (2);
+ os << "0x" << hex << v;
+ }
+
+ os.fill (prev_fill);
+
+ os << "};";
+ }
+ }
+ else
+ {
+ os << fq_name (t) << " (";
+
+ if (value_)
+ os << data_ << "," << endl
+ << "sizeof (" << data_ << ")," << endl
+ << "sizeof (" << data_ << ")," << endl
+ << "false";
+ else
+ os << "0";
+
+
+ os << ")";
+ }
+ }
// Date/time.
//
diff --git a/xsd/cxx/tree/default-value.hxx b/xsd/cxx/tree/default-value.hxx
index 7e9867a..c80132e 100644
--- a/xsd/cxx/tree/default-value.hxx
+++ b/xsd/cxx/tree/default-value.hxx
@@ -124,18 +124,29 @@ namespace CXX
Traversal::Inherits inherits_;
};
- // Some initialization (e.g., list) need a function body.
+ // Some initialization (e.g., list) need a function body while others
+ // (e.g., *binary) require extra data.
//
- struct IsSimpleInit: Traversal::List,
- Traversal::Complex,
+ struct InitKind: Traversal::List,
+ Traversal::Complex,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
- Traversal::Fundamental::NameTokens,
- Traversal::Fundamental::IdRefs,
- Traversal::Fundamental::Entities
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::IdRefs,
+ Traversal::Fundamental::Entities
{
- // Should be true initially.
+ enum Kind
+ {
+ simple,
+ data,
+ function
+ };
+
+ // Should be simple initially.
//
- IsSimpleInit (Boolean& r);
+ InitKind (Kind& r);
virtual Void
traverse (SemanticGraph::List&);
@@ -144,6 +155,12 @@ namespace CXX
traverse (SemanticGraph::Complex&);
virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary&);
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary&);
+
+ virtual Void
traverse (SemanticGraph::Fundamental::NameTokens&);
virtual Void
@@ -153,7 +170,7 @@ namespace CXX
traverse (SemanticGraph::Fundamental::Entities&);
private:
- Boolean& r_;
+ Kind& r_;
Traversal::Inherits inherits_;
};
@@ -201,6 +218,13 @@ namespace CXX
InitValue (Context&);
Void
+ data (String const& data)
+ {
+ data_ = data;
+ dispatch_count_ = 0;
+ }
+
+ Void
dispatch (SemanticGraph::Node& type, String const& value);
virtual Void
@@ -318,6 +342,8 @@ namespace CXX
private:
String value_;
+ String data_;
+ Size dispatch_count_;
MemberTypeName type_name_;
LiteralValue literal_value_;
};
diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx
index 4a94520..8c70f23 100644
--- a/xsd/cxx/tree/tree-source.cxx
+++ b/xsd/cxx/tree/tree-source.cxx
@@ -578,38 +578,68 @@ namespace CXX
if (!lit)
{
- Boolean simple_init (true);
+ InitKind::Kind kind (InitKind::simple);
{
- IsSimpleInit test (simple_init);
+ InitKind test (kind);
test.dispatch (t);
}
String const& member (edefault_value_member (m));
- String init_func;
- if (!simple_init)
- {
- init_func = escape (L"_xsd_" + scope_ + member + L"_init");
-
- os << "static " << scope_ << "::" << etype (m) << endl
- << init_func << " ()"
- << "{"
- << scope_ << "::" << etype (m) << " r;"
- << endl;
-
- init_value_.dispatch (t, m.value ());
+ String init_name;
- os << "return r;"
- << "};";
+ switch (kind)
+ {
+ case InitKind::data:
+ {
+ init_name = escape (L"_xsd_" + scope_ + member + L"data");
+ init_value_.data (init_name);
+ init_value_.dispatch (t, m.value ());
+ break;
+ }
+ case InitKind::function:
+ {
+ init_name = escape (L"_xsd_" + scope_ + member + L"init");
+
+ os << "static " << scope_ << "::" << etype (m) << endl
+ << init_name << " ()"
+ << "{"
+ << scope_ << "::" << etype (m) << " r;"
+ << endl;
+
+ init_value_.dispatch (t, m.value ());
+
+ os << "return r;"
+ << "};";
+ break;
+ }
+ case InitKind::simple:
+ break;
}
os << "const " << scope_ << "::" << etype (m) << " " <<
scope_ << "::" << member << " (" << endl;
- if (simple_init)
- init_value_.dispatch (t, m.value ());
- else
- os << init_func << " ()";
+ switch (kind)
+ {
+ case InitKind::data:
+ {
+ // Second dispatch.
+ //
+ init_value_.dispatch (t, m.value ());
+ break;
+ }
+ case InitKind::function:
+ {
+ os << init_name << " ()";
+ break;
+ }
+ case InitKind::simple:
+ {
+ init_value_.dispatch (t, m.value ());
+ break;
+ }
+ }
os << ");"
<< endl;