From d0743458695eb2bb764bc308a9496db30f74f17a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 Jan 2010 17:03:18 +0200 Subject: Add support for binary (base64 and hex) default/fixed values --- xsd/cxx/tree/default-value.cxx | 293 ++++++++++++++++++++++++++++++++++++++--- xsd/cxx/tree/default-value.hxx | 44 +++++-- xsd/cxx/tree/tree-source.cxx | 70 +++++++--- 3 files changed, 357 insertions(+), 50 deletions(-) (limited to 'xsd/cxx') 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 +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 (c - 'A'); + else if (c >= 'a' && c <= 'z') + r = static_cast (c - 'a' + 26); + else if (c >= '0' && c <= '9') + r = static_cast (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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << hex << v; + + v = static_cast ((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 ((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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast ((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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << hex << v; + + v = static_cast ((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 (c - '0'); + else if (c >= 'A' && c <= 'F') + r = static_cast (10 + (c - 'A')); + else if (c >= 'a' && c <= 'f') + r = static_cast (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 ((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; -- cgit v1.1