diff options
author | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff.email> | 2024-03-06 10:24:08 +0100 |
commit | aad5ad9bf0c02aa4e79bc6b7d6c934612fff4026 (patch) | |
tree | 9cc224b059f248a6229ab0dcdc64eb4a73fa9800 /xsd/cxx/tree | |
parent | c1034fc5e99197f507caf450aa15bc178698b26e (diff) |
New upstream version 4.2.0upstream/4.2.0upstream
Diffstat (limited to 'xsd/cxx/tree')
44 files changed, 28190 insertions, 0 deletions
diff --git a/xsd/cxx/tree/counter.cxx b/xsd/cxx/tree/counter.cxx new file mode 100644 index 0000000..3fee0b1 --- /dev/null +++ b/xsd/cxx/tree/counter.cxx @@ -0,0 +1,265 @@ +// file : xsd/cxx/tree/counter.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/counter.hxx> + +#include <iostream> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct Member: Traversal::Member + { + Member (size_t& complexity) + : complexity_ (complexity) + { + } + + virtual void + traverse (Type&) + { + complexity_++; + } + + size_t& complexity_; + }; + + struct Any: Traversal::Any, Traversal::AnyAttribute + { + Any (size_t& complexity) + : complexity_ (complexity) + { + } + + virtual void + traverse (SemanticGraph::Any&) + { + complexity_++; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + complexity_++; + } + + size_t& complexity_; + }; + + struct TypeBase: Traversal::List, + Traversal::Union, + Traversal::Enumeration, + Traversal::Complex, + Context + { + TypeBase (Context& c, size_t& complexity) + : Context (c), complexity_ (complexity) + { + } + + virtual void + traverse (SemanticGraph::List&) + { + complexity_++; + } + + virtual void + traverse (SemanticGraph::Union&) + { + complexity_++; + } + + virtual void + traverse (SemanticGraph::Enumeration& e) + { + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + complexity_ += (string_based ? 1 : 2); + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + complexity_++; // One for the type itself. + + // Plus some for each member. + // + Any any (complexity_); + Member member (complexity_); + Traversal::Names names; + + names >> member; + + if (options.generate_wildcard ()) + names >> any; + + Complex::names (c, names); + } + + private: + size_t& complexity_; + }; + + + // + // + struct GlobalType: Traversal::Type, Context + + { + GlobalType (Context& c, Counts& counts) + : Context (c), counts_ (counts) + { + } + + virtual void + traverse (SemanticGraph::Type& t) + { + counts_.global_types++; + + size_t complexity (0); + TypeBase type (*this, complexity); + type.dispatch (t); + + counts_.complexity_total += complexity; + counts_.complexity.push_back (complexity); + } + + private: + Counts& counts_; + }; + + // + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c, Counts& counts) + : GlobalElementBase (c), + Context (c), + counts_ (counts), + last_ (0) + { + } + + ~GlobalElement () + { + if (last_ != 0) + { + last_->context ().set ("last", true); + count_last (); + } + } + + virtual void + traverse (Type& e) + { + // Check if the previous element we saw needs to be generated. + // + if (last_ != 0) + count_last (); + + last_ = &e; + + if (counts_.global_elements == 0) + e.context ().set ("first", true); + + counts_.global_elements++; + } + + private: + void + count_last () + { + if (generate_p (*last_)) + { + counts_.generated_global_elements++; + + size_t complexity (0); + + if (doc_root_p (*last_)) + { + if (options.generate_element_type ()) + { + complexity += 1; // For c-tors and d-tor. + + if (!options.suppress_parsing ()) + complexity += 1; + + if (options.generate_serialization ()) + complexity += 1; + } + else + { + if (!options.suppress_parsing ()) + complexity += 6; // 13 parsing functions. + + if (options.generate_serialization ()) + complexity += 4; // 8 serialization functions. + } + } + + if (complexity == 0) + { + // This element must be a substitution group members. For + // such elements we are only generating an entry in a map. + // We will assign it a complexity of 1 so that we don't + // end up with the total complexity that is less than the + // number of elements and types. + // + complexity = 1; + } + + counts_.complexity_total += complexity; + counts_.complexity.push_back (complexity); + } + } + + private: + Counts& counts_; + SemanticGraph::Element* last_; + }; + } + + Counts Counter:: + count (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& path) + { + Counts counts; + Context ctx (std::wcerr, tu, path, ops, counts, false, 0, 0, 0, 0); + + Traversal::Schema schema; + Sources sources; + + schema >> sources >> schema; + + // The GlobalElement object destructor updates the counts, so make sure + // that this object is destroyed before we return the counts. + // + { + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalType global_type (ctx, counts); + GlobalElement global_element (ctx, counts); + + schema >> schema_names >> ns >> ns_names; + + ns_names >> global_element; + ns_names >> global_type; + + schema.dispatch (tu); + } + + return counts; + } + } +} diff --git a/xsd/cxx/tree/counter.hxx b/xsd/cxx/tree/counter.hxx new file mode 100644 index 0000000..bc1dc79 --- /dev/null +++ b/xsd/cxx/tree/counter.hxx @@ -0,0 +1,25 @@ +// file : xsd/cxx/tree/counter.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_COUNTER_HXX +#define XSD_CXX_TREE_COUNTER_HXX + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + class Counter + { + public: + Counts + count (options const&, + SemanticGraph::Schema&, + SemanticGraph::Path const&); + }; + } +} + +#endif // XSD_CXX_TREE_COUNTER_HXX diff --git a/xsd/cxx/tree/default-value.cxx b/xsd/cxx/tree/default-value.cxx new file mode 100644 index 0000000..fd1c8c4 --- /dev/null +++ b/xsd/cxx/tree/default-value.cxx @@ -0,0 +1,1273 @@ +// file : xsd/cxx/tree/default-value.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/default-value.hxx> + +using std::hex; +using std::dec; + +namespace CXX +{ + namespace Tree + { + namespace + { + void + normalize (String& s) + { + size_t n (s.size ()); + + for (size_t i (0); i < n; ++i) + { + wchar_t& c (s[i]); + + if (c == 0x0D || // carriage return + c == 0x09 || // tab + c == 0x0A) + c = 0x20; + } + } + + void + collapse (String& s) + { + size_t n (s.size ()), j (0); + bool subs (false), trim (true); + + for (size_t i (0); i < n; ++i) + { + wchar_t 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_t n (s.size ()), i (0); + + if (n > 0 && (s[i] == '-' || s[i] == '+')) + i++; + + size_t j (i); + + bool strip (true); + + for (; i < n; ++i) + { + wchar_t 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); + } + + void + make_float (String& s) + { + if (s.find ('.') == String::npos && + s.find ('e') == String::npos && + s.find ('E') == String::npos) + s += L".0"; + } + } + + // + // IsLiteralValue + // + + IsLiteralValue:: + IsLiteralValue (bool& r) + : IsFundamentalType (r) + { + *this >> inherits_ >> *this; + } + + void IsLiteralValue:: + traverse (SemanticGraph::Complex& c) + { + inherits (c); + } + + // + // LiteralValue + // + + LiteralValue:: + LiteralValue (Context& c) + : Context (c) + { + *this >> inherits_ >> *this; + } + + String LiteralValue:: + dispatch (SemanticGraph::Node& type, String const& value) + { + literal_.clear (); + value_ = value; + Traversal::NodeBase::dispatch (type); + return literal_; + } + + void LiteralValue:: + traverse (SemanticGraph::Complex& c) + { + inherits (c); + } + + // Boolean. + // + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Boolean&) + { + collapse (value_); + literal_ = (value_ == L"true" || value_ == L"1") ? L"true" : L"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_ + L"U"; + } + + 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_ + L"U"; + } + + 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_ + L"U"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Long&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + literal_ += L"LL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + literal_ += L"ULL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Integer&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"LL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"LL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"ULL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"ULL"; + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_ + L"LL"; + } + + // Floats. + // + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Float& t) + { + collapse (value_); + + if (value_ == L"NaN") + { + literal_ = L"::std::numeric_limits< " + fq_name (t) + + L" >::quiet_NaN ()"; + } + else if (value_ == L"INF") + { + literal_ = L"::std::numeric_limits< " + fq_name (t) + + L" >::infinity ()"; + } + else if (value_ == L"-INF") + { + literal_ = L"- ::std::numeric_limits< " + fq_name (t) + + L" >::infinity ()"; + } + else + { + strip_zeros (value_); + make_float (value_); + literal_ = value_ + L"F"; + } + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Double& t) + { + collapse (value_); + + if (value_ == L"NaN") + { + literal_ = L"::std::numeric_limits< " + fq_name (t) + + L" >::quiet_NaN ()"; + } + else if (value_ == L"INF") + { + literal_ = L"::std::numeric_limits< " + fq_name (t) + + L" >::infinity ()"; + } + else if (value_ == L"-INF") + { + literal_ = L"- ::std::numeric_limits< " + fq_name (t) + + L" >::infinity ()"; + } + else + { + strip_zeros (value_); + make_float (value_); + literal_ = value_; + } + } + + void LiteralValue:: + traverse (SemanticGraph::Fundamental::Decimal&) + { + collapse (value_); + strip_zeros (value_); + make_float (value_); + literal_ = value_; + } + + // + // InitKind + // + + InitKind:: + InitKind (Kind& r) + : r_ (r) + { + *this >> inherits_ >> *this; + } + + void InitKind:: + traverse (SemanticGraph::List&) + { + r_ = function; + } + + void InitKind:: + traverse (SemanticGraph::Complex& c) + { + inherits (c); + } + + void InitKind:: + traverse (SemanticGraph::Fundamental::Base64Binary&) + { + r_ = data; + } + + void InitKind:: + traverse (SemanticGraph::Fundamental::HexBinary&) + { + r_ = data; + } + + void InitKind:: + traverse (SemanticGraph::Fundamental::NameTokens&) + { + r_ = function; + } + + void InitKind:: + traverse (SemanticGraph::Fundamental::IdRefs&) + { + r_ = function; + } + + void InitKind:: + traverse (SemanticGraph::Fundamental::Entities&) + { + r_ = function; + } + + // + // InitValue + // + + InitValue:: + InitValue (Context& c) + : Context (c), type_name_ (c), literal_value_ (c) + { + } + + void InitValue:: + dispatch (SemanticGraph::Node& type, String const& value) + { + value_ = value; + Traversal::NodeBase::dispatch (type); + } + + void InitValue:: + traverse (SemanticGraph::List& l) + { + collapse (value_); + + if (!value_) + return; + + SemanticGraph::Type& t (l.argumented ().type ()); + + String ov (value_); + size_t b (0); + + for (size_t e (ov.find (' ')); ; e = ov.find (' ', b)) + { + String v (ov, b, e != String::npos ? e - b : e); + + os << "{"; + type_name_.dispatch (t); + os << " tmp ("; + + String lit (literal_value_.dispatch (t, v)); + + if (lit) + os << lit; + else + { + value_ = v; + Traversal::NodeBase::dispatch (t); + } + + os << ");" + << "r.push_back (tmp);" + << "}"; + + if (e == String::npos) + break; + + b = e + 1; + } + + value_ = ov; + } + + void InitValue:: + traverse (SemanticGraph::Union&) + { + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Complex& c) + { + Traversal::NodeBase::dispatch (ultimate_base (c)); + } + + // anyType & anySimpleType. + // + void InitValue:: + traverse (SemanticGraph::AnyType& t) + { + os << fq_name (t) << " (" << strlit (value_) << ")"; + } + + void InitValue:: + traverse (SemanticGraph::AnySimpleType& t) + { + os << fq_name (t) << " (" << strlit (value_) << ")"; + } + + // Strings. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::String&) + { + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + normalize (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Token&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::NameToken&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::NameTokens&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("NMTOKEN").first->named ())); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Name&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::NCName&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Language&) + { + collapse (value_); + os << strlit (value_); + } + + // Qualified name. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::QName& t) + { + size_t p (value_.rfind ('#')); + + if (p != String::npos) + { + String ns (value_, 0, p); + String qname (value_, p + 1, String::npos); + + collapse (ns); + collapse (qname); + + p = qname.find (':'); + + String name; + if (p != String::npos) + name.assign (qname, p + 1, String::npos); + else + name = qname; + + os << fq_name (t) << " (" << strlit (ns) << ", " << + strlit (name) << ")"; + } + else + { + // Unqualified name. + // + collapse (value_); + os << fq_name (t) << " (" << strlit (value_) << ")"; + } + } + + // ID/IDREF. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::Id&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::IdRef&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::IdRefs&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("IDREF").first->named ())); + } + + // URI. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::AnyURI&) + { + collapse (value_); + os << strlit (value_); + } + + // Binary. + // + static unsigned char + base64_decode (wchar_t 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& t) + { + collapse (value_); + + if (dispatch_count_++ == 0) + { + if (value_) + { + os << "unsigned char " << data_ << "[] = {"; + + // Decode. + // + size_t size (value_.size ()); + + // Remove all whitespaces. + // + { + size_t j (0); + bool subs (false); + + for (size_t i (0); i < size; ++i) + { + wchar_t 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_t quad_count (size / 4); + + // Source and destination indexes. + // + size_t si (0), di (0); + + // Process all quads except the last one. + // + unsigned short v; + unsigned char b1, b2, b3, b4; + + wchar_t prev_fill (os.fill ('0')); + + for (size_t 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; + + os << hex; + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << v; + + v = static_cast<unsigned char> ((b3 << 6) | b4); + os.width (2); + os << ", 0x" << v; + + os << dec; + + di += 3; + } + + // Process the last quad. The first two octets are always there. + // + b1 = base64_decode (value_[si++]); + b2 = base64_decode (value_[si++]); + + wchar_t 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 << dec; + di++; + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + os << hex; + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << v; + + os << dec; + + di += 2; + } + } + else + { + // No pads. + // + b3 = base64_decode (e3); + b4 = base64_decode (e4); + + os << hex; + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << v; + + v = static_cast<unsigned char> ((b3 << 6) | b4); + os.width (2); + os << ", 0x" << v; + + os << dec; + + 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 (wchar_t 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& t) + { + collapse (value_); + + if (dispatch_count_++ == 0) + { + if (value_) + { + os << "unsigned char " << data_ << "[] = {"; + + // Decode. + // + size_t n (value_.size () / 2); + wchar_t prev_fill (os.fill ('0')); + + for (size_t 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 << dec; + } + + 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. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::Date& t) + { + // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] + // + collapse (value_); + + size_t b (0); + size_t 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 << fq_name (t) << " (" << year << ", " << month << ", " << day; + time_zone (b + 2); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::DateTime& t) + { + // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM] + // + collapse (value_); + + size_t b (0); + size_t 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) + { + wchar_t 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); + make_float (seconds); + + os << fq_name (t) << " (" + << year << ", " << month << ", " << day << ", " + << hours << ", " << minutes << ", " << seconds; + time_zone (e); + os << ")"; + } + + namespace + { + size_t + find_delim (String const& s, size_t pos) + { + for (; pos < s.size (); ++pos) + { + wchar_t 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& t) + { + // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] + // + collapse (value_); + + size_t b (1), e, n (value_.size ()); + + os << fq_name (t) << " ("; + + if (value_[0] == '-') + { + os << "true, "; + b++; + } + else + os << "false, "; + + e = find_delim (value_, b); + + if (e < n && value_[e] == 'Y') + { + String v (value_, b, e - b); + strip_zeros (v); + os << v << ", "; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0, "; + + if (e < n && value_[e] == 'M') + { + String v (value_, b, e - b); + strip_zeros (v); + os << v << ", "; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0, "; + + if (e < n && value_[e] == 'D') + { + String v (value_, b, e - b); + strip_zeros (v); + os << v << ", "; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0, "; + + 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 << v << ", "; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0, "; + + if (e < n && value_[e] == 'M') + { + String v (value_, b, e - b); + strip_zeros (v); + os << v << ", "; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0, "; + + if (e < n && value_[e] == 'S') + { + String v (value_, b, e - b); + strip_zeros (v); + make_float (v); + os << v; + + b = e + 1; + e = find_delim (value_, b); + } + else + os << "0.0"; + + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Day& t) + { + // gday := ---DD[Z|(+|-)HH:MM] + // + collapse (value_); + + String day (value_, 3, 2); + strip_zeros (day); + + os << fq_name (t) << " (" << day; + time_zone (5); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Month& t) + { + // gmonth := --MM[Z|(+|-)HH:MM] + // + collapse (value_); + + String month (value_, 2, 2); + strip_zeros (month); + + os << fq_name (t) << " (" << month; + time_zone (4); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + // 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 << fq_name (t) << " (" << month << ", " << day; + time_zone (7); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Year& t) + { + // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM] + // + collapse (value_); + + size_t pos (value_[0] == '-' ? 5 : 4); + for (; pos < value_.size (); ++pos) + { + wchar_t c (value_[pos]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String year (value_, 0, pos); + strip_zeros (year); + + os << fq_name (t) << " (" << year; + time_zone (pos); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM] + // + collapse (value_); + + size_t 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 << fq_name (t) << " (" << year << ", " << month; + time_zone (pos + 3); + os << ")"; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Time& t) + { + // time := HH:MM:SS[.S+][Z|(+|-)HH:MM] + // + collapse (value_); + + String hours (value_, 0, 2); + String minutes (value_, 3, 2); + + size_t e (8); + for (; e < value_.size (); ++e) + { + wchar_t c (value_[e]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String seconds (value_, 6, e - 6); + + strip_zeros (hours); + strip_zeros (minutes); + strip_zeros (seconds); + make_float (seconds); + + os << fq_name (t) << " (" << hours << ", " << minutes << ", " << seconds; + time_zone (e); + os << ")"; + } + + void InitValue:: + time_zone (size_t 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 << ", " << h << ", " << m; + } + } + + // Entity. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::Entity&) + { + collapse (value_); + os << strlit (value_); + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Entities&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("ENTITY").first->named ())); + } + + void InitValue:: + string_sequence_type (SemanticGraph::Type& t) + { + collapse (value_); + + if (!value_) + return; + + size_t b (0); + + for (size_t e (value_.find (' ')); ; e = value_.find (' ', b)) + { + String v (value_, b, e != String::npos ? e - b : e); + + os << "{"; + type_name_.dispatch (t); + os << " tmp (" << strlit (v) << ");" + << "r.push_back (tmp);" + << "}"; + + if (e == String::npos) + break; + + b = e + 1; + } + } + } +} diff --git a/xsd/cxx/tree/default-value.hxx b/xsd/cxx/tree/default-value.hxx new file mode 100644 index 0000000..149982f --- /dev/null +++ b/xsd/cxx/tree/default-value.hxx @@ -0,0 +1,363 @@ +// file : xsd/cxx/tree/default-value.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_DEFAULT_VALUE_HXX +#define XSD_CXX_TREE_DEFAULT_VALUE_HXX + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + struct IsLiteralValue: IsFundamentalType, Traversal::Complex + { + using IsFundamentalType::traverse; + + IsLiteralValue (bool& r); + + virtual void + traverse (SemanticGraph::Complex&); + + private: + Traversal::Inherits inherits_; + }; + + 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::Complex, + + Context + { + using Traversal::NodeDispatcher::dispatch; + using Traversal::EdgeDispatcher::dispatch; + + LiteralValue (Context&); + + String + dispatch (SemanticGraph::Node& type, String const& value); + + // Handle inheritance. + // + virtual void + traverse (SemanticGraph::Complex&); + + // 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&); + + private: + String value_; + String literal_; + + Traversal::Inherits inherits_; + }; + + // Some initialization (e.g., list) need a function body while others + // (e.g., *binary) require extra data. + // + struct InitKind: Traversal::List, + Traversal::Complex, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::IdRefs, + Traversal::Fundamental::Entities + { + enum Kind + { + simple, + data, + function + }; + + // Should be simple initially. + // + InitKind (Kind& r); + + virtual void + traverse (SemanticGraph::List&); + + virtual void + traverse (SemanticGraph::Complex&); + + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary&); + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary&); + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens&); + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs&); + + virtual void + traverse (SemanticGraph::Fundamental::Entities&); + + private: + Kind& r_; + Traversal::Inherits inherits_; + }; + + struct InitValue: Traversal::List, + Traversal::Union, + Traversal::Complex, + + Traversal::AnyType, + 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 + { + using Traversal::NodeDispatcher::dispatch; + using Traversal::EdgeDispatcher::dispatch; + + InitValue (Context&); + + void + data (String const& data) + { + data_ = data; + dispatch_count_ = 0; + } + + void + dispatch (SemanticGraph::Node& type, String const& value); + + virtual void + traverse (SemanticGraph::List&); + + virtual void + traverse (SemanticGraph::Union&); + + virtual void + traverse (SemanticGraph::Complex&); + + // anyType & anySimpleType. + // + virtual void + traverse (SemanticGraph::AnyType&); + + 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_sequence_type (SemanticGraph::Type& element_type); + + void + time_zone (size_t pos); + + private: + String value_; + String data_; + size_t dispatch_count_; + MemberTypeName type_name_; + LiteralValue literal_value_; + }; + } +} + +#endif // XSD_CXX_TREE_DEFAULT_VALUE_HXX diff --git a/xsd/cxx/tree/elements.cxx b/xsd/cxx/tree/elements.cxx new file mode 100644 index 0000000..fc080c8 --- /dev/null +++ b/xsd/cxx/tree/elements.cxx @@ -0,0 +1,1409 @@ +// file : xsd/cxx/tree/elements.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + // Context + // + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + options_type const& ops, + Counts const& counts_, + bool generate_xml_schema__, + StringLiteralMap const* map, + Regex const* fe, + Regex const* he, + Regex const* ie) + : CXX::Context (o, root, path, ops, map), + options (ops), + counts (counts_), + any_type (any_type_), + any_simple_type (any_simple_type_), + element_type (element_type_), + container (container_), + flags_type (flags_type_), + qname_type (qname_type_), + xs_string_type (xs_string_type_), + properties_type (properties_type_), + error_handler_type (error_handler_type_), + list_stream_type (list_stream_type_), + namespace_infomap_type (namespace_infomap_type_), + parser_type (parser_type_), + std_ostream_type (std_ostream_type_), + ostream_type (ostream_type_), + istream_type (istream_type_), + xerces_ns (xerces_ns_), + dom_auto_ptr (dom_auto_ptr_), + dom_node_key (dom_node_key_), + as_double_type (as_double_type_), + as_decimal_type (as_decimal_type_), + generate_xml_schema (generate_xml_schema_), + doxygen (doxygen_), + polymorphic (ops.generate_polymorphic ()), + polymorphic_all (ops.polymorphic_type_all ()), + poly_plate (ops.polymorphic_plate ()), + detach (ops.generate_detach ()), + fwd_expr (fe), + hxx_expr (he), + ixx_expr (ie), + ns_scope (ns_scope_), + regex_custom_type_map (regex_custom_type_map_), + direct_custom_type_map (direct_custom_type_map_), + qname_type_ (L"::xsd::cxx::xml::qualified_name< " + char_type + L" >"), + parser_type_ (L"::xsd::cxx::xml::dom::parser< " + char_type + L" >"), + generate_xml_schema_ (generate_xml_schema__), + doxygen_ (ops.generate_doxygen ()), + ns_scope_stack (ns_scope_stack_), + cxx_uq_id_expr_ (L"^[a-zA-Z_]\\w*$"), + cxx_uq_id_expr (cxx_uq_id_expr_) + { + SemanticGraph::Namespace& xs (xs_ns ()); + SemanticGraph::Context& xsc (xs.context ()); + + // Cache some often-used names from the XML Schema namespace + // if names have already been processed. + // + if (xsc.count ("container")) + { + String xs_name (ns_name (xs)); + + any_type = fq_name (xs.find ("anyType").first->named ()); + any_simple_type = fq_name (xs.find ("anySimpleType").first->named ()); + xs_string_type = fq_name (xs.find ("string").first->named ()); + + container = xs_name + L"::" + xsc.get<String> ("container"); + flags_type = xs_name + L"::" + xsc.get<String> ("flags"); + + if (ops.generate_element_type ()) + element_type = xs_name + L"::" + xsc.get<String> ("element-type"); + + properties_type = xs_name + L"::" + xsc.get<String> ("properties"); + + if (!ops.suppress_parsing () || ops.generate_serialization ()) + { + error_handler_type = xs_name + L"::" + + xsc.get<String> ("error-handler"); + } + + dom_auto_ptr_ = xs_name + (std >= cxx_version::cxx11 + ? L"::dom::unique_ptr" + : L"::dom::auto_ptr"); + + dom_node_key_ = xs_name + L"::dom::" + + xsc.get<String> ("tree-node-key"); + + if (ops.generate_serialization ()) + { + as_double_type_ = xs_name + L"::" + + xsc.get<String> ("as-double"); + + as_decimal_type_ = xs_name + L"::" + + xsc.get<String> ("as-decimal"); + + list_stream_type = xs_name + L"::" + + xsc.get<String> ("list-stream"); + + namespace_infomap_type = xs_name + L"::" + + xsc.get<String> ("namespace-infomap"); + } + + // istream and ostream are templates and for now use the same + // names regardless of the naming convention. + // + if (!ops.generate_extraction ().empty ()) + istream_type = xs_name + L"::istream"; + + if (!ops.generate_insertion ().empty ()) + ostream_type = xs_name + L"::ostream"; + } + + // Xerces-C++ namespace. IntelliSense for some reason does not like + // it fully-qualified (maybe because it's a namespace alias). + // + if (ops.generate_intellisense ()) + xerces_ns = "xercesc"; + else + xerces_ns = "::xercesc"; + + // + // + if (char_type == L"char") + std_ostream_type_ = L"::std::ostream"; + else if (char_type == L"wchar_t") + std_ostream_type_ = L"::std::wostream"; + else + std_ostream_type_ = L"::std::basic_ostream< " + char_type + L" >"; + + // Custom type mapping. + // + + // Direct custom type mapping. + // + { + NarrowStrings const& v (ops.custom_type ()); + + for (NarrowStrings::const_iterator i (v.begin ()), + e (v.end ()); i != e; ++i) + { + String s (*i); + + if (s.empty ()) + throw InvalidCustomTypeMapping (s, "mapping string is empty"); + + // Split the string in two parts at the last '='. + // + size_t pos (s.rfind ('=')); + + // If no delimiter found then both type and base are empty. + // + if (pos == String::npos) + { + direct_custom_type_map[s].type.clear (); + direct_custom_type_map[s].base.clear (); + continue; + } + + String name (s, 0, pos); + String rest (s, pos + 1); + + // See if we've got the base part after '/'. + // + pos = rest.rfind ('/'); + + String type, base; + + if (pos != String::npos) + { + type.assign (rest, 0, pos); + base.assign (rest, pos + 1, String::npos); + } + else + type = rest; + + // type can be a potentially-qualified template-id. base is + // an unqualified C++ name. + // + + if (!base.empty () && !cxx_uq_id_expr.match (base)) + throw InvalidCustomTypeMapping (s, "invalid C++ identifier"); + + direct_custom_type_map[name].type = type; + direct_custom_type_map[name].base = base; + } + } + + // Regex custom type mapping. + // + { + NarrowStrings const& v (ops.custom_type_regex ()); + + for (NarrowStrings::const_iterator i (v.begin ()), + e (v.end ()); i != e; ++i) + { + String s (*i); + + if (s.empty ()) + throw InvalidCustomTypeMapping (s, "mapping string is empty"); + + wchar_t delimiter (s[0]); + + // First get pattern. + // + size_t pos (s.find (delimiter, 1)); + + if (pos == String::npos) + throw InvalidCustomTypeMapping ( + s, "missing pattern-substitution separator"); + + String pat (s, 1, pos - 1); + String rest (s, pos + 1); + + String type, base; + + // See if we've got type and base. + // + if (!rest.empty ()) + { + pos = rest.find (delimiter); + + if (pos == String::npos) + throw InvalidCustomTypeMapping ( + s, "missing pattern-substitution separator"); + + type.assign (rest, 0, pos); + rest = String (rest, pos + 1); + + if (!rest.empty ()) + { + pos = rest.find (delimiter); + + if (pos == String::npos) + throw InvalidCustomTypeMapping ( + s, "missing pattern-substitution separator"); + + base.assign (rest, 0, pos); + rest = String (rest, pos + 1); + + if (!rest.empty ()) + throw InvalidCustomTypeMapping (s, "invalid format"); + } + } + + regex_custom_type_map.push_back ( + RegexCustomTypeMapInfo (WideRegexPat (pat), type, base)); + } + } + } + + Context:: + Context (Context& c) + : CXX::Context (c), + options (c.options), + counts (c.counts), + any_type (c.any_type), + any_simple_type (c.any_simple_type), + element_type (c.element_type), + container (c.container), + flags_type (c.flags_type), + qname_type (c.qname_type), + xs_string_type (c.xs_string_type), + properties_type (c.properties_type), + error_handler_type (c.error_handler_type), + list_stream_type (c.list_stream_type), + namespace_infomap_type (c.namespace_infomap_type), + parser_type (c.parser_type), + std_ostream_type (c.std_ostream_type), + ostream_type (c.ostream_type), + istream_type (c.istream_type), + xerces_ns (c.xerces_ns), + dom_auto_ptr (c.dom_auto_ptr), + dom_node_key (c.dom_node_key), + as_double_type (c.as_double_type), + as_decimal_type (c.as_decimal_type), + generate_xml_schema (c.generate_xml_schema), + doxygen (c.doxygen), + polymorphic (c.polymorphic), + polymorphic_all (c.polymorphic_all), + poly_plate (c.poly_plate), + detach (c.detach), + fwd_expr (c.fwd_expr), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + ns_scope (c.ns_scope), + regex_custom_type_map (c.regex_custom_type_map), + direct_custom_type_map (c.direct_custom_type_map), + ns_scope_stack (c.ns_scope_stack), + cxx_uq_id_expr (c.cxx_uq_id_expr) + { + } + + Context:: + Context (Context& c, std::wostream& o) + : CXX::Context (c, o), + options (c.options), + counts (c.counts), + any_type (c.any_type), + any_simple_type (c.any_simple_type), + element_type (c.element_type), + container (c.container), + flags_type (c.flags_type), + qname_type (c.qname_type), + xs_string_type (c.xs_string_type), + properties_type (c.properties_type), + error_handler_type (c.error_handler_type), + list_stream_type (c.list_stream_type), + namespace_infomap_type (c.namespace_infomap_type), + parser_type (c.parser_type), + std_ostream_type (c.std_ostream_type), + ostream_type (c.ostream_type), + istream_type (c.istream_type), + xerces_ns (c.xerces_ns), + dom_auto_ptr (c.dom_auto_ptr), + dom_node_key (c.dom_node_key), + as_double_type (c.as_double_type), + as_decimal_type (c.as_decimal_type), + generate_xml_schema (c.generate_xml_schema), + doxygen (c.doxygen), + polymorphic (c.polymorphic), + polymorphic_all (c.polymorphic_all), + poly_plate (c.poly_plate), + detach (c.detach), + fwd_expr (c.fwd_expr), + hxx_expr (c.hxx_expr), + ixx_expr (c.ixx_expr), + ns_scope (c.ns_scope), + regex_custom_type_map (c.regex_custom_type_map), + direct_custom_type_map (c.direct_custom_type_map), + ns_scope_stack (c.ns_scope_stack), + cxx_uq_id_expr (c.cxx_uq_id_expr) + { + } + + void Context:: + update_ns_scope () + { + ns_scope.clear (); + + bool first (true); + + for (NamespaceStack::iterator i (ns_scope_stack.begin ()); + i != ns_scope_stack.end (); + ++i) + { + // We only qualify names until the namespace level. + // + if (first) + first = false; + else + ns_scope += L"::"; + + ns_scope += *i; + } + } + + bool Context:: + custom_type (SemanticGraph::Type const& t, String& r) const + { + String const& name (t.name ()); + + // First search the direct mapping. + // + { + DirectCustomTypeMap::const_iterator i ( + direct_custom_type_map.find (name)); + + if (i != direct_custom_type_map.end ()) + { + r = i->second.type; + return true; + } + } + + + // Second search the regex mapping. + // + for (RegexCustomTypeMap::const_iterator + i (regex_custom_type_map.begin ()), + e (regex_custom_type_map.end ()); + i != e; ++i) + { + if (i->pat.match (name)) + { + // Empty type sub tells us to use the original name. + // + if (i->type_sub.empty ()) + { + r.clear (); + return true; + } + + r = i->pat.replace (name, i->type_sub); + return true; + } + } + + return false; + } + + String Context:: + custom_type (SemanticGraph::Type const& t) const + { + String r; + if (custom_type (t, r)) + { + // Empty type name tells us to use the original name. + // + if (r.empty ()) + r = ename (t); + } + + return r; + } + + bool Context:: + renamed_type (SemanticGraph::Type const& t, String& r) const + { + String const& name (t.name ()); + + // First search the direct mapping. + // + { + DirectCustomTypeMap::const_iterator i ( + direct_custom_type_map.find (name)); + + if (i != direct_custom_type_map.end ()) + { + r = i->second.base; + return true; + } + } + + + // Second search the regex mapping. + // + for (RegexCustomTypeMap::const_iterator + i (regex_custom_type_map.begin ()), + e (regex_custom_type_map.end ()); + i != e; ++i) + { + if (i->pat.match (name)) + { + if (!i->base_sub.empty ()) + { + r = i->pat.replace (name, i->base_sub); + } + else + r.clear (); + + return true; + } + } + + return false; + } + + void Context:: + write_annotation (SemanticGraph::Annotation& a) + { + String const& doc (a.documentation ()); + wchar_t const* s (doc.c_str ()); + size_t size (doc.size ()); + + // Remove leading and trailing whitespaces. + // + while (*s == wchar_t (0x20) || *s == wchar_t (0x0A) || + *s == wchar_t (0x0D) || *s == wchar_t (0x09)) + { + s++; + size--; + } + + if (size != 0) + { + wchar_t const* e (s + size - 1); + + while (e > s && + (*e == wchar_t (0x20) || *e == wchar_t (0x0A) || + *e == wchar_t (0x0D) || *e == wchar_t (0x09))) + --e; + + size = s <= e ? e - s + 1 : 0; + } + + if (size != 0) + { + os << " * "; + + // Go over the data, forcing newline after 80 chars and adding + // ' * ' after each new line. + // + wchar_t const* last_space (0); + wchar_t const* b (s); + wchar_t const* e (s); + bool after_newline (false); + bool rogue (false); + + for (; e < s + size; ++e) + { + unsigned int u (unicode_char (e)); // May advance e. + + // We are going to treat \v and \f as rogue here even though + // they can be present in C++ source code. + // + if (u > 127 || (u < 32 && u != '\t' && u != '\n')) + rogue = true; + + if (u == ' ' || u == '\t') + { + if (after_newline) + { + if (e == b) + b++; // Skip leading spaces after newline. + + continue; + } + else + last_space = e; + } + else if (after_newline) + { + os << " * "; + after_newline = false; + } + + if (u == '\n') + { + write_rogue_text (b, e - b + 1, rogue); + + b = e + 1; + last_space = 0; + after_newline = true; + rogue = false; + continue; + } + + if (e - b >= 70 && last_space != 0) + { + write_rogue_text (b, last_space - b, rogue); + os << endl; + + b = last_space + 1; + last_space = 0; + after_newline = true; + // Cannot reset rogue since we don't output the whole string. + } + } + + if (e != b) + write_rogue_text (b, e - b, rogue); + + if (!after_newline) + os << endl; + } + } + + void Context:: + write_rogue_text (wchar_t const* s, size_t size, bool rogue) + { + if (!rogue) + os.write (s, size); + else + { + for (wchar_t const* p (s); p < s + size; ++p) + { + unsigned int u (unicode_char (p)); // May advance p. + + // We are going to treat \v and \f as rogue here even though + // they can be present in C++ source code. + // + if (u > 127 || (u < 32 && u != '\t' && u != '\n')) + os.put ('?'); + else + os.put (static_cast<wchar_t> (u)); + } + } + } + + bool Context:: + polymorphic_p (SemanticGraph::Type& t) + { + // IDREF templates cannot be polymorphic. + // + if (!t.named_p () && + (t.is_a<SemanticGraph::Fundamental::IdRef> () || + t.is_a<SemanticGraph::Fundamental::IdRefs> ())) + return false; + + if (polymorphic_all) + { + bool fund (false); + IsFundamentalType test (fund); + test.dispatch (t); + return !fund; + } + else + return t.context ().get<bool> ("polymorphic"); + } + + bool Context:: + anonymous_substitutes_p (SemanticGraph::Type& t) + { + // IDREF templates cannot match. + // + if (!t.named_p () && + (t.is_a<SemanticGraph::Fundamental::IdRef> () || + t.is_a<SemanticGraph::Fundamental::IdRefs> ())) + return false; + + // See which elements this type classifies. + // + for (SemanticGraph::Type::ClassifiesIterator i (t.classifies_begin ()), + e (t.classifies_end ()); i != e; ++i) + { + if (SemanticGraph::Element* e = + dynamic_cast<SemanticGraph::Element*> (&i->instance ())) + { + if (e->substitutes_p ()) + return true; + } + } + + return false; + } + + // GenerateDefautCtor + // + GenerateDefaultCtor:: + GenerateDefaultCtor (Context& c, bool& generate, bool no_base) + : Context (c), generate_ (generate), no_base_ (no_base) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Complex& c) + { + // Make sure we figure out if we have any required members before + // we base our decision on the base type. + // + Complex::names (c, names_); + + if (!generate_) + Complex::inherits (c, inherits_); + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Type&) + { + if (!no_base_) + generate_ = true; + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Enumeration&) + { + if (!no_base_) + generate_ = true; + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + generate_ = true; + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Attribute& a) + { + if (min (a) == 1 && !a.fixed_p ()) + generate_ = true; + } + + void GenerateDefaultCtor:: + traverse (SemanticGraph::Any& a) + { + if (options.generate_wildcard () && + min (a) == 1 && max (a) == 1) + generate_ = true; + } + + + // GenerateFromBaseCtor + // + GenerateFromBaseCtor:: + GenerateFromBaseCtor (Context& c, bool& generate) + : generate_ (generate), + custom_ (false), + traverser_ (c, generate, custom_) + { + inherits_ >> traverser_; + } + + void GenerateFromBaseCtor:: + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!generate_ && custom_) + { + // We have a customized type in the hierarchy. In this case we + // want to generate the c-tor unless base and ultimate-base are + // the same (see CtorArgs). + // + SemanticGraph::Type& b (c.inherits ().base ()); + generate_ = b.is_a<SemanticGraph::Complex> () && + !b.is_a<SemanticGraph::Enumeration> (); + } + } + + GenerateFromBaseCtor::Traverser:: + Traverser (Context& c, bool& generate, bool& custom) + : Context (c), generate_ (generate), custom_ (custom) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Type& t) + { + if (!custom_) + { + String tmp; + custom_ = custom_type (t, tmp); + } + } + + void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Complex& c) + { + names (c, names_); + + if (!generate_) + inherits (c, inherits_); + + if (!generate_) + traverse (static_cast<SemanticGraph::Type&> (c)); + } + + void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + generate_ = true; + } + + void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Attribute& a) + { + if (min (a) == 1 && !a.fixed_p ()) + generate_ = true; + } + + void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Any& a) + { + if (options.generate_wildcard () && + min (a) == 1 && max (a) == 1) + generate_ = true; + } + + // HasComplexNonOptArgs + // + HasComplexPolyNonOptArgs:: + HasComplexPolyNonOptArgs (Context& c, + bool base, + bool& complex, + bool& poly, + bool& clash) + : Context (c), + complex_ (complex), + poly_ (poly), + clash_ (clash) + { + if (base) + *this >> inherits_ >> *this; + + *this >> names_ >> *this; + } + + void HasComplexPolyNonOptArgs:: + traverse (SemanticGraph::Complex& c) + { + // No optimizations: need to check every arg for clashes. + // + inherits (c, inherits_); + names (c, names_); + } + + void HasComplexPolyNonOptArgs:: + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + { + bool poly (polymorphic && polymorphic_p (e.type ())); + + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + + if (poly) + poly_ = true; + + if (!simple) + complex_ = true; + + if (poly && simple) + clash_ = false; + } + } + + // FromBaseCtorArg + // + FromBaseCtorArg:: + FromBaseCtorArg (Context& c, CtorArgType at, bool arg) + : Context (c), arg_type_ (at), arg_ (arg) + { + } + + void FromBaseCtorArg:: + traverse (SemanticGraph::Any& a) + { + if (!options.generate_wildcard ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + String const& name (ename (a)); + + os << "," << endl + << "const " << xerces_ns << "::DOMElement&"; + + if (arg_) + os << " " << name; + } + } + + void FromBaseCtorArg:: + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + if (min (e) == 1 && max (e) == 1) + { + String const& name (ename (e)); + + os << "," << endl; + + bool ptr (false); + + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + ptr = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + + if (ptr) + os << auto_ptr << "< " << etype (e) << " >"; + else + os << "const " << etype (e) << "&"; + + if (arg_) + os << " " << name; + } + } + + void FromBaseCtorArg:: + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not going to include attributes with + // default or required fixed values here. Instead we are + // going to default-initialize them. + // + if (min (a) == 1 && !a.fixed_p ()) + { + String const& name (ename (a)); + + os << "," << endl + << "const " << etype (a) << "&"; + + if (arg_) + os << " " << name; + } + } + + // CtorArgs + // + CtorArgs:: + CtorArgs (Context& c, CtorArgType at) + : Context (c), + arg_type_ (at), + base_arg_ (0), + first_ (true), + member_name_ (c) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + CtorArgs:: + CtorArgs (Context& c, CtorArgType at, String& base_arg) + : Context (c), + arg_type_ (at), + base_arg_ (&base_arg), + first_ (true), + member_name_ (c) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + void CtorArgs:: + traverse (SemanticGraph::Type& t) + { + os << comma () << "const "; + + member_name_.dispatch (t); + + os << "&"; + + if (base_arg_ != 0) + { + // IDREF templates don't have a name. + // + *base_arg_ = t.named_p () + ? (L"_xsd_" + ename (t) + L"_base") + : L"_xsd_base"; + + os << " " << *base_arg_; + } + } + + void CtorArgs:: + traverse (SemanticGraph::Enumeration& e) + { + os << comma () << "const "; + + member_name_.traverse (e); + + os << "&"; + + if (base_arg_ != 0) + { + *base_arg_ = L"_xsd_" + ename (e) + L"_base"; + + os << " " << *base_arg_; + } + } + + void CtorArgs:: + traverse (SemanticGraph::Any& a) + { + if (!options.generate_wildcard ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + os << comma () << "const " << xerces_ns << "::DOMElement&"; + + if (base_arg_ != 0) + os << " " << ename (a); + } + } + + void CtorArgs:: + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + if (min (e) == 1 && max (e) == 1) + { + bool ptr (false); + + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + ptr = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + + if (ptr) + os << comma () << auto_ptr << "< " << etype (e) << " >"; + else + os << comma () << "const " << etype (e) << "&"; + + if (base_arg_ != 0) + os << " " << ename (e); + } + } + + void CtorArgs:: + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not going to include attributes with + // default or required fixed values here. Instead we are + // going to default-initialize them. + // + if (min (a) == 1 && !a.fixed_p ()) + { + os << comma () << "const " << etype (a) << "&"; + + if (base_arg_ != 0) + os << " " << ename (a); + } + } + + String CtorArgs:: + comma () + { + bool tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + + // CtorArgsWithoutBase + // + CtorArgsWithoutBase:: + CtorArgsWithoutBase (Context& c, CtorArgType at, bool arg, bool first) + : Context (c), arg_type_ (at), arg_ (arg), first_ (first) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + void CtorArgsWithoutBase:: + traverse (SemanticGraph::Any& a) + { + if (!options.generate_wildcard ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + os << comma () << "const " << xerces_ns << "::DOMElement&"; + + if (arg_) + os << " " << ename (a); + } + } + + void CtorArgsWithoutBase:: + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + if (min (e) == 1 && max (e) == 1) + { + bool ptr (false); + + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + ptr = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + + if (ptr) + os << comma () << auto_ptr << "< " << etype (e) << " >"; + else + os << comma () << "const " << etype (e) << "&"; + + if (arg_) + os << " " << ename (e); + } + } + + void CtorArgsWithoutBase:: + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not going to include attributes with + // default or required fixed values here. Instead we are + // going to default-initialize them. + // + if (min (a) == 1 && !a.fixed_p ()) + { + os << comma () << "const " << etype (a) << "&"; + + if (arg_) + os << " " << ename (a); + } + } + + String CtorArgsWithoutBase:: + comma () + { + bool tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + // GlobalElementBase + // + bool GlobalElementBase:: + generate_p (SemanticGraph::Element& e) + { + if (e.substitutes_p () && ctx_.polymorphic) + return true; + + if (!doc_root_p (e)) + return false; + + // If we are not generating element types nor parsing/serialization + // code then we won't generate anything from it. + // + if (!ctx_.options.generate_element_type () && + ctx_.options.suppress_parsing () && + !ctx_.options.generate_serialization ()) + return false; + + return true; + } + + bool GlobalElementBase:: + doc_root_p (SemanticGraph::Element& e) + { + if (!ctx_.options.root_element_first () && + !ctx_.options.root_element_last () && + !ctx_.options.root_element_all () && + !ctx_.options.root_element_none () && + ctx_.options.root_element ().empty ()) + return true; // By default treat them all. + + if (ctx_.options.root_element_none ()) + return false; + + if (ctx_.options.root_element_all ()) + return true; + + if (ctx_.options.root_element_first () && + e.context ().count ("first") != 0) + return true; + + if (ctx_.options.root_element_last () && + e.context ().count ("last") != 0) + return true; + + NarrowStrings const& names (ctx_.options.root_element ()); + + // Hopefully nobody will specify more than a handful of names ;-). + // + for (NarrowStrings::const_iterator i (names.begin ()); + i != names.end (); ++i) + { + String name (*i); + + if (e.name () == name) + return true; + } + + return false; + } + + // Namespace + // + Namespace:: + Namespace (Context& c, + size_t first, + size_t last) + : CXX::Namespace (c, *this), + GlobalElementBase (c), + ctx_ (c), + first_ (first), + last_ (last), + count_ (0) + { + } + + void Namespace:: + traverse (Type& ns) + { + using SemanticGraph::Element; + + if (first_ > last_) + CXX::Namespace::traverse (ns); + else + { + bool opened (false); + + for (Type::NamesIterator i (ns.names_begin ()); + i != ns.names_end (); ++i) + { + SemanticGraph::Nameable& n (i->named ()); + + if (n.is_a<SemanticGraph::Type> () || + (n.is_a<Element> () && generate_p (dynamic_cast<Element&> (n)))) + { + if (count_ >= first_ && count_ <= last_) + { + if (!opened) + { + opened = true; + pre (ns); + } + + edge_traverser ().dispatch (*i); + } + + ++count_; + } + } + + if (opened) + post (ns); + } + } + + void Namespace:: + enter (Type&, String const& name, bool) + { + ctx_.enter_ns_scope (name); + } + + void Namespace:: + leave () + { + ctx_.leave_ns_scope (); + } + + // Includes + // + void TypeForward:: + traverse (SemanticGraph::Type& t) + { + String const& name (ename (t)); + + if (String custom = custom_type (t)) + { + String new_name; + renamed_type (t, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + + void Includes:: + traverse_ (SemanticGraph::Uses& u) + { + // Support for weak (forward) inclusion used in the file-per-type + // compilation model. + // + Type t (type_); + bool weak (u.context ().count ("weak")); + SemanticGraph::Schema& s (u.schema ()); + + if (weak && t == header) + { + // Generate forward declarations. + // + if (forward_) + t = forward; + else + { + schema_.dispatch (s); + return; + } + } + + if (t == source && !weak) + { + if (u.user ().context ().count ("type-schema")) + { + // Strong include into a type schema -- this is a base class. + // We have already included its header in our header so it + // would seem we don't need to do anything here. There is one + // subtle issue, however: Our constructors include arguments + // for base members which we simply pass to the base. The base + // header has only forward declarations for its members. This + // is not a problem if we pass references to base members -- + // forward declarations are sufficient for this case. The + // problematic case is when we pass them as auto/unique_ptr. + // Because we pass them by value (which is done to support + // unique_ptr move semantics), the compiler needs to be able + // to destroy the member, presumably if an exception is thrown. + // And for that forward declarations are not enough. + // + // So what we are going to do here is include all the base + // member headers (transitively), just like the base's source + // file does. + // + // Note that we only do this for source since in the inline + // case the necessary files are already pulled via the the + // .ixx file includes. + // + Traversal::Schema schema; + schema >> *this; + schema.dispatch (s); + } + + return; + } + + SemanticGraph::Path path ( + s.context ().count ("renamed") + ? s.context ().get<SemanticGraph::Path> ("renamed") + : u.path ()); + path.normalize (); + + // Try to use the portable representation of the path. If that + // fails, fall back to the native representation. + // + NarrowString path_str; + try + { + path_str = path.posix_string (); + } + catch (SemanticGraph::InvalidPath const&) + { + path_str = path.string (); + } + + String inc_path; + + switch (t) + { + case forward: + { + inc_path = ctx_.fwd_expr->replace (path_str); + break; + } + case header: + case source: + { + inc_path = ctx_.hxx_expr->replace (path_str); + break; + } + case inline_: + { + if (weak) + { + inc_path = ctx_.hxx_expr->replace (path_str); + ctx_.os << "#include " << ctx_.process_include_path (inc_path) + << endl; + } + + inc_path = ctx_.ixx_expr->replace (path_str); + break; + } + } + + ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl + << endl; + } + } +} diff --git a/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx new file mode 100644 index 0000000..4d10def --- /dev/null +++ b/xsd/cxx/tree/elements.hxx @@ -0,0 +1,2122 @@ +// file : xsd/cxx/tree/elements.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_ELEMENTS_HXX +#define XSD_CXX_TREE_ELEMENTS_HXX + +#include <map> +#include <set> +#include <deque> +#include <vector> +#include <sstream> + +#include <libcutl/re.hxx> + +#include <xsd/types.hxx> + +#include <xsd/cxx/elements.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + struct Counts + { + Counts () + : global_types (0), + global_elements (0), + generated_global_elements (0), + complexity_total (0) + { + } + + size_t global_types; + size_t global_elements; + size_t generated_global_elements; + + // Complexity value for each global type and generated global + // element, in order. + // + std::vector<size_t> complexity; + size_t complexity_total; + }; + + struct InvalidCustomTypeMapping + { + InvalidCustomTypeMapping (String const& mapping, + String const& reason) + : mapping_ (mapping), reason_ (reason) + { + } + + String const& + mapping () const + { + return mapping_; + } + + String const& + reason () const + { + return reason_; + } + + private: + String mapping_; + String reason_; + }; + + // A set of potentially qualified XML Schema type names. + // + struct TypeNameSet + { + template <typename I> + TypeNameSet (I begin, I end) + { + for (; begin != end; ++begin) + insert (*begin); + } + + void + insert (String const& name) + { + size_t p (name.rfind ('#')); + + if (p == String::npos) + unames_.insert (name); + else + qnames_.insert (name); + } + + bool + find (SemanticGraph::Type& t) + { + if (!unames_.empty ()) + { + if (unames_.find (t.name ()) != unames_.end ()) + return true; + } + + if (!qnames_.empty ()) + { + if (qnames_.find (t.scope ().name () + L"#" + t.name ()) != + qnames_.end ()) + return true; + } + + return false; + } + + private: + typedef std::set<String> StringSet; + + StringSet unames_; + StringSet qnames_; + }; + + // + // + class Context: public CXX::Context + { + public: + typedef cutl::re::regexsub Regex; + typedef cutl::re::wregex WideRegexPat; + + typedef Tree::options options_type; + + struct DirectCustomTypeMapInfo + { + DirectCustomTypeMapInfo (String const& t = L"", + String const& b = L"") + : type (t), base (b) + { + } + + String type; + String base; + }; + + struct RegexCustomTypeMapInfo + { + RegexCustomTypeMapInfo (WideRegexPat const& p, + String const& t, + String const& b) + : pat (p), type_sub (t), base_sub (b) + { + } + + WideRegexPat pat; + String type_sub; + String base_sub; + }; + + typedef std::vector<RegexCustomTypeMapInfo> RegexCustomTypeMap; + typedef std::map<String, DirectCustomTypeMapInfo> DirectCustomTypeMap; + + public: + Context (std::wostream& o, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + options_type const& ops, + Counts const& counts_, + bool generate_xml_schema, + StringLiteralMap const*, + Regex const* fwd_expr, + Regex const* hxx_expr, + Regex const* ixx_expr); + + protected: + Context (Context& c); + Context (Context& c, std::wostream& o); + + // Custom type mapping. + // + public: + // Returns empty string if custom mapping is not required. + // + String + custom_type (SemanticGraph::Type const&) const; + + // Returns true if custom mapping is required. name is + // populated with the custom type name or empty if the + // original name should be used. + // + bool + custom_type (SemanticGraph::Type const&, String& name) const; + + // Returns true if this type has been renamed as part of the + // customization process. If the function returns true, the + // name string is populated with the new name or empty if + // the type should not be generated at all. + // + bool + renamed_type (SemanticGraph::Type const&, String& name) const; + + public: + // Performs a number of processing steps, including forcing a new + // line after 80 characters as well as "commentizing" the text by + // adding '* ' after each newline. + // + void + write_annotation (SemanticGraph::Annotation&); + + // + // + public: + static bool + ordered_p (SemanticGraph::Type const& t) + { + return t.context ().count ("ordered") && + t.context ().get<bool> ("ordered"); + } + + // Check if we are generating mixed support for this type. We only + // do it for ordered types. + // + static bool + mixed_p (SemanticGraph::Complex const& c) + { + return c.mixed_p () && ordered_p (c); + } + + bool + polymorphic_p (SemanticGraph::Type&); + + bool + anonymous_p (SemanticGraph::Type const& t) + { + return t.context ().count ("anonymous"); + } + + // Return true if this anonymous type is defined in an element + // that belongs to a substitution group. + // + bool + anonymous_substitutes_p (SemanticGraph::Type&); + + // Escaped names. + // + public: + // Accessor name. + // + static String const& + eaname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("aname"); + } + + static String const& + eaname (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("aname"); + } + + static String const& + eaname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("aname"); + } + + // Modifier name. + // + static String const& + emname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("mname"); + } + + static String const& + emname (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("mname"); + } + + static String const& + emname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("mname"); + } + + // Detach name. + // + static String const& + edname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("dname"); + } + + // + // + static String const& + etype (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("type"); + } + + static String const& + etraits (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("traits"); + } + + static String const& + econtainer (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("container"); + } + + static String const& + econtainer (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("container"); + } + + static String const& + econtainer (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("container"); + } + + static String const& + eiterator (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("iterator"); + } + + static String const& + eiterator (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("iterator"); + } + + static String const& + eiterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("const-iterator"); + } + + static String const& + emember (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("member"); + } + + static String const& + emember (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("member"); + } + + static String const& + emember (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("member"); + } + + static String const& + edefault_value (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("default-value"); + } + + static String const& + edefault_value_member (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("default-value-member"); + } + + // Underlying enum value type. + // + static String const& + evalue (SemanticGraph::Enumeration const& e) + { + return e.context ().get<String> ("value"); + } + + // dom_document + // + static bool + edom_document_p (SemanticGraph::Complex const& c) + { + return c.context ().count ("dom-document"); + } + + static String const& + edom_document (SemanticGraph::Complex const& c) + { + return c.context ().get<String> ("dom-document"); + } + + static bool + edom_document_member_p (SemanticGraph::Complex const& c) + { + return c.context ().count ("dom-document-member"); + } + + static String const& + edom_document_member (SemanticGraph::Complex const& c) + { + return c.context ().get<String> ("dom-document-member"); + } + + // Parsing and serialization function names. + // + static String const& + eparser (SemanticGraph::Element const& e) + { + return e.context ().get<String> ("parser"); + } + + static String const& + eserializer (SemanticGraph::Element const& e) + { + return e.context ().get<String> ("serializer"); + } + + public: + void + enter_ns_scope (String const& name) + { + ns_scope_stack.push_back (name); + update_ns_scope (); + } + + void + leave_ns_scope () + { + ns_scope_stack.pop_back (); + update_ns_scope (); + } + + private: + void + update_ns_scope (); + + private: + // Write text that may contain characters that we will have + // to escape (indicated by the rogue flag). + // + void + write_rogue_text (wchar_t const* s, size_t size, bool rogue); + + public: + options_type const& options; + Counts const& counts; + String& any_type; + String& any_simple_type; + String& element_type; + String& container; + String& flags_type; + String& qname_type; + String& xs_string_type; + String& properties_type; + String& error_handler_type; + String& list_stream_type; + String& namespace_infomap_type; + String& parser_type; + String& std_ostream_type; + String& ostream_type; + String& istream_type; + String& xerces_ns; + String& dom_auto_ptr; + String& dom_node_key; + String& as_double_type; + String& as_decimal_type; + + bool& generate_xml_schema; + bool& doxygen; + bool polymorphic; + bool polymorphic_all; + unsigned long poly_plate; + bool detach; + + Regex const* fwd_expr; + Regex const* hxx_expr; + Regex const* ixx_expr; + + String& ns_scope; + + RegexCustomTypeMap& regex_custom_type_map; + DirectCustomTypeMap& direct_custom_type_map; + + private: + String any_type_; + String any_simple_type_; + String element_type_; + String container_; + String flags_type_; + String qname_type_; + String xs_string_type_; + String properties_type_; + String error_handler_type_; + String list_stream_type_; + String namespace_infomap_type_; + String parser_type_; + String std_ostream_type_; + String ostream_type_; + String istream_type_; + String xerces_ns_; + String dom_auto_ptr_; + String dom_node_key_; + String as_double_type_; + String as_decimal_type_; + + bool generate_xml_schema_; + bool doxygen_; + + typedef std::deque<String> NamespaceStack; + typedef std::deque<String> ScopeStack; + + String ns_scope_; + + NamespaceStack& ns_scope_stack; + NamespaceStack ns_scope_stack_; + + RegexCustomTypeMap regex_custom_type_map_; + DirectCustomTypeMap direct_custom_type_map_; + + private: + WideRegexPat const cxx_uq_id_expr_; + WideRegexPat const& cxx_uq_id_expr; + }; + + // Check whether this Schema type maps to a fundamental C++ type. + // + struct IsFundamentalType: 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 + + { + IsFundamentalType (bool& r) + : r_ (r) + { + } + + // Integral types. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Short&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Int&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Long&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger&) + { + r_ = true; + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean&) + { + r_ = true; + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Double&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal&) + { + r_ = true; + } + + private: + bool& r_; + }; + + // Check whether this is a string-based type. + // + struct IsStringBasedType: Traversal::Complex, + Traversal::Union, + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language + { + IsStringBasedType (bool& r) + : r_ (r) + { + *this >> inherits_ >> *this; + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + } + + virtual void + traverse (SemanticGraph::Union&) + { + // Current mapping of union is string-based. + // + r_ = true; + } + + // Strings. + // + virtual void + traverse (SemanticGraph::Fundamental::String&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Token&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NameToken&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Name&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NCName&) + { + r_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Language&) + { + r_ = true; + } + + private: + bool& r_; + Traversal::Inherits inherits_; + }; + + + // Check whether this is a enumeration-based type. + // + struct IsEnumBasedType: Traversal::Complex + { + IsEnumBasedType (SemanticGraph::Enumeration*& e) + : enum_ (e) + { + *this >> inherits_; + + inherits_ >> *this; + inherits_ >> enum_; + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + } + + private: + struct Enumeration: Traversal::Enumeration + { + Enumeration (SemanticGraph::Enumeration*& e) + : e_ (e) + { + } + + virtual void + traverse (Type& e) + { + if (e_ == 0) + e_ = &e; + } + + private: + SemanticGraph::Enumeration*& e_; + }; + + + private: + Enumeration enum_; + Traversal::Inherits inherits_; + }; + + + // + // + struct MemberTypeName : Context, + Traversal::Type, + Traversal::List, + Traversal::Union, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + 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::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 + + { + MemberTypeName (Context& c) + : Context (c) + { + } + + MemberTypeName (Context& c, std::wostream& o) + : Context (c, o) + { + } + + virtual void + traverse (SemanticGraph::Type&) + { + abort (); + } + + virtual void + traverse (SemanticGraph::List& l) + { + os << fq_name (l); + } + + virtual void + traverse (SemanticGraph::Union& u) + { + os << fq_name (u); + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + os << fq_name (c); + } + + // anyType & anySimpleType. + // + virtual void + traverse (SemanticGraph::AnyType& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::AnySimpleType& t) + { + os << fq_name (t); + } + + // Integral types. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + os << fq_name (t); + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + os << fq_name (t); + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + os << fq_name (t); + } + + // Strings. + // + virtual void + traverse (SemanticGraph::Fundamental::String& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Token& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Name& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NCName& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Language& t) + { + os << fq_name (t); + } + + + // Qualified name. + // + virtual void + traverse (SemanticGraph::Fundamental::QName& t) + { + os << fq_name (t); + } + + + // ID/IDREF. + // + virtual void + traverse (SemanticGraph::Fundamental::Id& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + if (t.named_p ()) + { + // IDREF<anyType> + // + os << fq_name (t); + } + else + { + SemanticGraph::Nameable& ncname ( + xs_ns ().find ("NCName").first->named ()); + + os << "::xsd::cxx::tree::idref< " << char_type << ", " << + fq_name (ncname) << ", " << + type_name (t.argumented ().type ()) << " >"; + } + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + if (t.named_p ()) + { + // IDREFS<anyType> + // + os << fq_name (t); + } + else + { + SemanticGraph::Nameable& ncname ( + xs_ns ().find ("NCName").first->named ()); + + os << "::xsd::cxx::tree::idrefs< " << char_type << ", " << + any_simple_type << ", ::xsd::cxx::tree::idref< " << + char_type << ", " << fq_name (ncname) << ", " << + type_name (t.argumented ().type ()) << " > >"; + } + } + + // URI. + // + virtual void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + os << fq_name (t); + } + + // Binary. + // + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + os << fq_name (t); + } + + + // Date/time. + // + virtual void + traverse (SemanticGraph::Fundamental::Date& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Duration& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Day& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Month& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Year& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Time& t) + { + os << fq_name (t); + } + + // Entity. + // + virtual void + traverse (SemanticGraph::Fundamental::Entity& t) + { + os << fq_name (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Entities& t) + { + os << fq_name (t); + } + + private: + // For idref/idrefs + // + String + type_name (SemanticGraph::Type& t) + { + // This type is always named. + // + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + // + // + struct BaseTypeName : MemberTypeName + { + BaseTypeName (Context& c) + : MemberTypeName (c) + { + } + + BaseTypeName (Context& c, std::wostream& o) + : MemberTypeName (c, o) + { + } + + virtual void + fundamental_base (SemanticGraph::Type& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << " >"; + } + + // Integrals. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fundamental_base (t); + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fundamental_base (t); + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + fundamental_base (t); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << ", " << + "::xsd::cxx::tree::schema_type::double_ >"; + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << ", " << + "::xsd::cxx::tree::schema_type::decimal >"; + } + }; + + // Initial value should be true. + // + struct IsSimpleType: Traversal::Complex, + Traversal::Member, + Traversal::Any, + Traversal::AnyAttribute + { + IsSimpleType (bool& v) + : v_ (v) + { + *this >> names_ >> *this; + *this >> inherits_ >> *this; + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + if (c.mixed_p ()) + v_ = false; + + if (v_) + names (c, names_); + + if (v_) + inherits (c, inherits_); + } + + virtual void + traverse (SemanticGraph::Member&) + { + v_ = false; + } + + virtual void + traverse (SemanticGraph::Any&) + { + v_ = false; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + v_ = false; + } + + private: + bool& v_; + Traversal::Names names_; + Traversal::Inherits inherits_; + }; + + // Test whether we need to generate default c-tor. Note that we are not + // interested in anyAttribute since it is always mapped to a sequence. + // + struct GenerateDefaultCtor: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Traversal::Element, + Traversal::Attribute, + Traversal::Any, + Context + { + // generate should initially be false. + // + GenerateDefaultCtor (Context&, bool& generate, bool no_base); + + virtual void + traverse (SemanticGraph::Complex&); + + virtual void + traverse (SemanticGraph::Type&); + + virtual void + traverse (SemanticGraph::Enumeration&); + + virtual void + traverse (SemanticGraph::Element&); + + virtual void + traverse (SemanticGraph::Attribute&); + + virtual void + traverse (SemanticGraph::Any&); + + private: + bool& generate_; + bool no_base_; + + private: + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // Test whether we need to generate from-base c-tor. + // + struct GenerateFromBaseCtor: Traversal::Complex + { + // generate should initially be false. + // + GenerateFromBaseCtor (Context& c, bool& generate); + + virtual void + traverse (SemanticGraph::Complex& c); + + private: + bool& generate_; + bool custom_; + + // Note that we are not interested in anyAttribute since it is always + // mapped to a sequence. + // + struct Traverser: Traversal::Type, + Traversal::Complex, + Traversal::Element, + Traversal::Attribute, + Traversal::Any, + Context + { + Traverser (Context& c, bool& generate, bool& custom); + + virtual void + traverse (SemanticGraph::Type&); + + virtual void + traverse (SemanticGraph::Complex&); + + virtual void + traverse (SemanticGraph::Attribute&); + + virtual void + traverse (SemanticGraph::Element&); + + virtual void + traverse (SemanticGraph::Any&); + + private: + bool& generate_; + bool& custom_; + + private: + Traversal::Inherits inherits_; + Traversal::Names names_; + } traverser_; + + Traversal::Inherits inherits_; + }; + + // Test whether the type has any non-optional element of complex + // (has attributes/elements) and polymorpjic types. + // + struct HasComplexPolyNonOptArgs: Traversal::Complex, + Traversal::Element, + Context + { + // complex and poly should initially be false. clash + // should initially be true. + // + HasComplexPolyNonOptArgs (Context& c, + bool including_base, + bool& complex, + bool& poly, + bool& clash); + + virtual void + traverse (SemanticGraph::Complex&); + + virtual void + traverse (SemanticGraph::Element&); + + private: + bool& complex_; + bool& poly_; + bool& clash_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // Contructor argument types. + // + struct CtorArgType + { + enum Value + { + type, + complex_auto_ptr, + poly_auto_ptr + }; + + CtorArgType (Value v = Value (0)) : v_ (v) {} + operator Value () const {return v_;} + + private: + Value v_; + }; + + // Immediate non-optional member. Note that AnyAttribute is always + // mapped to a sequence. + // + struct FromBaseCtorArg: Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + FromBaseCtorArg (Context& c, CtorArgType, bool arg); + + virtual void + traverse (SemanticGraph::Any&); + + virtual void + traverse (SemanticGraph::Attribute&); + + virtual void + traverse (SemanticGraph::Element&); + + private: + CtorArgType arg_type_; + bool arg_; + }; + + // List of all non-optional members and a simple base. Note that + // AnyAttribute is always mapped to a sequence. + // + struct CtorArgs: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + using Complex::traverse; + + // The second version outputs the argument name and stores + // in in the base_arg string. + // + CtorArgs (Context&, CtorArgType); + CtorArgs (Context&, CtorArgType, String& base_arg); + + virtual void + traverse (SemanticGraph::Type&); + + virtual void + traverse (SemanticGraph::Enumeration&); + + virtual void + traverse (SemanticGraph::Any&); + + virtual void + traverse (SemanticGraph::Attribute&); + + virtual void + traverse (SemanticGraph::Element&); + + private: + String + comma (); + + private: + CtorArgType arg_type_; + String base_; + String* base_arg_; + bool first_; + + private: + Traversal::Inherits inherits_; + Traversal::Names names_; + + MemberTypeName member_name_; + }; + + + // Check whether we need to generate c-tor without the base argument. + // + struct GenerateWithoutBaseCtor: Traversal::List, + Traversal::Union, + Traversal::Complex, + Traversal::Enumeration, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary + { + // generate should initially be false. + // + GenerateWithoutBaseCtor (bool& generate) + : generate_ (generate) + { + *this >> inherits_ >> *this; + } + + virtual void + traverse (SemanticGraph::List&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Union&) + { + // No default initialization. + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + Complex::inherits (c); + } + + virtual void + traverse (SemanticGraph::Enumeration&) + { + // No default initialization. + } + + virtual void + traverse (SemanticGraph::AnyType&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::AnySimpleType&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::String&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Token&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary&) + { + generate_ = true; + } + + private: + bool& generate_; + Traversal::Inherits inherits_; + }; + + + // List of all non-optional members sans simple base. Note that + // AnyAttribute is always mapped to a sequence. + // + struct CtorArgsWithoutBase: Traversal::Complex, + Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + using Complex::traverse; + + CtorArgsWithoutBase (Context& c, CtorArgType, bool arg, bool first); + + virtual void + traverse (SemanticGraph::Any&); + + virtual void + traverse (SemanticGraph::Element&); + + virtual void + traverse (SemanticGraph::Attribute&); + + private: + String + comma (); + + private: + CtorArgType arg_type_; + bool arg_; + bool first_; + + private: + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // + // + struct GlobalElementBase + { + GlobalElementBase (Context& c) + : ctx_ (c) + { + } + + bool + generate_p (SemanticGraph::Element&); + + bool + doc_root_p (SemanticGraph::Element&); + + private: + Context& ctx_; + }; + + + // + // + struct Namespace: CXX::Namespace, + GlobalElementBase, + CXX::Namespace::ScopeTracker + { + Namespace (Context&, + size_t first = 1, + size_t last = 0); + + virtual void + traverse (Type&); + + protected: + virtual void + enter (Type&, String const& name, bool last); + + virtual void + leave (); + + protected: + Context& ctx_; + + private: + size_t first_; + size_t last_; + size_t count_; + }; + + // + // + struct DocumentedNamespace: Namespace + { + DocumentedNamespace (Context& c) + : Namespace (c) + { + } + + virtual void + enter (Type& ns, String const& name, bool last) + { + Namespace::enter (ns, name, last); + + // Only add documentation to the innermost namespace. + // + if (ctx_.doxygen && name && last) + { + ctx_.os << "/**" << endl + << " * @brief C++ namespace for the %" << + ctx_.comment (ns.name ()) << endl + << " * schema namespace." << endl + << " */" << endl; + } + } + }; + + // + // + struct TypeForward: Traversal::Type, Context + { + TypeForward (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Type& t); + }; + + struct Includes: Traversal::Imports, + Traversal::Includes + { + enum Type + { + forward, + header, + inline_, + source + }; + + Includes (Context& c, Type type) + : ctx_ (c), + type_ (type), + forward_ (c.options.generate_forward ()), + namespace_ (c), + type_forward_ (c) + { + schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_; + } + + virtual void + traverse (SemanticGraph::Imports& i) + { + traverse_ (i); + } + + virtual void + traverse (SemanticGraph::Includes& i) + { + traverse_ (i); + } + + private: + void + traverse_ (SemanticGraph::Uses&); + + private: + Context& ctx_; + Type type_; + bool forward_; + + Traversal::Schema schema_; + Traversal::Names schema_names_; + Namespace namespace_; + Traversal::Names names_; + TypeForward type_forward_; + }; + + // + // + struct FundIncludes: 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, + Context + { + FundIncludes (Context& c, String const& prefix) + : Context (c), prefix_ (prefix), + long_ (false), unsigned_long_ (false) + { + } + + // Integral types. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + gen_include (t, "byte.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + gen_include (t, "unsigned-byte.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + gen_include (t, "short.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + gen_include (t, "unsigned-short.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + gen_include (t, "int.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + gen_include (t, "unsigned-int.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + if (!long_) + long_ = gen_include (t, "long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + if (!unsigned_long_) + unsigned_long_ = gen_include (t, "unsigned-long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + if (!long_) + long_ = gen_include (t, "long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + if (!long_) + long_ = gen_include (t, "long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + if (!unsigned_long_) + unsigned_long_ = gen_include (t, "unsigned-long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + if (!unsigned_long_) + unsigned_long_ = gen_include (t, "unsigned-long.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + if (!long_) + long_ = gen_include (t, "long.hxx"); + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + gen_include (t, "boolean.hxx"); + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + gen_include (t, "float.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + gen_include (t, "double.hxx"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + gen_include (t, "decimal.hxx"); + } + + private: + bool + gen_include (SemanticGraph::Type& t, String const& file) + { + String custom; + + // XML Schema built-in type customization is only possible when + // we are generating separate header. + // + if (generate_xml_schema && custom_type (t, custom)) + { + String new_name; + renamed_type (t, new_name); + + if (!new_name) + return false; + } + + os << "#include <xsd/cxx/tree/" << prefix_ << "/" << file << ">" + << endl; + + return true; + } + + private: + String prefix_; + bool long_; + bool unsigned_long_; + }; + } +} + +#endif // XSD_CXX_TREE_ELEMENTS_HXX diff --git a/xsd/cxx/tree/fundamental-header.hxx b/xsd/cxx/tree/fundamental-header.hxx new file mode 100644 index 0000000..0ea82cf --- /dev/null +++ b/xsd/cxx/tree/fundamental-header.hxx @@ -0,0 +1,1337 @@ +// file : xsd/cxx/tree/fundamental-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX +#define XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX + +#include <set> +#include <vector> +#include <algorithm> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + struct FundamentalNamespace : DocumentedNamespace, + + Traversal::AnyType, + Traversal::AnySimpleType, + + 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::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::QName, + + 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 + { + using Namespace::traverse; + + FundamentalNamespace (Context& c) + : DocumentedNamespace (c), + Context (c), + export_ (c.options.export_xml_schema () && type_exp) + { + *this >> names_ >> *this; + + if (export_) + xs_ns_ = ns_name (xs_ns ()); + } + + void + gen_typedef (String const& name, + String const& type, + String const& arg1 = L"", + String const& arg2 = L"", + String const& arg3 = L"", + bool export_type = true) + { + os << "typedef " << type; + + // Use unqualified arguments since we are in the same + // namespace. + // + if (arg1) + { + os << arg1; + + if (arg2) + { + os << ", " << arg2; + + if (arg3) + os << ", " << arg3; + } + + os << " >"; + } + + os << " " << name << ";"; + + if (export_type && export_ && type.find (L'<') != String::npos) + { + String s (type); + + // Use qualified arguments. + // + if (arg1) + { + s += xs_ns_; + s += L"::"; + s += arg1; + + if (arg2) + { + s += L", "; + s += xs_ns_; + s += L"::"; + s += arg2; + + if (arg3) + { + s += L", "; + s += xs_ns_; + s += L"::"; + s += arg3; + } + } + + s += " >"; + } + + if (exports_set_.count (s) == 0) + { + exports_.push_back (s); + exports_set_.insert (s); + } + } + } + + String + built_in_type (SemanticGraph::Type& t, + String const& type, + String const& arg1 = L"", + String const& arg2 = L"", + String const& arg3 = L"") + { + String custom; + + String name (ename (t)); + + // XML Schema built-in type customization is only possible when + // we are generating separate header. + // + if (generate_xml_schema && custom_type (t, custom)) + { + if (custom.empty ()) + custom = name; + + String new_name; + renamed_type (t, new_name); + + if (new_name) + { + gen_typedef (new_name, type, arg1, arg2, arg3); + + if (doxygen) + os << endl; + } + + if (doxygen) + os << "/**" << endl + << " * @brief C++ type corresponding to the " << + comment (t.name ()) << " XML Schema" << endl + << " * built-in type." << endl + << " */" << endl; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + + if (doxygen) + os << endl; + } + else + { + // Otherwise generate simple typedef. + // + + if (doxygen) + os << "/**" << endl + << " * @brief C++ type corresponding to the " << + comment (t.name ()) << " XML Schema" << endl + << " * built-in type." << endl + << " */" << endl; + + gen_typedef (name, type, arg1, arg2, arg3); + + if (doxygen) + os << endl; + } + + return name; + } + + // anyType and anySimpleType + // + virtual void + traverse (SemanticGraph::AnyType& t) + { + os << "// anyType and anySimpleType." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + type_ = built_in_type (t, "::xsd::cxx::tree::type"); + } + + virtual void + traverse (SemanticGraph::AnySimpleType& t) + { + simple_type_ = built_in_type ( + t, L"::xsd::cxx::tree::simple_type< " + char_type + L", ", type_); + + if (doxygen) + os << "/**" << endl + << " * @brief Alias for the anyType type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("container"), + "::xsd::cxx::tree::type"); + + os << endl; + + if (doxygen) + os << endl; + } + + // Integrals. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + os << "// 8-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "signed char"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + built_in_type (t, "unsigned char"); + os << endl; + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + os << "// 16-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "short"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + built_in_type (t, "unsigned short"); + os << endl; + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + os << "// 32-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "int"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + built_in_type (t, "unsigned int"); + os << endl; + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + os << "// 64-bit" << endl + << "//" <<endl; + + if (doxygen) + os << endl; + + built_in_type (t, "long long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + built_in_type (t, "unsigned long long"); + os << endl; + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + os << "// Supposed to be arbitrary-length integral types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "long long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + built_in_type (t, "long long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + built_in_type (t, "unsigned long long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + built_in_type (t, "unsigned long long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + built_in_type (t, "long long"); + os << endl; + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + os << "// Boolean." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "bool"); + + os << endl; + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + os << "// Floating-point types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "float"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + double_ = built_in_type (t, "double"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + decimal_ = built_in_type (t, "double"); + os << endl; + } + + + // Strings. + // + virtual void + traverse (SemanticGraph::Fundamental::String& t) + { + os << "// String types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + string_ = built_in_type ( + t, L"::xsd::cxx::tree::string< " + char_type + L", ", simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + norm_string_ = built_in_type ( + t, + L"::xsd::cxx::tree::normalized_string< " + char_type + L", ", + string_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Token& t) + { + token_ = built_in_type ( + t, L"::xsd::cxx::tree::token< " + char_type + L", ", norm_string_); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + nmtoken_ = built_in_type ( + t, L"::xsd::cxx::tree::nmtoken< " + char_type + L", ", token_); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::nmtokens< " + char_type + L", ", + simple_type_, + nmtoken_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Name& t) + { + name_ = built_in_type ( + t, L"::xsd::cxx::tree::name< " + char_type + L", ", token_); + } + + virtual void + traverse (SemanticGraph::Fundamental::NCName& t) + { + ncname_ = built_in_type ( + t, L"::xsd::cxx::tree::ncname< " + char_type + L", ", name_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Language& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::language< " + char_type + L", ", token_); + + os << endl; + } + + // ID/IDREF. + // + virtual void + traverse (SemanticGraph::Fundamental::Id& t) + { + os << "// ID/IDREF." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type ( + t, L"::xsd::cxx::tree::id< " + char_type + L", ", ncname_); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + idref_ = built_in_type ( + t, L"::xsd::cxx::tree::idref< " + char_type + L", ", ncname_, type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::idrefs< " + char_type + L", ", + simple_type_, + idref_); + + os << endl; + } + + + // URI. + // + virtual void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + os << "// URI." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + uri_ = built_in_type ( + t, L"::xsd::cxx::tree::uri< " + char_type + L", ", simple_type_); + + os << endl; + } + + // Qualified name. + // + virtual void + traverse (SemanticGraph::Fundamental::QName& t) + { + os << "// Qualified name." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type ( + t, + L"::xsd::cxx::tree::qname< " + char_type + L", ", + simple_type_, + uri_, + ncname_); + + os << endl; + } + + // Binary. + // + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + os << "// Binary." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Binary buffer type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("buffer"), + L"::xsd::cxx::tree::buffer< " + char_type + L" >"); + + if (doxygen) + os << endl; + + built_in_type ( + t, + L"::xsd::cxx::tree::base64_binary< " + char_type + L", ", + simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::hex_binary< " + char_type + L", ", + simple_type_); + + os << endl; + } + + + // Date/time. + // + virtual void + traverse (SemanticGraph::Fundamental::Date& t) + { + os << "// Date/time." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Time zone type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("time-zone"), + "::xsd::cxx::tree::time_zone"); + + if (doxygen) + os << endl; + + built_in_type ( + t, L"::xsd::cxx::tree::date< " + char_type + L", ", simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::date_time< " + char_type + L", ", + simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Duration& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::duration< " + char_type + L", ", + simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Day& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gday< " + char_type + L", ", simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Month& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gmonth< " + char_type + L", ", simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::gmonth_day< " + char_type + L", ", + simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Year& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gyear< " + char_type + L", ", simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::gyear_month< " + char_type + L", ", + simple_type_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Time& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::time< " + char_type + L", ", simple_type_); + + os << endl; + } + + // Entity. + // + virtual void + traverse (SemanticGraph::Fundamental::Entity& t) + { + os << "// Entity." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + entity_ = built_in_type ( + t, L"::xsd::cxx::tree::entity< " + char_type + L", ", ncname_); + } + + virtual void + traverse (SemanticGraph::Fundamental::Entities& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::entities< " + char_type + L", ", + simple_type_, + entity_); + + os << endl; + } + + virtual void + post (SemanticGraph::Namespace& n) + { + SemanticGraph::Context& c (xs_ns ().context()); + + bool parsing (!options.suppress_parsing ()); + bool serialization (options.generate_serialization ()); + bool element_map (options.generate_element_map ()); + + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order sequence entry." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("content-order"), + "::xsd::cxx::tree::content_order"); + } + + if (options.generate_element_type ()) + { + if (doxygen) + os << "/**" << endl + << " * @brief Base class for element types." << endl + << " */" << endl; + else + os << "// Base class for element types." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("element-type"), + L"::xsd::cxx::tree::element_type< " + char_type + L", ", + type_); + + os << endl; + } + + if (element_map) + { + if (doxygen) + os << "/**" << endl + << " * @brief Root element map." << endl + << " */" << endl; + else + os << "// Root element map." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("element-map"), + L"::xsd::cxx::tree::element_map< " + char_type + L", ", + type_); + + os << endl; + } + + if (serialization) + { + os << "// Namespace information and list stream. Used in" << endl + << "// serialization functions." << endl + << "//" << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Namespace serialization information." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("namespace-info"), + L"::xsd::cxx::xml::dom::namespace_info< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Namespace serialization information map." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("namespace-infomap"), + L"::xsd::cxx::xml::dom::namespace_infomap< " + + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief List serialization stream." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("list-stream"), + L"::xsd::cxx::tree::list_stream< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Serialization wrapper for the %double type." << endl + << " */" << endl; + + // Do not export as_double and as_decimal since they are already + // instantiated. + // + gen_typedef (c.get<String> ("as-double"), + L"::xsd::cxx::tree::as_double< ", + double_, + "", + "", + false); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Serialization wrapper for the %decimal type." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("as-decimal"), + L"::xsd::cxx::tree::as_decimal< ", + decimal_, + "", + "", + false); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Simple type facet." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("facet"), "::xsd::cxx::tree::facet"); + + os << endl; + } + + //@@ Can't change names of ostream/istream since they are + // templates. + // + if (!options.generate_insertion ().empty ()) + { + if (doxygen) + os << "/**" << endl + << " * @brief Data representation output stream template." << endl + << " */" << endl; + else + os << "// Data representation output stream template." << endl + << "//" << endl; + + os << "using ::xsd::cxx::tree::ostream;" + << endl; + } + + if (!options.generate_extraction ().empty ()) + { + if (doxygen) + os << "/**" << endl + << " * @brief Data representation input stream template." << endl + << " */" << endl; + else + os << "// Data representation input stream template." << endl + << "//" << endl; + + os << "using ::xsd::cxx::tree::istream;" + << endl; + } + + os << "// Flags and properties." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Parsing and serialization flags." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("flags"), "::xsd::cxx::tree::flags"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Parsing properties." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("properties"), + L"::xsd::cxx::tree::properties< " + char_type + L" >"); + os << endl; + + + // + // + if (parsing || serialization) + { + os << "// Parsing/serialization diagnostics." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Error severity." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("severity"), + "::xsd::cxx::tree::severity"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Error condition." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("error"), + L"::xsd::cxx::tree::error< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief List of %error conditions." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("diagnostics"), + L"::xsd::cxx::tree::diagnostics< " + char_type + L" >"); + os << endl; + } + + // + // + os << "// Exceptions." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Root of the C++/Tree %exception hierarchy." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("exception"), + L"::xsd::cxx::tree::exception< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the size argument exceeds" << + endl + << " * the capacity argument." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("bounds"), + L"::xsd::cxx::tree::bounds< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that a duplicate ID value" << + endl + << " * was encountered in the object model." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("duplicate-id"), + L"::xsd::cxx::tree::duplicate_id< " + char_type + L" >"); + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating a parsing failure." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("parsing"), + L"::xsd::cxx::tree::parsing< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an expected element" << + endl + << " * was not encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-element"), + L"::xsd::cxx::tree::expected_element< " + char_type + L" >"); + } + + if (parsing || serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an unexpected " << + "element" << endl + << " * was encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("unexpected-element"), + L"::xsd::cxx::tree::unexpected_element< " + char_type + L" >"); + } + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an expected " << + "attribute" << endl + << " * was not encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-attribute"), + L"::xsd::cxx::tree::expected_attribute< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an unexpected " << + "enumerator" << endl + << " * was encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("unexpected-enumerator"), + L"::xsd::cxx::tree::unexpected_enumerator< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the text content " << + "was" << endl + << " * expected for an element." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-text-content"), + L"::xsd::cxx::tree::expected_text_content< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that a prefix-namespace" << + endl + << " * mapping was not provided." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-prefix-mapping"), + L"::xsd::cxx::tree::no_prefix_mapping< " + char_type + L" >"); + } + + if (options.generate_polymorphic ()) + { + if (parsing || serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the type " << + "information" << endl + << " * is not available for a type." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-type-info"), + L"::xsd::cxx::tree::no_type_info< " + char_type + L" >"); + } + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the types are not" << + endl + << " * related by inheritance." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("not-derived"), + L"::xsd::cxx::tree::not_derived< " + char_type + L" >"); + } + } + + if (element_map) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that parsing or " << + "serialization" << endl + << " * information is not available for an element." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-element-info"), + L"::xsd::cxx::tree::no_element_info< " + char_type + L" >"); + } + + if (serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating a serialization " << + "failure." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("serialization"), + L"::xsd::cxx::tree::serialization< " + char_type + L" >"); + } + + os << endl; + + if (parsing || serialization) + { + if (doxygen) + os << "/**" << endl + << " * @brief Error handler callback interface." << endl + << " */" << endl; + else + os << "// Error handler callback interface." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("error-handler"), + L"::xsd::cxx::xml::error_handler< " + char_type + L" >"); + + os << endl; + } + + if (parsing || serialization) + { + if (doxygen) + os << "/**" << endl + << " * @brief DOM interaction." << endl + << " */" << endl; + else + os << "// DOM interaction." << endl + << "//" << endl; + + os << "namespace dom" + << "{"; + + // @@ Disregarding current naming convention by using the + // fixed name (even in C++11, template alias is not yet + // widely supported). + // + if (doxygen) + os << "/**" << endl + << " * @brief Automatic pointer for DOMDocument." << endl + << " */" << endl; + else + os << "// Automatic pointer for DOMDocument." << endl + << "//" << endl; + + if (std >= cxx_version::cxx11) + os << "using ::xsd::cxx::xml::dom::unique_ptr;"; + else + os << "using ::xsd::cxx::xml::dom::auto_ptr;"; + + os << endl; + + if (parsing) + { + if (!generate_xml_schema) + { + String g (L"XSD_CXX_TREE_TREE_NODE_KEY" + ns_name (n)); + + std::transform (g.begin (), g.end(), g.begin (), upcase); + g = escape (g); // Make it a C++ id. + + os << "#ifndef " << g << endl + << "#define " << g << endl; + } + + if (doxygen) + os << "/**" << endl + << " * @brief DOM user data key for back pointers to " << + "tree nodes." << endl + << " */" << endl; + else + os << "// DOM user data key for back pointers to tree nodes." << endl + << "//" << endl; + + os << "const XMLCh* const " << c.get<String> ("tree-node-key") << + " = ::xsd::cxx::tree::user_data_keys::node;"; + + if (!generate_xml_schema) + os << "#endif" << endl; + } + + os << "}"; // namespace dom + } + + if (element_map) + { + if (doxygen) + os << "//@cond" << endl + << endl; + + if (!generate_xml_schema) + { + String g (L"XSD_CXX_TREE_ELEMENT_MAP_INIT" + ns_name (n)); + + std::transform (g.begin (), g.end(), g.begin (), upcase); + g = escape (g); // Make it a C++ id. + + os << "#ifndef " << g << endl + << "#define " << g << endl; + } + + os << "static" << endl + << "const ::xsd::cxx::tree::element_map_init< " << + char_type << ", " << type_ << " >" << endl + << "_xsd_element_map_init;"; + + if (!generate_xml_schema) + os << "#endif" << endl; + + if (doxygen) + os << endl + << "//@endcond" << endl; + } + + Namespace::post (n); + + // Generate exports. + // + if (export_) + { + StringSet ns_set; + + for (StringList::const_iterator i (exports_.begin ()); + i != exports_.end (); ++i) + { + String const& e (*i); + + // 12 is to skip ::xsd::cxx:: + // + ns_set.insert (String (e, 12, e.rfind (':', e.find ('<')) - 13)); + } + + os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{"; + + for (StringSet::const_iterator i (ns_set.begin ()); + i != ns_set.end (); ++i) + { + String const& ns (*i); + String prefix (L"::xsd::cxx::" + ns); + + size_t n (1); + for (size_t b (0), e (ns.find (':')); ; n++) + { + os << "namespace " << String (ns, b, e) + << "{"; + + if (e == String::npos) + break; + + b = e + 2; + e = ns.find (':', b); + } + + for (StringList::const_iterator i (exports_.begin ()); + i != exports_.end (); ++i) + { + String const& e (*i); + String ens (e, 12, e.rfind (':', e.find ('<')) - 13); + + if (ns == ens) + { + String type (e, e.rfind (':', e.find ('<')) + 1); + os << "template class " << type_exp << type << ";"; + } + } + + while (n--) + os << "}"; + } + + os << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + } + + private: + typedef std::set<String> StringSet; + typedef std::vector<String> StringList; + + bool export_; + StringList exports_; + StringSet exports_set_; + String xs_ns_; + + Traversal::Names names_; + + String type_; + String simple_type_; + String string_; + String norm_string_; + String token_; + String nmtoken_; + String name_; + String ncname_; + String idref_; + String uri_; + String entity_; + + String double_; + String decimal_; + }; + } +} + +#endif // XSD_CXX_TREE_FUNDAMENTAL_HEADER_HXX diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx new file mode 100644 index 0000000..9782b4d --- /dev/null +++ b/xsd/cxx/tree/generator.cxx @@ -0,0 +1,1268 @@ +// file : xsd/cxx/tree/generator.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <vector> +#include <algorithm> +#include <iostream> +#include <fstream> + +#include <libcutl/re.hxx> +#include <libcutl/shared-ptr.hxx> + +#include <libcutl/compiler/code-stream.hxx> +#include <libcutl/compiler/cxx-indenter.hxx> +#include <libcutl/compiler/sloc-counter.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/generators/dependencies.hxx> + +#include <xsd/version.hxx> + +#include <xsd/cxx/tree/generator.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +#include <xsd/cxx/tree/counter.hxx> +#include <xsd/cxx/tree/validator.hxx> +#include <xsd/cxx/tree/name-processor.hxx> +#include <xsd/cxx/tree/order-processor.hxx> +#include <xsd/cxx/tree/polymorphism-processor.hxx> + +#include <xsd/cxx/tree/tree-forward.hxx> +#include <xsd/cxx/tree/tree-header.hxx> +#include <xsd/cxx/tree/tree-inline.hxx> +#include <xsd/cxx/tree/tree-source.hxx> + +#include <xsd/cxx/tree/parser-header.hxx> +#include <xsd/cxx/tree/parser-source.hxx> + +#include <xsd/cxx/tree/stream-header.hxx> +#include <xsd/cxx/tree/stream-source.hxx> + +#include <xsd/cxx/tree/serialization-header.hxx> +#include <xsd/cxx/tree/serialization-source.hxx> + +#include <xsd/cxx/tree/stream-insertion-header.hxx> +#include <xsd/cxx/tree/stream-insertion-source.hxx> +#include <xsd/cxx/tree/stream-extraction-source.hxx> + +#include <xsd/cxx/tree/options.hxx> + +using namespace std; +using namespace cutl; +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef std::wostream WideOutputStream; + +typedef std::wifstream WideInputFileStream; +typedef std::wofstream WideOutputFileStream; + +namespace CXX +{ + namespace + { + char const copyright_gpl[] = + "// Copyright (c) " XSD_COPYRIGHT ".\n" + "//\n" + "// This program was generated by CodeSynthesis XSD, an XML Schema to\n" + "// C++ data binding compiler.\n" + "//\n" + "// This program is free software; you can redistribute it and/or modify\n" + "// it under the terms of the GNU General Public License version 2 as\n" + "// published by the Free Software Foundation.\n" + "//\n" + "// This program is distributed in the hope that it will be useful,\n" + "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "// GNU General Public License for more details.\n" + "//\n" + "// You should have received a copy of the GNU General Public License\n" + "// along with this program; if not, write to the Free Software\n" + "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" + "//\n" + "// In addition, as a special exception, Code Synthesis gives permission\n" + "// to link this program with the Xerces-C++ library (or with modified\n" + "// versions of Xerces-C++ that use the same license as Xerces-C++), and\n" + "// distribute linked combinations including the two. You must obey the GNU\n" + "// General Public License version 2 in all respects for all of the code\n" + "// used other than Xerces-C++. If you modify this copy of the program, you\n" + "// may extend this exception to your version of the program, but you are\n" + "// not obligated to do so. If you do not wish to do so, delete this\n" + "// exception statement from your version.\n" + "//\n" + "// Furthermore, Code Synthesis makes a special exception for the Free/Libre\n" + "// and Open Source Software (FLOSS) which is described in the accompanying\n" + "// FLOSSE file.\n" + "//\n\n"; + + char const copyright_proprietary[] = + "// Copyright (c) " XSD_COPYRIGHT ".\n" + "//\n" + "// This program was generated by CodeSynthesis XSD, an XML Schema\n" + "// to C++ data binding compiler, in the Proprietary License mode.\n" + "// You should have received a proprietary license from Code Synthesis\n" + "// prior to generating this code. See the license text for conditions.\n" + "//\n\n"; + } + + void Tree::Generator:: + usage () + { + CXX::Tree::options::print_usage (wcout); + CXX::options::print_usage (wcout); + } + + namespace + { + void + open (WideInputFileStream& ifs, NarrowString const& path) + { + try + { + Path fs_path (path); + ifs.open (fs_path.string ().c_str (), + std::ios_base::in | std::ios_base::binary); + + if (!ifs.is_open ()) + { + wcerr << path.c_str () << ": error: unable to open in read mode" + << endl; + + throw Tree::Generator::Failed (); + } + } + catch (InvalidPath const&) + { + wcerr << "error: '" << path.c_str () << "' is not a valid " + << "filesystem path" << endl; + + throw Tree::Generator::Failed (); + } + } + + void + append (WideOutputFileStream& os, + NarrowString const& path, + WideInputFileStream& default_is) + { + using std::ios_base; + + if (path) + { + WideInputFileStream is; + open (is, path); + os << is.rdbuf (); + } + else if (default_is.is_open ()) + { + os << default_is.rdbuf (); + default_is.seekg (0, ios_base::beg); + } + } + + void + append (WideOutputFileStream& os, + NarrowStrings const& primary, + NarrowStrings const& def) + { + NarrowStrings const& v (primary.empty () ? def : primary); + + for (NarrowStrings::const_iterator i (v.begin ()), e (v.end ()); + i != e; ++i) + { + os << i->c_str () << endl; + } + } + } + + + size_t Tree::Generator:: + generate (Tree::options const& ops, + Schema& schema, + Path const& file_path, + bool fpt, + StringLiteralMap const& string_literal_map, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks) + { + using cutl::shared_ptr; + typedef cutl::re::regexsub Regex; + + typedef vector<Path> Paths; + typedef vector<shared_ptr<WideOutputFileStream> > WideOutputFileStreams; + + try + { + // Do option validation. + // + if (ops.parts () < 1) + { + wcerr << "error: invalid value for option --parts: " << + ops.parts () << endl; + throw Failed (); + } + + // Get counts. + // + Counts counts; + { + Counter counter; + counts = counter.count (ops, schema, file_path); + + /* + wcerr << "global type count: " << counts.global_types << endl; + wcerr << "global element count: " << counts.global_elements << endl; + wcerr << "generated global element count: " << + counts.generated_global_elements << endl; + + wcerr << "total complexity: " << counts.complexity_total << endl; + wcerr << "complexity vector size: " << counts.complexity.size () + << endl; + */ + } + + // Evaluate the graph for possibility of generating something useful. + // + { + Validator validator; + if (!validator.validate ( + ops, schema, file_path, disabled_warnings, counts)) + throw Failed (); + } + + bool gen_cxx (!ops.generate_dep_only () && !ops.file_list_only ()); + + // Process ordered types. + // + if (gen_cxx) + { + OrderProcessor proc; + if (!proc.process (ops, schema, file_path)) + throw Failed (); + } + + // Process names. + // + if (gen_cxx) + { + NameProcessor proc; + if (!proc.process (ops, schema, file_path, string_literal_map)) + throw Failed (); + } + + // Process polymorphic types. + // + if (gen_cxx && + ops.generate_polymorphic () && + !ops.polymorphic_type_all ()) + { + PolymorphismProcessor proc; + if (!proc.process (ops, schema, file_path, disabled_warnings)) + throw Failed (); + } + + // Parts. + // + size_t parts (ops.parts ()); + size_t units (counts.global_types + counts.generated_global_elements); + size_t units_per_part (units / parts); + + if (parts != 1 && units_per_part < 1) + { + wcerr << "error: too many parts specified: " << parts << endl; + throw Failed (); + } + + size_t complexity_per_part (counts.complexity_total / parts); + + + NarrowString parts_suffix (ops.parts_suffix ()); + + // + // + bool generate_xml_schema (ops.generate_xml_schema ()); + + // We could be compiling several schemas at once in which case + // handling of the --generate-xml-schema option gets tricky: we + // will need to rely on the presence of the --extern-xml-schema + // to tell us which (fake) schema file corresponds to XML Schema. + // + if (generate_xml_schema) + { + if (NarrowString name = ops.extern_xml_schema ()) + { + if (file_path.string () != name) + generate_xml_schema = false; + } + } + + bool header (true); + bool inline_ (ops.generate_inline () && !generate_xml_schema); + bool forward (ops.generate_forward () && !generate_xml_schema); + bool source (!generate_xml_schema); + bool gen_dep ((ops.generate_dep () || ops.generate_dep_only ()) && + !generate_xml_schema); + + if (ops.generate_dep_only () && generate_xml_schema) + { + wcerr << "error: no dependency information can be generated for " + "XML Schema header" << endl; + throw Failed (); + } + + if (gen_dep && fpt) + { + wcerr << "error: dependency generation not support in the " << + "file-per-type mode" << endl; + throw Failed (); + } + + // Generate code. + // + NarrowString name (file_path.leaf ().string ()); + + NarrowString hxx_suffix (ops.hxx_suffix ()); + NarrowString ixx_suffix (ops.ixx_suffix ()); + NarrowString cxx_suffix (ops.cxx_suffix ()); + NarrowString fwd_suffix (ops.fwd_suffix ()); + NarrowString dep_suffix (ops.dep_suffix ()); + + Regex hxx_expr (ops.hxx_regex ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" + : ops.hxx_regex ()); + + Regex ixx_expr (ops.ixx_regex ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#" + : ops.ixx_regex ()); + + Regex cxx_expr (ops.cxx_regex ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#" + : ops.cxx_regex ()); + + Regex fwd_expr (ops.fwd_regex ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#" + : ops.fwd_regex ()); + + // @@ This will blow up if --dep-file value contains backslashes (e.g., + // it's a Windows path). + // + Regex dep_expr ( + ops.dep_regex_specified () ? ops.dep_regex () : + ops.dep_file_specified () ? "#.+#" + ops.dep_file () + "#" : + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + dep_suffix + "#"); + + if (header && !hxx_expr.match (name)) + { + wcerr << "error: header expression '" << + hxx_expr.regex ().str ().c_str () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (inline_ && !ixx_expr.match (name)) + { + wcerr << "error: inline expression '" << + ixx_expr.regex ().str ().c_str () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (source && parts == 1 && !cxx_expr.match (name)) + { + wcerr << "error: source expression '" << + cxx_expr.regex ().str ().c_str () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (forward && !fwd_expr.match (name)) + { + wcerr << "error: forward expression '" << + fwd_expr.regex ().str ().c_str () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (gen_dep && !dep_expr.match (name)) + { + wcerr << "error: dependency expression '" << + dep_expr.regex ().str ().c_str () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + NarrowString hxx_name (header ? hxx_expr.replace (name) : NarrowString ()); + NarrowString ixx_name (inline_ ? ixx_expr.replace (name) : NarrowString ()); + NarrowString fwd_name (forward ? fwd_expr.replace (name) : NarrowString ()); + NarrowString dep_name (gen_dep ? dep_expr.replace (name) : NarrowString ()); + + Path hxx_path (hxx_name); + Path ixx_path (ixx_name); + Path fwd_path (fwd_name); + Path dep_path (dep_name != "-" ? dep_name : NarrowString ()); + Paths cxx_paths; + + if (source) + { + if (parts > 1) + { + for (size_t i (0); i < parts; ++i) + { + std::ostringstream os; + os << i; + + Regex expr ( + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + parts_suffix + os.str () + "$2#"); + + NarrowString part_name (expr.replace (name)); + + if (!cxx_expr.match (part_name)) + { + wcerr << "error: source expression '" << + cxx_expr.regex ().str ().c_str () << "' does not match '" << + part_name.c_str () << "'" << endl; + throw Failed (); + } + + cxx_paths.push_back (Path (cxx_expr.replace (part_name))); + } + } + else + cxx_paths.push_back (Path (cxx_expr.replace (name))); + } + + Path out_dir; + + if (NarrowString dir = ops.output_dir ()) + { + try + { + out_dir = Path (dir); + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + if (fpt && !generate_xml_schema) + { + // In the file-per-type mode the schema files are always local + // unless the user added the directory so that we propagate this + // to the output files. + // + Path fpt_dir (file_path.directory ()); + + if (!fpt_dir.empty ()) + out_dir /= fpt_dir; + } + + if (!out_dir.empty ()) + { + if (!hxx_path.empty ()) hxx_path = out_dir / hxx_path; + if (!ixx_path.empty ()) ixx_path = out_dir / ixx_path; + if (!fwd_path.empty ()) fwd_path = out_dir / fwd_path; + if (!dep_path.empty () && + !dep_path.absolute ()) dep_path = out_dir / dep_path; + + for (Paths::iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + *i = out_dir / *i; + } + + // + // + WideOutputFileStream hxx; + WideOutputFileStream ixx; + WideOutputFileStream fwd; + WideOutputFileStream depf; // See dep below. + WideOutputFileStreams cxx; + + // DEP + // + if (gen_dep) + { + if (!dep_path.empty ()) + { + depf.open (dep_path.string ().c_str (), ios_base::out); + + if (!depf.is_open ()) + { + wcerr << dep_path << ": error: unable to open in write mode" + << endl; + throw Failed (); + } + + unlinks.add (dep_path); + } + + // Note: not adding to file_list. + } + + WideOutputStream& dep (gen_dep && !dep_path.empty () ? depf : wcout); + + // FWD + // + if (forward) + { + if (gen_cxx) + { + fwd.open (fwd_path.string ().c_str (), ios_base::out); + + if (!fwd.is_open ()) + { + wcerr << fwd_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (fwd_path); + } + + file_list.push_back (fwd_path.string ()); + } + + // HXX + // + if (header) + { + if (gen_cxx) + { + hxx.open (hxx_path.string ().c_str (), ios_base::out); + + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); + } + + file_list.push_back (hxx_path.string ()); + } + + // IXX + // + if (inline_) + { + if (gen_cxx) + { + ixx.open (ixx_path.string ().c_str (), ios_base::out); + + if (!ixx.is_open ()) + { + wcerr << ixx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (ixx_path); + } + + file_list.push_back (ixx_path.string ()); + } + + // CXX + // + if (source) + { + for (Paths::iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + { + if (gen_cxx) + { + shared_ptr<WideOutputFileStream> s ( + new (shared) WideOutputFileStream ( + i->string ().c_str (), ios_base::out)); + + if (!s->is_open ()) + { + wcerr << *i << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + cxx.push_back (s); + unlinks.add (*i); + } + + file_list.push_back (i->string ()); + } + } + + // Print copyright and license. + // + char const* copyright ( + ops.proprietary_license () ? copyright_proprietary : copyright_gpl); + + if (gen_cxx && header) + hxx << copyright; + + if (gen_cxx && forward) + fwd << copyright; + + if (ops.generate_doxygen ()) + { + // Use native path format. + // + hxx << "/**" << endl + << " * @file" << endl + << " * @brief Generated from " << name.c_str () << "." << endl + << " */" << endl + << endl; + + } + + if (gen_cxx && inline_) + ixx << copyright; + + if (gen_cxx && source) + { + for (WideOutputFileStreams::iterator i (cxx.begin ()); + i != cxx.end (); ++i) + **i << copyright; + } + + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name (ops.prologue_file ()); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name (ops.epilogue_file ()); + + if (name) + open (epilogue, name); + } + + // SLOC counter. + // + size_t sloc_total (0); + bool show_sloc (ops.show_sloc ()); + + typedef + compiler::ostream_filter<compiler::cxx_indenter, wchar_t> + ind_filter; + + typedef + compiler::ostream_filter<compiler::sloc_counter, wchar_t> + sloc_filter; + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + NarrowString guard_prefix (ops.guard_prefix ()); + + if (!guard_prefix) + guard_prefix = file_path.directory ().string (); + + if (guard_prefix) + guard_prefix += '_'; + + // DEP + // + if (gen_dep) + { + NarrowString target; + NarrowStrings const& ts (ops.dep_target ()); + + if (!ts.empty ()) + { + for (NarrowStrings::const_iterator i (ts.begin ()); + i != ts.end (); ++i) + target += (target.empty () ? "" : " \\\n") + *i; + } + else + { + target = hxx_path.string (); + + if (forward) + target += " \\\n" + fwd_path.string (); + + if (inline_) + target += " \\\n" + ixx_path.string (); + + for (Paths::iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + target += " \\\n" + i->string (); + + if (!dep_path.empty ()) + target += " \\\n" + dep_path.string (); + } + + dep << target.c_str () << ':'; + + XSDFrontend::Generators::Dependencies gen; + Paths prq (gen.generate (schema, file_path)); + + for (Paths::iterator i (prq.begin ()); i != prq.end (); ++i) + dep << " \\" << endl + << " " << *i; + + dep << endl; + + // If requested, generate phony rules for included/imported schemas + // but not the main file which is the first in the list. + // + if (ops.dep_phony () && prq.size () > 1) + { + for (Paths::iterator i (prq.begin () + 1); i != prq.end (); ++i) + dep << endl + << *i << ':' << endl; + } + } + + // FWD + // + if (gen_cxx && forward) + { + Context ctx (fwd, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + sloc_filter sloc (fwd); + + // Guard + // + String guard (guard_expr.replace (guard_prefix + fwd_name)); + guard = ctx.escape (guard); // make a c++ id + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + fwd << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + if (ctx.std >= cxx_version::cxx11) + { + fwd << "#ifndef XSD_CXX11" << endl + << "#define XSD_CXX11" << endl + << "#endif" << endl + << endl; + } + + if (ctx.char_type == L"char") + { + fwd << "#ifndef XSD_USE_CHAR" << endl + << "#define XSD_USE_CHAR" << endl + << "#endif" << endl + << endl; + + fwd << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl + << "#define XSD_CXX_TREE_USE_CHAR" << endl + << "#endif" << endl + << endl; + } + else if (ctx.char_type == L"wchar_t") + { + fwd << "#ifndef XSD_USE_WCHAR" << endl + << "#define XSD_USE_WCHAR" << endl + << "#endif" << endl + << endl; + + fwd << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl + << "#define XSD_CXX_TREE_USE_WCHAR" << endl + << "#endif" << endl + << endl; + } + + // Copy prologue. + // + fwd << "// Begin prologue." << endl + << "//" << endl; + + append (fwd, ops.fwd_prologue (), ops.prologue ()); + append (fwd, ops.fwd_prologue_file (), prologue); + + fwd << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + fwd << "#include <xsd/cxx/version.hxx>" << endl + << endl + << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + fwd << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Generate. + // + { + ind_filter ind (fwd); // We don't want to indent prologues/epilogues. + generate_forward (ctx); + } + + fwd << "#include <xsd/cxx/post.hxx>" << endl + << endl; + + // Copy epilogue. + // + fwd << "// Begin epilogue." << endl + << "//" << endl; + + append (fwd, ops.fwd_epilogue_file (), epilogue); + append (fwd, ops.fwd_epilogue (), ops.epilogue ()); + + fwd << "//" << endl + << "// End epilogue." << endl + << endl; + + fwd << "#endif // " << guard << endl; + + if (show_sloc) + wcerr << fwd_path << ": " << sloc.stream ().count () << endl; + + sloc_total += sloc.stream ().count (); + } + + // HXX + // + if (gen_cxx && header) + { + Context ctx (hxx, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + sloc_filter sloc (hxx); + + // Guard + // + String guard (guard_expr.replace (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // make a c++ id + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + hxx << "#ifndef " << guard << endl + << "#define " << guard << endl + << endl; + + if (!forward) + { + if (ctx.std >= cxx_version::cxx11) + { + hxx << "#ifndef XSD_CXX11" << endl + << "#define XSD_CXX11" << endl + << "#endif" << endl + << endl; + } + + if (ctx.char_type == L"char") + { + hxx << "#ifndef XSD_USE_CHAR" << endl + << "#define XSD_USE_CHAR" << endl + << "#endif" << endl + << endl; + + hxx << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl + << "#define XSD_CXX_TREE_USE_CHAR" << endl + << "#endif" << endl + << endl; + } + else if (ctx.char_type == L"wchar_t") + { + hxx << "#ifndef XSD_USE_WCHAR" << endl + << "#define XSD_USE_WCHAR" << endl + << "#endif" << endl + << endl; + + hxx << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl + << "#define XSD_CXX_TREE_USE_WCHAR" << endl + << "#endif" << endl + << endl; + } + } + else if (!generate_xml_schema) + { + // Generate it before the prologue so that we get the above + // defines. + // + hxx << "#include " << ctx.process_include_path (fwd_name) + << endl << endl; + } + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append (hxx, ops.hxx_prologue (), ops.prologue ()); + append (hxx, ops.hxx_prologue_file (), prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + hxx << "#include <xsd/cxx/config.hxx>" << endl + << endl + << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + hxx << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Generate. + // + { + ind_filter ind (hxx); // We don't want to indent prologues/epilogues. + + if (!generate_xml_schema && !forward) + generate_forward (ctx); + + generate_tree_header (ctx); + + if (!generate_xml_schema) + { + if (ops.generate_ostream ()) + generate_stream_header (ctx); + + if (!ops.generate_element_type () && !ops.suppress_parsing ()) + generate_parser_header (ctx); + + if (ops.generate_serialization ()) + generate_serialization_header (ctx); + + if (!ops.generate_insertion ().empty ()) + generate_stream_insertion_header (ctx); + } + } + + hxx << "#include <xsd/cxx/post.hxx>" << endl + << endl; + + // Copy epilogue. + // + // Note that it goes before the inline file in case it defines + // something (such as a custom type) which is needed by this file. + // And if something in the epilogue needs something from the inline + // file, then it should be the inline rather than header epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, ops.hxx_epilogue_file (), epilogue); + append (hxx, ops.hxx_epilogue (), ops.epilogue ()); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + if (inline_) + { + hxx << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << "#include " << ctx.process_include_path (ixx_name) << endl + << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + wcerr << hxx_path << ": " << sloc.stream ().count () << endl; + + sloc_total += sloc.stream ().count (); + } + + + // IXX + // + if (gen_cxx && inline_) + { + Context ctx (ixx, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + sloc_filter sloc (ixx); + + // Guard + // + String guard (guard_expr.replace (guard_prefix + ixx_name)); + guard = ctx.escape (guard); // make a c++ id + std::transform (guard.begin (), guard.end(), guard.begin (), upcase); + + ixx << "#ifndef " << guard.c_str () << endl + << "#define " << guard.c_str () << endl + << endl; + + // Copy prologue. + // + ixx << "// Begin prologue." << endl + << "//" << endl; + + append (ixx, ops.ixx_prologue (), ops.prologue ()); + append (ixx, ops.ixx_prologue_file (), prologue); + + ixx << "//" << endl + << "// End prologue." << endl + << endl; + + ixx << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Generate. + // + { + ind_filter ind (ixx); // We don't want to indent prologues/epilogues. + generate_tree_inline (ctx, 1, 0); + } + + ixx << "#include <xsd/cxx/post.hxx>" << endl + << endl; + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, ops.ixx_epilogue_file (), epilogue); + append (ixx, ops.ixx_epilogue (), ops.epilogue ()); + + ixx << "//" << endl + << "// End epilogue." << endl + << endl; + + ixx << "#endif // " << guard.c_str () << endl; + + if (show_sloc) + wcerr << ixx_path << ": " << sloc.stream ().count () << endl; + + sloc_total += sloc.stream ().count (); + } + + // CXX + // + if (gen_cxx && source) + { + size_t first_unit (0); // First unit in the current part. + + for (size_t part (0); part < parts; ++part) + { + // Figure out the range of units for this part. + // + size_t last_unit (first_unit); + + if (units != 0) + { + size_t complexity (counts.complexity[last_unit]); + + while (complexity < complexity_per_part) + { + // Make sure there will be at least one unit for each part left. + // + if ((last_unit + 1) >= units || + (units - (last_unit + 1) - 1) < (parts - part - 1)) + break; + + // Check if the increase in complexity should be kept in this + // part or moved to the next. + // + size_t new_complexity ( + complexity + counts.complexity[last_unit + 1]); + + if (new_complexity > complexity_per_part) + { + if ((new_complexity - complexity_per_part) > + (counts.complexity[last_unit + 1] / 2)) + break; + } + + last_unit++; + complexity = new_complexity; + } + + if (part + 1 == parts) + { + // Last part. + // + last_unit = units - 1; + } + } + + // + // + size_t first (first_unit); + size_t last (last_unit); + + first_unit = last_unit + 1; + + //wcerr << "[" << first << ", " << last << "]: " << complexity + // << endl; + + WideOutputFileStream& os (*cxx[part]); + + Context ctx (os, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + sloc_filter sloc (os); + + // Copy prologue. + // + os << "// Begin prologue." << endl + << "//" << endl; + + append (os, ops.cxx_prologue (), ops.prologue ()); + append (os, ops.cxx_prologue_file (), prologue); + + os << "//" << endl + << "// End prologue." << endl + << endl; + + os << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + os << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + // Generate. + // + { + // We don't want to indent prologues/epilogues. + // + ind_filter ind (os); + + if (!inline_) + generate_tree_inline (ctx, first, last); + + generate_tree_source (ctx, first, last); + + if (ops.generate_ostream ()) + generate_stream_source (ctx, first, last); + + if (!ops.generate_element_type () && !ops.suppress_parsing ()) + generate_parser_source (ctx, first, last); + + if (ops.generate_serialization ()) + generate_serialization_source (ctx, first, last); + + if (!ops.generate_extraction ().empty ()) + generate_stream_extraction_source (ctx); + + if (!ops.generate_insertion ().empty ()) + generate_stream_insertion_source (ctx); + } + + os << "#include <xsd/cxx/post.hxx>" << endl + << endl; + + // Copy epilogue. + // + os << "// Begin epilogue." << endl + << "//" << endl; + + append (os, ops.cxx_epilogue_file (), epilogue); + append (os, ops.cxx_epilogue (), ops.epilogue ()); + + os << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + wcerr << cxx_paths[part] << ": " << sloc.stream ().count () + << endl; + + sloc_total += sloc.stream ().count (); + } + } + + return sloc_total; + } + catch (UnrepresentableCharacter const& e) + { + wcerr << "error: character at position " << e.position () << " " + << "in string '" << e.string () << "' is unrepresentable in " + << "the target encoding" << endl; + + wcerr << "info: use the --custom-literals option to provide custom " + << "string literals mapping" << endl; + + throw Failed (); + } + catch (NoNamespaceMapping const& e) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: unable to map XML Schema namespace '" << e.ns () + << "' to C++ namespace" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: use the --namespace-map or --namespace-regex option " + << "to provide custom mapping" << endl; + + throw Failed (); + } + catch (InvalidNamespaceMapping const& e) + { + wcerr << "error: invalid XML to C++ namespace mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (InvalidCustomTypeMapping const& e) + { + wcerr << "error: invalid custom type mapping specified: " + << "'" << e.mapping () << "': " << e.reason () << endl; + + throw Failed (); + } + catch (cutl::re::format const& e) + { + wcerr << "error: invalid regex: '" << + e.regex ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (cutl::re::wformat const& e) + { + wcerr << "error: invalid regex: '" << + e.regex () << "': " << e.description ().c_str () << endl; + + throw Failed (); + } + } +} diff --git a/xsd/cxx/tree/generator.hxx b/xsd/cxx/tree/generator.hxx new file mode 100644 index 0000000..a9b96fe --- /dev/null +++ b/xsd/cxx/tree/generator.hxx @@ -0,0 +1,44 @@ +// file : xsd/cxx/tree/generator.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_GENERATOR_HXX +#define XSD_CXX_TREE_GENERATOR_HXX + +#include <libxsd-frontend/semantic-graph/elements.hxx> // Path +#include <libxsd-frontend/semantic-graph/schema.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/literal-map.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + class Generator + { + public: + static void + usage (); + + struct Failed {}; + + static size_t + generate (options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + bool file_per_type, + StringLiteralMap const&, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + private: + Generator (); + }; + } +} + +#endif // XSD_CXX_TREE_GENERATOR_HXX diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx new file mode 100644 index 0000000..325870a --- /dev/null +++ b/xsd/cxx/tree/name-processor.cxx @@ -0,0 +1,2427 @@ +// file : xsd/cxx/tree/name-processor.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <map> +#include <vector> +#include <sstream> +#include <iostream> + +#include <libcutl/re.hxx> + +#include <xsd/cxx/tree/default-value.hxx> +#include <xsd/cxx/tree/name-processor.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + // + // + typedef set<String> NameSet; + + class Context: public Tree::Context + { + public: + struct Failed {}; + + Context (Tree::options const& ops, + Counts const& counts, + bool generate_xml_schema, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + StringLiteralMap const& map) + : Tree::Context (std::wcerr, + root, + path, + ops, + counts, + generate_xml_schema, + &map, + 0, + 0, + 0), + global_type_names (global_type_names_), + global_element_names (global_element_names_), + detach (ops.generate_detach ()), + type_regex (type_regex_), + accessor_regex (accessor_regex_), + one_accessor_regex (one_accessor_regex_), + opt_accessor_regex (opt_accessor_regex_), + seq_accessor_regex (seq_accessor_regex_), + modifier_regex (modifier_regex_), + one_modifier_regex (one_modifier_regex_), + opt_modifier_regex (opt_modifier_regex_), + seq_modifier_regex (seq_modifier_regex_), + parser_regex (parser_regex_), + serializer_regex (serializer_regex_), + const_regex (const_regex_), + enumerator_regex (enumerator_regex_), + element_type_regex (element_type_regex_) + { + NarrowString tn (options.type_naming ()); + NarrowString fn (options.function_naming ()); + + // Type name regex. + // + { + // Predefined rules. The most frequently used come last: global + // names, two components (<name>,type), three components + // (<name>,const,iterator), and one component (value in enum). + // + if (tn == "knr") + { + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/$1/"); + + /* + type_regex.push_back ("/([^,]+)/$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/[^ ]* (.+)/$1/"); + */ + } + else + { + // Upper camel case or Java. + // + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/\\u$1/"); + + /* + type_regex.push_back ("/([^,]+)/\\u$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/[^ ]* (.+)/\\u$1/"); + */ + + } + + compile_regex (options.type_regex (), type_regex, "type"); + } + + // Accessor name regex. + // + { + // Predefined rules. The most frequently used come last: one + // component, three components (<name>,default,value) and two + // component (dom,document). + // + if (fn == "knr") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + accessor_regex.push_back ("/([^,]+)/$1/"); + } + else if (fn == "lcc") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/\\l$1/"); + } + else if (fn == "ucc") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/\\u$1/"); + } + else + { + // Java: add get. + // + accessor_regex.push_back ("/([^,]+),([^,]+)/get\\u$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/get\\u$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/get\\u$1/"); + } + + compile_regex (options.accessor_regex (), + accessor_regex, + "accessor"); + + compile_regex (options.one_accessor_regex (), + one_accessor_regex, + "one accessor"); + + compile_regex (options.opt_accessor_regex (), + opt_accessor_regex, + "optional accessor"); + + compile_regex (options.seq_accessor_regex (), + seq_accessor_regex, + "sequence accessor"); + } + + // Modifier name regex. + // + { + if (fn == "knr") + { + // any,attribute + // + modifier_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + } + else if (fn == "lcc") + { + modifier_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + modifier_regex.push_back ("/([^,]+)/\\l$1/"); + } + else if (fn == "ucc") + { + modifier_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + modifier_regex.push_back ("/([^,]+)/\\u$1/"); + } + else + { + // Java: add set. + // + modifier_regex.push_back ("/([^,]+),([^,]+)/set\\u$1\\u$2/"); + modifier_regex.push_back ("/([^,]+)/set\\u$1/"); + modifier_regex.push_back ("/detach,([^,]+)/detach\\u$1/"); + } + + compile_regex (options.modifier_regex (), + modifier_regex, + "modifier"); + + compile_regex (options.one_modifier_regex (), + one_modifier_regex, + "one modifier"); + + compile_regex (options.opt_modifier_regex (), + opt_modifier_regex, + "optional modifier"); + + compile_regex (options.seq_modifier_regex (), + seq_modifier_regex, + "sequence modifier"); + } + + // Parser name regex. + // + { + if (fn == "lcc") + { + parser_regex.push_back ("/(.+)/\\l$1/"); + } + else if (fn == "ucc") + { + parser_regex.push_back ("/(.+)/\\u$1/"); + } + else if (fn == "java") + { + // Java: add parse. + // + parser_regex.push_back ("/(.+)/parse\\u$1/"); + } + + compile_regex (options.parser_regex (), parser_regex, "parser"); + } + + // Serializer name regex. + // + { + if (fn == "lcc") + { + serializer_regex.push_back ("/(.+)/\\l$1/"); + } + else if (fn == "ucc") + { + serializer_regex.push_back ("/(.+)/\\u$1/"); + } + else if (fn == "java") + { + // Java: add serialize. + // + serializer_regex.push_back ("/(.+)/serialize\\u$1/"); + } + + compile_regex (options.serializer_regex (), + serializer_regex, + "serializer"); + } + + // Const regex. + // + { + if (fn == "knr") + { + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + } + else if (fn == "lcc") + { + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1_\\u$2_\\u$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + } + else if (fn == "ucc") + { + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1_\\u$2_\\u$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + } + else + { + // Java: all uppercase. + // + const_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\U$1_$2_$3/"); + const_regex.push_back ("/([^,]+),([^,]+)/\\U$1_$2/"); + } + + compile_regex (options.const_regex (), const_regex, "const"); + } + + // Enumerator name regex. + // + { + // By default map an empty enumerator to the 'empty' word. + // + enumerator_regex.push_back ("/^$/empty/"); + + compile_regex (options.enumerator_regex (), + enumerator_regex, + "enumerator"); + } + + // Element type regex. + // + compile_regex (options.element_type_regex (), + element_type_regex, + "element_type"); + } + + protected: + Context (Context& c) + : Tree::Context (c), + global_type_names (c.global_type_names), + global_element_names (c.global_element_names), + detach (c.detach), + type_regex (c.type_regex), + accessor_regex (c.accessor_regex), + one_accessor_regex (c.one_accessor_regex), + opt_accessor_regex (c.opt_accessor_regex), + seq_accessor_regex (c.seq_accessor_regex), + modifier_regex (c.modifier_regex), + one_modifier_regex (c.one_modifier_regex), + opt_modifier_regex (c.opt_modifier_regex), + seq_modifier_regex (c.seq_modifier_regex), + parser_regex (c.parser_regex), + serializer_regex (c.serializer_regex), + const_regex (c.const_regex), + enumerator_regex (c.enumerator_regex), + element_type_regex (c.element_type_regex) + { + } + + public: + typedef cutl::re::wregexsub Regex; + typedef cutl::re::wformat RegexFormat; + + struct RegexVector: vector<Regex> + { + void + push_back (String const& r) + { + vector<Regex>::push_back (Regex (r)); + } + }; + + String + process_regex (String const& name, + RegexVector const& rv, + String const& id) + { + bool trace (options.name_regex_trace ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::const_reverse_iterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (name)) + { + String r (i->replace (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& name, + RegexVector const& primary, + RegexVector const& backup, + String const& id) + { + bool trace (options.name_regex_trace ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::const_reverse_iterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (name)) + { + String r (i->replace (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::const_reverse_iterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (name)) + { + String r (i->replace (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& ns, + String const& name, + RegexVector const& rv, + String const& id) + { + String s (ns + L' ' + name); + bool trace (options.name_regex_trace ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::const_reverse_iterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (s)) + { + String r (i->replace (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + String + process_regex (String const& ns, + String const& name, + RegexVector const& primary, + RegexVector const& backup, + String const& id) + { + String s (ns + L' ' + name); + bool trace (options.name_regex_trace ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::const_reverse_iterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (s)) + { + String r (i->replace (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::const_reverse_iterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->regex () << "' : "; + + if (i->match (s)) + { + String r (i->replace (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + public: + String + find_name (String const& base_name, + NameSet& set, + bool insert = true) + { + String name (base_name); + + for (size_t i (1); set.find (name) != set.end (); ++i) + { + std::wostringstream os; + os << i; + name = base_name + os.str (); + } + + if (insert) + set.insert (name); + + return name; + } + + private: + void + compile_regex (NarrowStrings const& sv, + RegexVector& rv, + String const& id) + { + for (NarrowStrings::const_iterator i (sv.begin ()); i != sv.end (); + ++i) + { + try + { + rv.push_back (*i); + } + catch (RegexFormat const& e) + { + os << "error: invalid " << id << " name regex: '" << + e.regex () << "': " << e.description ().c_str () << endl; + + throw Failed (); + } + } + } + + private: + map<String, NameSet> global_type_names_; + map<String, NameSet> global_element_names_; + + RegexVector type_regex_; + RegexVector accessor_regex_; + RegexVector one_accessor_regex_; + RegexVector opt_accessor_regex_; + RegexVector seq_accessor_regex_; + RegexVector modifier_regex_; + RegexVector one_modifier_regex_; + RegexVector opt_modifier_regex_; + RegexVector seq_modifier_regex_; + RegexVector parser_regex_; + RegexVector serializer_regex_; + RegexVector const_regex_; + RegexVector enumerator_regex_; + RegexVector element_type_regex_; + + public: + map<String, NameSet>& global_type_names; + map<String, NameSet>& global_element_names; + + bool detach; + + RegexVector& type_regex; + RegexVector& accessor_regex; + RegexVector& one_accessor_regex; + RegexVector& opt_accessor_regex; + RegexVector& seq_accessor_regex; + RegexVector& modifier_regex; + RegexVector& one_modifier_regex; + RegexVector& opt_modifier_regex; + RegexVector& seq_modifier_regex; + RegexVector& parser_regex; + RegexVector& serializer_regex; + RegexVector& const_regex; + RegexVector& enumerator_regex; + RegexVector& element_type_regex; + }; + + // + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual void + traverse (Type& e) + { + // Process the name with enumerator name regex. + // + String name ( + process_regex (e.name (), enumerator_regex, L"enumerator")); + + // Escape and unclash. + // + name = find_name (escape (name), set_); + e.context ().set ("name", name); + } + + private: + NameSet& set_; + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + // Use processed name. + // + String name (e.context ().get<String> ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (e, name) && !name) + return; + + NameSet enum_set; + enum_set.insert (name); + + Enumerator enumerator (*this, enum_set); + Traversal::Names names (enumerator); + + Traversal::Enumeration::names (e, names); + + // Assign name to the value type. First process the name + // with type name regex. + // + String value_name ( + escape (process_regex ("value", type_regex, L"type"))); + e.context ().set ("value", find_name (value_name, enum_set)); + } + }; + + // + // + struct PrimaryMember: Traversal::Member, Context + { + PrimaryMember (Context& c, NameSet& name_set, NameSet& stem_set) + : Context (c), name_set_ (name_set), stem_set_ (stem_set) + { + } + + virtual void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + String stem (find_name (m.name (), stem_set_)); + + m.context ().set ("stem", stem); + m.context ().set ("name", + find_name (escape (stem), name_set_, false)); + } + + private: + NameSet& name_set_; + NameSet& stem_set_; + }; + + // + // + struct DerivedMember: Traversal::Member, Context + { + DerivedMember (Context& c, NameSet& name_set) + : Context (c), name_set_ (name_set) + { + } + + virtual void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (m.scope ())); + + size_t max (Tree::Context::max (m)); + size_t min (Tree::Context::min (m)); + + String const& s (m.context ().get<String> ("stem")); + String const& b (m.context ().get<String> ("name")); + + bool def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + // Accessors/modifiers. Note that we postpone inserting + // the names into the name_set to avoid over-escaping. + // + String an, mn; + + if (max != 1) + { + an = find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + name_set_, + false); + } + else if (min == 0 && !def_attr) + { + an = find_name ( + escape (process_regex (s, + opt_accessor_regex, + accessor_regex, + L"optional accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + opt_modifier_regex, + modifier_regex, + L"optional modifier")), + name_set_, + false); + } + else + { + an = find_name ( + escape (process_regex (s, + one_accessor_regex, + accessor_regex, + L"one accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_, + false); + } + + m.context ().set ("aname", an); + m.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Detach. + // + if (detach && max == 1 && (min == 1 || def_attr)) + { + String dn (find_name ( + escape (process_regex (L"detach," + s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_)); + + m.context ().set ("dname", dn); + } + + // Types. + // + m.context ().set ( + "type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "traits", + find_name ( + escape (process_regex (s + L",traits", type_regex, L"type")), + name_set_)); + + if (max != 1) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + } + else if (min == 0 && !def_attr) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",optional", type_regex, L"type")), + name_set_)); + } + + // Data member. + // + m.context ().set ("member", find_name (b + L"_", name_set_)); + + // Default value. + // + if (m.default_p ()) + { + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + String an ( + escape ( + process_regex ( + s + L",default,value", accessor_regex, L"accessor"))); + + m.context ().set ("default-value", find_name (an, name_set_)); + + bool lit (false); + { + IsLiteralValue test (lit); + test.dispatch (m.type ()); + } + + if (!lit) + { + m.context ().set ( + "default-value-member", + find_name (b + L"_default_value_", name_set_)); + } + } + } + + // Element id. + // + if (m.is_a<SemanticGraph::Element> () && ordered_p (c)) + { + String id ( + escape ( + process_regex ( + s + L",id", const_regex, L"const"))); + + m.context ().set ("ordered-id-name", find_name (id, name_set_)); + } + } + + private: + NameSet& name_set_; + }; + + + // + // + struct Any: Traversal::Any, Traversal::AnyAttribute, Context + { + Any (Context& c, + NameSet& name_set, + NameSet& stem_set, + bool& has_wildcard) + : Context (c), + name_set_ (name_set), + stem_set_ (stem_set), + has_wildcard_ (has_wildcard) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + size_t max (Tree::Context::max (a)); + size_t min (Tree::Context::min (a)); + + String s (find_name (L"any", stem_set_)); + + String b (find_name (escape (s), name_set_, false)); + a.context ().set ("name", b); + + // Accessors/modifiers. Note that we postpone inserting the + // names into the name_set to avoid over-escaping. + // + String an, mn; + + if (max != 1) + { + an = find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + name_set_, + false); + } + else if (min == 0) + { + an = find_name ( + escape (process_regex (s, + opt_accessor_regex, + accessor_regex, + L"optional accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + opt_modifier_regex, + modifier_regex, + L"optional modifier")), + name_set_, + false); + } + else + { + an = find_name ( + escape (process_regex (s, + one_accessor_regex, + accessor_regex, + L"one accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_, + false); + } + + a.context ().set ("aname", an); + a.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Types + // + if (max != 1) + { + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + } + else if (min == 0) + { + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",optional", type_regex, L"type")), + name_set_)); + } + + // Data member. + // + a.context ().set ("member", find_name (b + L"_", name_set_)); + + // Wildcard id. + // + if (ordered_p (c)) + { + String id ( + escape ( + process_regex ( + s + L",id", const_regex, L"const"))); + + a.context ().set ("ordered-id-name", find_name (id, name_set_)); + } + + if (!has_wildcard_) + has_wildcard_ = true; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String s (find_name (L"any,attribute", stem_set_)); + + String b (find_name (escape (s), name_set_, false)); + a.context ().set ("name", b); + + // Accessors/modifiers. Note that we postpone inserting the + // names into the name_set to avoid over-escaping. + // + String an ( + find_name ( + escape (process_regex (s, accessor_regex, L"accessor")), + name_set_, + false)); + + String mn ( + find_name ( + escape (process_regex (s, modifier_regex, L"modifier")), + name_set_, + false)); + + a.context ().set ("aname", an); + a.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Types + // + a.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",set", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + a.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + + // Data member. + // + a.context ().set ("member", find_name (b + L"_", name_set_)); + + if (!has_wildcard_) + has_wildcard_ = true; + } + + private: + NameSet& name_set_; + NameSet& stem_set_; + bool& has_wildcard_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + SemanticGraph::Context& ctx (c.context ()); + + // We leave this set around to allow other mappings to use + // this information. + // + ctx.set ("cxx-tree-name-processor-stem-set", NameSet ()); + ctx.set ("cxx-tree-name-processor-member-set", NameSet ()); + + // Use processed name. + // + String name (ctx.get<String> ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (c, name) && !name) + return; + + NameSet& stem_set ( + ctx.get<NameSet> ("cxx-tree-name-processor-stem-set")); + + NameSet& member_set ( + ctx.get<NameSet> ("cxx-tree-name-processor-member-set")); + + stem_set.insert (c.name ()); + member_set.insert (name); + + // Add our base's stems and members to the initial list. + // + if (c.inherits_p ()) + { + // @@ What if this types name is the same as one of base's + // members? + // + SemanticGraph::Type& base (c.inherits ().base ()); + + if (base.is_a<SemanticGraph::Complex> () && + !base.is_a<SemanticGraph::Enumeration> ()) + { + if (!base.context ().count ( + "cxx-tree-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_stem_set ( + base.context ().get<NameSet> ( + "cxx-tree-name-processor-stem-set")); + + stem_set.insert (base_stem_set.begin (), base_stem_set.end ()); + + NameSet const& base_member_set ( + base.context ().get<NameSet> ( + "cxx-tree-name-processor-member-set")); + + member_set.insert (base_member_set.begin (), + base_member_set.end ()); + } + } + + // First assign the "primary" names. + // + { + PrimaryMember member (*this, member_set, stem_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Derived names for members. + // + { + DerivedMember member (*this, member_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Names for the mixed content. + // + if (mixed_p (c)) + { + // Check if we already have the mixed content down inheritance + // hierarchy. + // + using SemanticGraph::Complex; + + for (Complex* p (&c); p->inherits_p ();) + { + if (Complex* b = dynamic_cast<Complex*> ( + &p->inherits ().base ())) + { + if (mixed_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("mixed-type", bctx.get<String> ("mixed-type")); + ctx.set ("mixed-const-iterator", + bctx.get<String> ("mixed-const-iterator")); + ctx.set ("mixed-ordered-id-name", + bctx.get<String> ("mixed-ordered-id-name")); + ctx.set ("mixed-aname", bctx.get<String> ("mixed-aname")); + ctx.set ("mixed-member", bctx.get<String> ("mixed-member")); + ctx.set ("mixed-in-base", true); + break; + } + + p = b; + } + else + break; + } + + // If not, set up the names. + // + if (!ctx.count ("mixed-in-base")) + { + String s (find_name (L"text,content", stem_set)); + String n (find_name (escape (s), member_set, false)); + + String an (find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + member_set, + false)); + + String mn (find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + member_set, + false)); + + ctx.set ("mixed-aname", an); + ctx.set ("mixed-mname", mn); + + member_set.insert (name); + + if (an != n) + member_set.insert (an); + + if (mn != n && mn != an) + member_set.insert (mn); + + // Types. + // + ctx.set ( + "mixed-type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + member_set)); + + ctx.set ( + "mixed-const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + member_set)); + + // Text content id. + // + ctx.set ( + "mixed-ordered-id-name", + find_name ( + escape ( + process_regex (s + L",id", const_regex, L"const")), + member_set)); + + // Data member. + // + ctx.set ("mixed-member", find_name (n + L"_", member_set)); + } + } + + // Names for wildcards. + // + if (options.generate_wildcard ()) + { + bool has_wildcard (false); + Any any (*this, member_set, stem_set, has_wildcard); + Traversal::Names names (any); + Complex::names (c, names); + + // Assign names for dom_document. + // + if (has_wildcard) + { + // Check if we already have dom_document down inheritance + // hierarchy. + // + for (SemanticGraph::Complex* p (&c); p->inherits_p ();) + { + if (SemanticGraph::Complex* base = + dynamic_cast<SemanticGraph::Complex*> ( + &p->inherits ().base ())) + { + if (base->context ().count ("dom-document")) + { + c.context ().set ( + "dom-document", + base->context ().get<String> ("dom-document")); + break; + } + + p = base; + } + else + break; + } + + // If not, set up the names. + // + if (!c.context ().count ("dom-document")) + { + String stem (find_name (L"dom,document", stem_set)); + + String an ( + escape ( + process_regex (stem, accessor_regex, L"accessor"))); + + c.context ().set ("dom-document", find_name (an, member_set)); + + c.context ().set ( + "dom-document-member", + find_name (escape (stem + L"_"), member_set)); + } + } + } + + // Names for the order container. + // + if (ordered_p (c)) + { + // Check if we already have the order container down + // inheritance hierarchy. + // + using SemanticGraph::Complex; + + for (Complex* p (&c); p->inherits_p ();) + { + if (Complex* b = dynamic_cast<Complex*> ( + &p->inherits ().base ())) + { + if (ordered_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("order-type", bctx.get<String> ("order-type")); + ctx.set ("order-const-iterator", + bctx.get<String> ("order-const-iterator")); + ctx.set ("order-aname", bctx.get<String> ("order-aname")); + ctx.set ("order-member", bctx.get<String> ("order-member")); + ctx.set ("order-in-base", true); + break; + } + + p = b; + } + else + break; + } + + // If not, set up the names. + // + if (!ctx.count ("order-in-base")) + { + String s (find_name (L"content,order", stem_set)); + String n (find_name (escape (s), member_set, false)); + + String an (find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + member_set, + false)); + + String mn (find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + member_set, + false)); + + ctx.set ("order-aname", an); + ctx.set ("order-mname", mn); + + member_set.insert (name); + + if (an != n) + member_set.insert (an); + + if (mn != n && mn != an) + member_set.insert (mn); + + // Types. + // + ctx.set ( + "order-type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + member_set)); + + ctx.set ( + "order-const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + member_set)); + + // Data member. + // + ctx.set ("order-member", find_name (n + L"_", member_set)); + } + } + } + }; + + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual void + traverse (SemanticGraph::Type& t) + { + // Process the name with type name regex. + // + String name (process_regex ( + namespace_ (t).name (), + t.name (), + type_regex, + L"type")); + + // Escape and unclash. + // + name = find_name (escape (name), set_); + t.context ().set ("name", name); + + // Also add renamed name if any. + // + if (renamed_type (t, name) && name) + set_.insert (name); + } + + private: + NameSet& set_; + }; + + + // + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c, + NameSet const& type_set, + NameSet& element_set) + : GlobalElementBase (c), + Context (c), + type_set_ (type_set), + element_set_ (element_set) + { + } + + virtual void + traverse (Type& e) + { + // First we need to figure out if we need to process this + // global element. + // + if (!generate_p (e)) + return; + + if (options.generate_element_type ()) + { + SemanticGraph::Context& ec (e.context ()); + + String name; + + if (doc_root_p (e)) + { + name = find_name ( + escape ( + process_regex ( + namespace_ (e).name (), + e.name (), + element_type_regex, + type_regex, + L"element type"))); + + // Assign inner names. + // + NameSet set; + set.insert (name); + + ec.set ( + "type", + Context::find_name ( + escape (process_regex (L"value,type", type_regex, L"type")), + set)); + + ec.set ( + "traits", + Context::find_name ( + escape (process_regex (L"value,traits", type_regex, L"type")), + set)); + + String an (Context::find_name ( + escape (process_regex ("value", + one_accessor_regex, + accessor_regex, + L"one accessor")), + set, + false)); + + String mn (Context::find_name ( + escape (process_regex ("value", + one_modifier_regex, + modifier_regex, + L"one modifier")), + set, + false)); + + ec.set ("aname", an); + ec.set ("mname", mn); + + set.insert (an); + + if (an != mn) + set.insert (mn); + + // Detach. + // + if (detach) + { + String dn (Context::find_name ( + escape (process_regex (L"detach,value", + one_modifier_regex, + modifier_regex, + L"one modifier")), + set)); + + ec.set ("dname", dn); + } + + // Assign name() and namespace_() names. + // + ec.set ( + "element-name", + Context::find_name ( + escape ( + process_regex ("name", accessor_regex, L"modifier")), + set)); + + ec.set ( + "element-ns", + Context::find_name ( + escape ( + process_regex ("namespace", accessor_regex, L"modifier")), + set)); + + // Data members. + // + ec.set ("member", Context::find_name ("value_", set)); + ec.set ("element-name-member", + Context::find_name ("name_", set)); + ec.set ("element-ns-member", + Context::find_name ("namespace__", set)); + } + else + name = find_name (escape (e.name ())); + + ec.set ("name", name); + element_set_.insert (name); + } + else + { + // Make sure the name is unique among global elements and + // does not collide with a global type name. + // + String base (find_name (escape (e.name ()))); + e.context ().set ("name", base); + + String n (e.name ()); + + // Assign the parsing function name. + // + String p; + + if (!options.suppress_parsing () && doc_root_p (e)) + { + p = find_name ( + escape ( + process_regex (n, parser_regex, L"parsing function"))); + + e.context ().set ("parser", p); + } + + // Assign the serialization function name. + // + String s; + + if (options.generate_serialization () && doc_root_p (e)) + { + s = find_name ( + escape ( + process_regex ( + n, serializer_regex, L"serialization function"))); + + e.context ().set ("serializer", s); + } + + // Add the names to the set only after processing parsing and + // serialization function names so that we do not over-escape + // them. + // + element_set_.insert (base); + + if (p && p != base) + element_set_.insert (p); + + if (s && s != base && s != p) + element_set_.insert (s); + } + } + + private: + String + find_name (String const& name) + { + String r (name); + + // If we are conflicting with a type name let's first try to + // simply append an underscore and only resort to ugly names + // like name1, etc., if this fails. + // + if (type_set_.find (r) != type_set_.end ()) + r += L"_"; + + for (size_t i (1); + element_set_.find (r) != element_set_.end () || + type_set_.find (r) != type_set_.end (); ++i) + { + std::wostringstream os; + os << i; + r = name + os.str (); + } + + return r; + } + + private: + NameSet const& type_set_; + NameSet& element_set_; + }; + + struct NamespacePassOne: Traversal::Namespace, Context + { + NamespacePassOne (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& ns) + { + NameSet& type_set (global_type_names[ns.name ()]); + + GlobalType type (*this, type_set); + Traversal::Names names (type); + + Traversal::Namespace::names (ns, names); + Traversal::Namespace::names (ns); + } + }; + + + struct NamespacePassThree: Traversal::Namespace, Context + { + NamespacePassThree (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& ns) + { + String const& name (ns.name ()); + + NameSet const& type_set (global_type_names[name]); + NameSet& element_set (global_element_names[name]); + + GlobalElement element (*this, type_set, element_set); + Traversal::Names names (element); + + Traversal::Namespace::names (ns, names); + } + }; + + + struct FundamentalNamespace: Traversal::Namespace, + + Traversal::AnyType, + Traversal::AnySimpleType, + + 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::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::QName, + + 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 + { + using Namespace::traverse; + + FundamentalNamespace (Context& c) + : Context (c) + { + *this >> names_ >> *this; + } + + void + process_name (SemanticGraph::Type& t, String const& name) + { + String r ( + process_regex ( + namespace_ (t).name (), name, type_regex, L"type")); + + t.context ().set ("name", escape (r)); + } + + void + process_name (SemanticGraph::Namespace& n, + String const& name, + char const* key) + { + String r (process_regex (name, type_regex, L"type")); + n.context ().set (key, escape (r)); + } + + // anyType and anySimpleType + // + virtual void + traverse (SemanticGraph::AnyType& t) + { + process_name (t, "type"); + } + + virtual void + traverse (SemanticGraph::AnySimpleType& t) + { + process_name (t, "simple,type"); + } + + // Integrals. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + process_name (t, "byte"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + process_name (t, "unsigned,byte"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + process_name (t, "short"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + process_name (t, "unsigned,short"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + process_name (t, "int"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + process_name (t, "unsigned,int"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + process_name (t, "long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + process_name (t, "unsigned,long"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + process_name (t, "integer"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + process_name (t, "non,positive,integer"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + process_name (t, "non,negative,integer"); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + process_name (t, "positive,integer"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + process_name (t, "negative,integer"); + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + process_name (t, "boolean"); + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + process_name (t, "float"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + process_name (t, "double"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + process_name (t, "decimal"); + } + + // Strings. + // + virtual void + traverse (SemanticGraph::Fundamental::String& t) + { + process_name (t, "string"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + process_name (t, "normalized,string"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Token& t) + { + process_name (t, "token"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + process_name (t, "nmtoken"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + process_name (t, "nmtokens"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Name& t) + { + process_name (t, "name"); + } + + virtual void + traverse (SemanticGraph::Fundamental::NCName& t) + { + process_name (t, "ncname"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Language& t) + { + process_name (t, "language"); + } + + // ID/IDREF. + // + virtual void + traverse (SemanticGraph::Fundamental::Id& t) + { + process_name (t, "id"); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + process_name (t, "idref"); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + process_name (t, "idrefs"); + } + + + // URI. + // + virtual void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + process_name (t, "uri"); + } + + // Qualified name. + // + virtual void + traverse (SemanticGraph::Fundamental::QName& t) + { + process_name (t, "qname"); + } + + // Binary. + // + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + process_name (t, "base64,binary"); + } + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + process_name (t, "hex,binary"); + } + + + // Date/time. + // + virtual void + traverse (SemanticGraph::Fundamental::Date& t) + { + process_name (t, "date"); + } + + virtual void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + process_name (t, "date,time"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Duration& t) + { + process_name (t, "duration"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Day& t) + { + process_name (t, "gday"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Month& t) + { + process_name (t, "gmonth"); + } + + virtual void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + process_name (t, "gmonth,day"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Year& t) + { + process_name (t, "gyear"); + } + + virtual void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + process_name (t, "gyear,month"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Time& t) + { + process_name (t, "time"); + } + + // Entity. + // + virtual void + traverse (SemanticGraph::Fundamental::Entity& t) + { + process_name (t, "entity"); + } + + virtual void + traverse (SemanticGraph::Fundamental::Entities& t) + { + process_name (t, "entities"); + } + + virtual void + post (SemanticGraph::Namespace& n) + { + // Assign names to extra stuff in the XML Schema namespace. + // + process_name (n, "container", "container"); + process_name (n, "buffer", "buffer"); + process_name (n, "time,zone", "time-zone"); + + process_name (n, "content,order", "content-order"); + + if (options.generate_element_type ()) + process_name (n, "element,type", "element-type"); + + if (options.generate_element_map ()) + process_name (n, "element,map", "element-map"); + + if (options.generate_serialization ()) + { + process_name (n, "namespace,info", "namespace-info"); + process_name (n, "namespace,infomap", "namespace-infomap"); + process_name (n, "list,stream", "list-stream"); + process_name (n, "as,double", "as-double"); + process_name (n, "as,decimal", "as-decimal"); + process_name (n, "facet", "facet"); + } + + if (!options.generate_insertion ().empty ()) + { + process_name (n, "ostream", "ostream"); + } + + if (!options.generate_extraction ().empty ()) + { + process_name (n, "istream", "istream"); + } + + process_name (n, "flags", "flags"); + process_name (n, "properties", "properties"); + + NarrowString fn (options.function_naming ()); + + if (fn == "knr") + n.context ().set ("tree-node-key", String ("tree_node_key")); + else if (fn == "ucc") + n.context ().set ("tree-node-key", String ("TreeNodeKey")); + else + n.context ().set ("tree-node-key", String ("treeNodeKey")); + + process_name (n, "exception", "exception"); + process_name (n, "parsing", "parsing"); + process_name (n, "expected,element", "expected-element"); + process_name (n, "unexpected,element", "unexpected-element"); + process_name (n, "expected,attribute", "expected-attribute"); + process_name (n, "unexpected,enumerator", "unexpected-enumerator"); + process_name (n, "expected,text,content", "expected-text-content"); + process_name (n, "no,type,info", "no-type-info"); + process_name (n, "no,element,info", "no-element-info"); + process_name (n, "not,derived", "not-derived"); + process_name (n, "duplicate,id", "duplicate-id"); + process_name (n, "serialization", "serialization"); + process_name (n, "no,namespace,mapping", "no-namespace-mapping"); + process_name (n, "no,prefix,mapping", "no-prefix-mapping"); + process_name (n, "xsi,already,in,use", "xsi-already-in-use"); + process_name (n, "bounds", "bounds"); + + process_name (n, "severity", "severity"); + process_name (n, "error", "error"); + process_name (n, "diagnostics", "diagnostics"); + + if (!options.suppress_parsing () || + options.generate_serialization ()) + { + process_name (n, "error,handler", "error-handler"); + } + + Namespace::post (n); + } + + private: + Traversal::Names names_; + }; + + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct UsesPassOne: Traversal::Uses + { + virtual void + traverse (Type& u) + { + SemanticGraph::Schema& s (u.schema ()); + + if (!s.context ().count ("cxx-tree-name-processor-pass-1")) + { + s.context ().set ("cxx-tree-name-processor-pass-1", true); + Traversal::Uses::traverse (u); + } + } + }; + + struct UsesPassThree: Traversal::Uses + { + virtual void + traverse (Type& u) + { + SemanticGraph::Schema& s (u.schema ()); + + if (!s.context ().count ("cxx-tree-name-processor-pass-3")) + { + s.context ().set ("cxx-tree-name-processor-pass-3", true); + Traversal::Uses::traverse (u); + } + } + }; + + // Go into implied schemas while making sure we don't process + // the same stuff more than once. + // + struct Implies: Traversal::Implies + { + virtual void + traverse (SemanticGraph::Implies& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count ("cxx-tree-name-processor-seen")) + { + s.context ().set ("cxx-tree-name-processor-seen", true); + Traversal::Implies::traverse (i); + } + } + }; + + bool + process_impl (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file, + StringLiteralMap const& map) + { + try + { + Counts counts; + Context ctx (ops, counts, false, tu, file, map); + + if (tu.names_begin ()->named ().name () == + L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema xs_schema; + Traversal::Names xs_schema_names; + FundamentalNamespace xs_ns (ctx); + + xs_schema >> xs_schema_names >> xs_ns; + + xs_schema.dispatch (tu); + } + else + { + + // Pass one - assign names to global types. This pass cannot + // be combined with pass two because of possible recursive + // schema inclusions. Also note that we check first if this + // schema has already been processed which may happen in the + // file-per-type compilation mode. + // + if (!tu.context ().count ("cxx-tree-name-processor-pass-1")) + { + Traversal::Schema schema; + Traversal::Schema xs_schema; + UsesPassOne uses; + Implies implies; + + schema >> uses >> schema; + schema >> implies >> xs_schema; + + Traversal::Names schema_names; + Traversal::Names xs_schema_names; + NamespacePassOne ns (ctx); + FundamentalNamespace xs_ns (ctx); + + schema >> schema_names >> ns; + xs_schema >> xs_schema_names >> xs_ns; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-tree-name-processor-pass-1", true); + + schema.dispatch (tu); + } + + // Pass two - assign names inside complex types. Here + // we don't need to go into included/imported schemas. + // + { + Traversal::Schema schema; + Sources sources; + + schema >> sources >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + + schema >> schema_names >> ns >> ns_names; + + Complex complex (ctx); + Traversal::Enumeration enumeration; // Avoid fallback on complex. + + ns_names >> complex; + ns_names >> enumeration; + + schema.dispatch (tu); + } + + // Pass three - assign names to global elements as well as + // inside enums. Also note that we check first if this schema + // has already been processed which may happen in the file-per- + // type compilation mode. + // + if (!tu.context ().count ("cxx-tree-name-processor-pass-3")) + { + Traversal::Schema schema; + UsesPassThree uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + NamespacePassThree ns (ctx); + Traversal::Namespace ns_enum; + + schema >> schema_names; + + schema_names >> ns; + schema_names >> ns_enum; + + Traversal::Names ns_names; + Enumeration enumeration (ctx); + + ns_enum >> ns_names >> enumeration; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-tree-name-processor-pass-3", true); + + schema.dispatch (tu); + } + } + } + catch (Context::Failed const&) + { + // Diagnostics has already been issued. + // + return false; + } + + return true; + } + } + + bool NameProcessor:: + process (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file, + StringLiteralMap const& map) + { + return process_impl (ops, tu, file, map); + } + } +} diff --git a/xsd/cxx/tree/name-processor.hxx b/xsd/cxx/tree/name-processor.hxx new file mode 100644 index 0000000..632b05e --- /dev/null +++ b/xsd/cxx/tree/name-processor.hxx @@ -0,0 +1,28 @@ +// file : xsd/cxx/tree/name-processor.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_NAME_PROCESSOR_HXX +#define XSD_CXX_TREE_NAME_PROCESSOR_HXX + +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + class NameProcessor + { + public: + bool + process (options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + StringLiteralMap const&); + }; + } +} + +#endif // XSD_CXX_TREE_NAME_PROCESSOR_HXX diff --git a/xsd/cxx/tree/options.cli b/xsd/cxx/tree/options.cli new file mode 100644 index 0000000..0230429 --- /dev/null +++ b/xsd/cxx/tree/options.cli @@ -0,0 +1,479 @@ +// file : xsd/cxx/tree/options.cli +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include <cstddef>; // std::size_t + +include <xsd/types.hxx>; // NarrowString, NarrowStrings + +include <xsd/cxx/options.cli>; + +namespace CXX +{ + namespace Tree + { + class options: CXX::options + { + // Polymorphism. + // + bool --generate-polymorphic + { + "Generate polymorphism-aware code. Specify this option if you use + substitution groups or \cb{xsi:type}. Use the \cb{--polymorphic-type} + or \cb{--polymorphic-type-all} option to specify which type + hierarchies are polymorphic." + }; + + NarrowStrings --polymorphic-type + { + "<type>", + "Indicate that <type> is a root of a polymorphic type hierarchy. The + compiler can often automatically determine which types are + polymorphic based on the substitution group declarations. However, + you may need to use this option if you are not using substitution + groups or if substitution groups are defined in another schema. You + need to specify this option when compiling every schema file that + references <type>. The <type> argument is an XML Schema type name + that can be optionally qualified with a namespace in the + \c{\i{namespace}\b{#}\i{name}} form." + }; + + bool --polymorphic-type-all + { + "Indicate that all types should be treated as polymorphic." + }; + + unsigned long --polymorphic-plate = 0 + { + "<num>", + "Specify the polymorphic map plate the generated code should register + on. This functionality is primarily useful to segregate multiple + schemas that define the same polymorphic types." + }; + + // Ordered content. + // + NarrowStrings --ordered-type + { + "<type>", + "Indicate that element order in <type> is significant. An example + would be a complex type with unbounded choice as a content model + where the element order in XML has application-specific semantics. + For ordered types the compiler generates a special container data + member and a corresponding set of accessors and modifiers that are + used to capture the order of elements and, for mixed content, of + text. + + The <type> argument is an XML Schema type name that can be optionally + qualified with a namespace in the \c{\i{namespace}\b{#}\i{name}} form. + Note also that you will need to specify this option when compiling + every schema file that has other ordered types derived from this + type." + }; + + bool --ordered-type-derived + { + "Automatically treat types derived from ordered bases as also + ordered. This is primarily useful if you would like to be able + to iterate over the complete content using the content order + container." + }; + + bool --ordered-type-mixed + { + "Automatically treat complex types with mixed content as ordered." + }; + + bool --ordered-type-all + { + "Indicate that element order in all types is significant." + }; + + NarrowString --order-container + { + "<type>", + "Specify a custom class template that should be used as a container + for the content order in ordered types instead of the default + \cb{std::vector}. See \cb{--ordered-type} for more information on + ordered type. This option is primarily useful if you need to + perform more complex lookups in the content order container, for + example by element id. In this case, a container like Boost + multi-index may be more convenient. Note that if using a custom + container, you will also most likely need to include the relevant + headers using the \cb{--hxx-prologue*} options." + }; + + // Features. + // + bool --generate-serialization + { + "Generate serialization functions. Serialization functions convert + the object model back to XML." + }; + + bool --generate-ostream + { + "Generate ostream insertion operators (\cb{operator<<}) for generated + types. This allows one to easily print a fragment or the whole object + model for debugging or logging." + }; + + bool --generate-doxygen + { + "Generate documentation comments suitable for extraction by the + Doxygen documentation system. Documentation from annotations is + added to the comments if present in the schema." + }; + + bool --generate-comparison + { + "Generate comparison operators (\cb{operator==} and \cb{operator!=}) + for complex types. Comparison is performed member-wise." + }; + + bool --generate-default-ctor + { + "Generate default constructors even for types that have required + members. Required members of an instance constructed using such a + constructor are not initialized and accessing them results in + undefined behavior." + }; + + bool --generate-from-base-ctor + { + "Generate constructors that expect an instance of a base type + followed by all required members." + }; + + bool --suppress-assignment + { + "Suppress the generation of copy assignment operators for complex + types. If this option is specified, the copy assignment operators + for such types are declared private and left unimplemented." + }; + + bool --generate-detach + { + "Generate detach functions for required elements and attributes. + Detach functions for optional and sequence cardinalities are + provided by the respective containers. These functions, for + example, allow you to move sub-trees in the object model either + within the same tree or between different trees." + }; + + bool --generate-wildcard + { + "Generate accessors and modifiers as well as parsing and serialization + code for XML Schema wildcards (\cb{any} and \cb{anyAttribute}). XML + content matched by wildcards is presented as DOM fragments. Note + that you need to initialize the Xerces-C++ runtime if you are using + this option." + }; + + bool --generate-any-type + { + "Extract and store content of the XML Schema \cb{anyType} type as a + DOM fragment. Note that you need to initialize the Xerces-C++ runtime + if you are using this option." + }; + + NarrowStrings --generate-insertion + { + "<os>", + "Generate data representation stream insertion operators for the <os> + output stream type. Repeat this option to specify more than one + stream type. The ACE CDR stream (\cb{ACE_OutputCDR}) and RPC XDR + are recognized by the compiler and the necessary \cb{#include} + directives are automatically generated. For custom stream types use + the \cb{--hxx-prologue*} options to provide the necessary + declarations." + }; + + NarrowStrings --generate-extraction + { + "<is>", + "Generate data representation stream extraction constructors for the + <is> input stream type. Repeat this option to specify more than one + stream type. The ACE CDR stream (\cb{ACE_InputCDR}) and RPC XDR are + recognized by the compiler and the necessary \cb{#include} directives + are automatically generated. For custom stream types use the + \cb{--hxx-prologue*} options to provide the necessary declarations." + }; + + bool --generate-forward + { + "Generate a separate header file with forward declarations for the + types being generated." + }; + + bool --suppress-parsing + { + "Suppress the generation of the parsing functions and constructors. + Use this option to reduce the generated code size when parsing from + XML is not needed." + }; + + bool --generate-element-type + { + "Generate types instead of parsing and serialization functions for + root elements. This is primarily useful to distinguish object models + with the same root type but with different root elements." + }; + + bool --generate-element-map + { + "Generate a root element map that allows uniform parsing and + serialization of multiple root elements. This option is only valid + together with \cb{--generate-element-type}." + }; + + bool --generate-intellisense + { + "Generate workarounds for IntelliSense bugs in Visual Studio 2005 + (8.0). When this option is used, the resulting code is slightly + more verbose. IntelliSense in Visual Studio 2008 (9.0) and later + does not require these workarounds. Support for IntelliSense in + Visual Studio 2003 (7.1) is improved with this option but is + still incomplete." + }; + + bool --omit-default-attributes + { + "Omit attributes with default and fixed values from serialized XML + documents." + }; + + // Naming. + // + NarrowString --type-naming = "knr" + { + "<style>", + "Specify the type naming convention that should be used in the + generated code. Valid styles are \cb{knr} (default), \cb{ucc}, + and \cb{java}. See the NAMING CONVENTION section below for more + information." + }; + + NarrowString --function-naming = "knr" + { + "<style>", + "Specify the function naming convention that should be used in the + generated code. Valid styles are \cb{knr} (default), \cb{lcc}, + \cb{ucc}, and \cb{java}. See the NAMING CONVENTION section below + for more information." + }; + + NarrowStrings --type-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema type names to C++ type names. See the NAMING CONVENTION + section below for more information." + }; + + NarrowStrings --accessor-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes to C++ accessor function + names. See the NAMING CONVENTION section below for more information." + }; + + NarrowStrings --one-accessor-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality one to + C++ accessor function names. See the NAMING CONVENTION section + below for more information." + }; + + NarrowStrings --opt-accessor-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality optional + to C++ accessor function names. See the NAMING CONVENTION section + below for more information." + }; + + NarrowStrings --seq-accessor-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality sequence + to C++ accessor function names. See the NAMING CONVENTION section + below for more information." + }; + + NarrowStrings --modifier-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes to C++ modifier function + names. See the NAMING CONVENTION section below for more information." + }; + + NarrowStrings --one-modifier-regex + + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality one to C++ + modifier function names. See the NAMING CONVENTION section below + for more information." + }; + + NarrowStrings --opt-modifier-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality optional + to C++ modifier function names. See the NAMING CONVENTION section + below for more information." + }; + + NarrowStrings --seq-modifier-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema names of elements/attributes with cardinality sequence + to C++ modifier function names. See the NAMING CONVENTION section + below for more information." + }; + + NarrowStrings --parser-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema element names to C++ parsing function names. See the + NAMING CONVENTION section below for more information." + }; + + NarrowStrings --serializer-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema element names to C++ serialization function names. See + the NAMING CONVENTION section below for more information." + }; + + NarrowStrings --const-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema-derived names to C++ constant names. See the NAMING + CONVENTION section below for more information." + }; + + NarrowStrings --enumerator-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema enumeration values to C++ enumerator names. See the + NAMING CONVENTION section below for more information." + }; + + NarrowStrings --element-type-regex + { + "<regex>", + "Add <regex> to the list of regular expressions used to translate + XML Schema element names to C++ element type names. See the NAMING + CONVENTION section below for more information." + }; + + bool --name-regex-trace + { + "Trace the process of applying regular expressions specified with + the name transformation options. Use this option to find out why + your regular expressions don't do what you expected them to do." + }; + + // Root element. + // + bool --root-element-first + { + "Treat only the first global element as a document root. By default + all global elements are considered document roots." + }; + + bool --root-element-last + { + "Treat only the last global element as a document root. By default + all global elements are considered document roots." + }; + + bool --root-element-all + { + "Treat all global elements as document roots. This is the default + behavior. By explicitly specifying this option you can suppress + the warning that is issued if more than one global element is + defined." + }; + + bool --root-element-none + { + "Do not treat any global elements as document roots. By default all + global elements are considered document roots." + }; + + NarrowStrings --root-element + { + "<element>", + "Treat only <element> as a document root. Repeat this option to + specify more than one root element." + }; + + // Custom type. + // + NarrowStrings --custom-type + { + "<map>", + "Use a custom C++ type instead of the generated class. The <map> + argument is in the form \c{\i{name}[\b{=}\i{type}[\b{/}\i{base}]]}, + where \i{name} is a type name as defined in XML Schema and \i{type} + is a C++ type name that should be used instead. If \i{type} is not + present or empty then the custom type is assumed to have the same + name and be defined in the same namespace as the generated class + would have. If \i{base} is specified then the generated class is + still generated but with that name." + }; + + NarrowStrings --custom-type-regex + { + "<regex>", + "Use custom C++ types instead of the generated classes. The <regex> + argument is in the form + \c{\b{/}\i{name-pat}\b{/}[\i{type-sub}\b{/}[\i{base-sub}\b{/}]]}, + where \i{name-pat} is a regex pattern that will be matched against + type names as defined in XML Schema and \i{type-sub} is a C++ type + name substitution that should be used instead. If \i{type-sub} is + not present or its substitution results in an empty string then + the custom type is assumed to have the same name and be defined + in the same namespace as the generated class would have. If + \i{base-sub} is present and its substitution results in a + non-empty string then the generated class is still generated + but with the result of this substitution as its name. The pattern + and substitutions are in the Perl regular expression format. + See also the REGEX AND SHELL QUOTING section below." + }; + + // Parts. + // + std::size_t --parts = 1 + { + "<num>", + "Split generated source code into <num> parts. This is useful when + translating large, monolithic schemas and a C++ compiler is not + able to compile the resulting source code at once (usually due + to insufficient memory)." + }; + + NarrowString --parts-suffix = "-" + { + "<suffix>", + "Use <suffix> instead of the default '\cb{-}' to separate the file + name from the part number." + }; + }; + } +} diff --git a/xsd/cxx/tree/order-processor.cxx b/xsd/cxx/tree/order-processor.cxx new file mode 100644 index 0000000..ccc3dc5 --- /dev/null +++ b/xsd/cxx/tree/order-processor.cxx @@ -0,0 +1,243 @@ +// file : xsde/cxx/tree/order-processor.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/order-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct Member: Traversal::Element, Traversal::Any + { + Member (size_t count): count_ (count) {} + + virtual void + traverse (SemanticGraph::Element& e) + { + if (Context::skip (e)) + return; + + e.context ().set ("ordered-id", count_++); + } + + virtual void + traverse (SemanticGraph::Any& a) + { + a.context ().set ("ordered-id", count_++); + } + + size_t count_; + }; + + // + // + struct Type: Traversal::Complex + { + Type (TypeNameSet& ordered_types, bool derived, bool mixed, bool all) + : ordered_types_ (ordered_types), + derived_ (derived), + mixed_ (mixed), + all_ (all) + { + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (!ctx.count ("ordered")) + { + // First process our base. + // + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!b.context ().count ("ordered")) + dispatch (b); + } + + // See if our base (not necessarily immediate) is ordered. + // + using SemanticGraph::Complex; + + Complex* b (0); + + for (Complex* p (&c); p->inherits_p ();) + { + if ((b = dynamic_cast<Complex*> (&p->inherits ().base ()))) + { + if (Context::ordered_p (*b)) + break; + + p = b; + } + else + break; + } + + bool o (all_ || + (derived_ && b != 0 && Context::ordered_p (*b)) || + (mixed_ && c.mixed_p ()) || + ordered_types_.find (c)); + ctx.set ("ordered", o); + + // Assign ids to elements and wildcards, calculate total count. + // + if (o) + { + size_t count ( + b != 0 && Context::ordered_p (*b) + ? b->context ().get<size_t> ("ordered-count") + : 1); + + ctx.set ("ordered-start", count); + + Member m (count); + Traversal::Names n (m); + names (c, n); + + // Assign content id for mixed text. + // + if (Context::mixed_p (c) && count == 1) + ctx.set ("mixed-ordered-id", m.count_++); + + ctx.set ("ordered-count", m.count_); + } + } + } + + private: + TypeNameSet& ordered_types_; + bool derived_; + bool mixed_; + bool all_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (char const* seen_key) + : seen_key_ (seen_key) + { + } + + virtual void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Sources::traverse (sr); + } + } + + virtual void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Includes::traverse (i); + } + } + + virtual void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Imports::traverse (i); + } + } + + private: + char const* seen_key_; + }; + + char const* seen_key = "cxx-tree-order-processor-seen"; + + bool + process_impl (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&) + { + // Prepare a set of ordered types. + // + TypeNameSet ordered_types (ops.ordered_type ().begin (), + ops.ordered_type ().end ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + // Nothing to do if this is the XML Schema namespace. + // + if (i == tu.names_end () || + i->named ().name () != L"http://www.w3.org/2001/XMLSchema") + { + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count (seen_key)) + { + Traversal::Schema schema; + Uses uses (seen_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (ordered_types, + ops.ordered_type_derived (), + ops.ordered_type_mixed (), + ops.ordered_type_all ()); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (seen_key, true); + + schema.dispatch (tu); + } + } + + return true; + } + } + + bool OrderProcessor:: + process (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file) + { + return process_impl (ops, tu, file); + } + } +} diff --git a/xsd/cxx/tree/order-processor.hxx b/xsd/cxx/tree/order-processor.hxx new file mode 100644 index 0000000..868547d --- /dev/null +++ b/xsd/cxx/tree/order-processor.hxx @@ -0,0 +1,29 @@ +// file : xsde/cxx/tree/order-processor.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_ORDER_PROCESSOR_HXX +#define XSD_CXX_TREE_ORDER_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + class OrderProcessor + { + public: + bool + process (options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file); + }; + } +} + +#endif // XSD_CXX_TREE_ORDER_PROCESSOR_HXX diff --git a/xsd/cxx/tree/parser-header.cxx b/xsd/cxx/tree/parser-header.cxx new file mode 100644 index 0000000..9ef9e89 --- /dev/null +++ b/xsd/cxx/tree/parser-header.cxx @@ -0,0 +1,472 @@ +// file : xsd/cxx/tree/parser-header.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/parser-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eparser (e)); + String const& error_handler (error_handler_type); + + if (doxygen) + { + os << "/**" << endl + << " * @name Parsing functions for the %" << + comment (e.name ()) << " document root." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl + << "//@{" << endl + << endl; + } + + if (!doxygen) + { + os << "// Parse a URI or a local file." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file with an error handler." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file with a Xerces-C++ " << + "DOM error" << endl + << " * handler." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse std::istream." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with an error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a " << + "Xerces-C++ DOM error" << endl + << " * handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource id." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource " << + "id and an" << endl + << " * error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource " << + "id and a" << endl + << " * Xerces-C++ DOM error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse xercesc::InputSource." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source with an " << + "error handler." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source with a " << + "Xerces-C++ DOM" << endl + << " * error handler." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A Xerces-C++ DOM document." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (const " << xerces_ns << "::DOMDocument& d," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A pointer to the Xerces-C++ DOM document." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function is normally used together with the " << + "keep_dom and" << endl + << " * own_dom parsing flags to assign ownership of the DOM " << + "document" << endl + << " * to the object model." << endl + << " */" << endl; + } + + os << inst_exp + << auto_ptr << "< " << type_name (e) << " >" << endl + << name << " (" << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + + void + generate_parser_header (Context& ctx) + { + ctx.os << "#include <iosfwd>" << endl + << endl + << "#include <xercesc/sax/InputSource.hpp>" << endl + << "#include <xercesc/dom/DOMDocument.hpp>" << endl + << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl + << endl; + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx); + ElementFunction element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/parser-header.hxx b/xsd/cxx/tree/parser-header.hxx new file mode 100644 index 0000000..b7860c4 --- /dev/null +++ b/xsd/cxx/tree/parser-header.hxx @@ -0,0 +1,19 @@ +// file : xsd/cxx/tree/parser-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_PARSER_HEADER_HXX +#define XSD_CXX_TREE_PARSER_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + + +namespace CXX +{ + namespace Tree + { + void + generate_parser_header (Context&); + } +} + +#endif // XSD_CXX_TREE_PARSER_HEADER_HXX diff --git a/xsd/cxx/tree/parser-source.cxx b/xsd/cxx/tree/parser-source.cxx new file mode 100644 index 0000000..cee5ea6 --- /dev/null +++ b/xsd/cxx/tree/parser-source.cxx @@ -0,0 +1,541 @@ +// file : xsd/cxx/tree/parser-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/parser-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + SemanticGraph::Type& t (e.type ()); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. + // + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + // Check if this element is abstract. + // + bool abst; + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + // Nothing to do if we are abstract and not polymorphic. + // + if (abst && !polymorphic) + return; + + String const& name (eparser (e)); + String type (type_name (e)); + String const& error_handler (error_handler_type); + + // Note that I am using fq-name in function calls because g++ gets + // confused if the name is 'type'. (see tests/schema/anonymous) + // + + char const* d (std >= cxx_version::cxx11 ? "std::move (d)" : "d"); + + // URI. + // + os << auto_ptr << "< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << + char_type << " > > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + + // istream + // + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, f, p);" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, f, p);" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + + // InputSource. + // + os << auto_ptr << "< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << + char_type << " > > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + os << auto_ptr << "< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + + os << auto_ptr << "< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.disable_multi_import ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}"; + + + // DOM. + // + + bool fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + // const DOMDocument& + // + os << auto_ptr << "< " << type << " >" << endl + << name << " (const " << xerces_ns << "::DOMDocument& doc," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "if (f & " << flags_type << "::keep_dom)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "static_cast< " << xerces_ns << + "::DOMDocument* > (doc.cloneNode (true)));" + << endl + << "return " << auto_ptr << "< " << type << " > (" << endl + << fq_name (e, "parser") << " (" << endl + << d << ", f | " << flags_type << "::own_dom, p));" + << "}" + << "const " << xerces_ns << "::DOMElement& e (*doc.getDocumentElement ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl; + + if (poly) + { + os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< " << + poly_plate << ", " << char_type << " > ().create (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl; + + if (abst) + os << "0,"; + else + os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + + os << endl + << "true, true, e, n, f, 0));" + << endl + << "if (tmp.get () != 0)" + << "{" + << auto_ptr << "< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" + << "{"; + + if (fund) + { + os << auto_ptr << "< " << type << " > r (" << endl + << "new " << type << " (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " >::create (" << endl + << "e, f, 0)));"; + } + else + { + os << auto_ptr << "< " << type << " > r (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type << " >::create (" << endl + << "e, f, 0));"; + } + } + + os << "return r;" + << "}" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << ");" + << "}"; + + + // dom::auto_ptr/unique_ptr<DOMDocument> + // + os << auto_ptr << "< " << type << " >" << endl + << name << " (" << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d," << endl + << flags_type << " f," << endl + << "const " << properties_type << "&)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > c (" << endl + << "((f & " << flags_type << "::keep_dom) &&" << endl + << "!(f & " << flags_type << "::own_dom))" << endl + << "? static_cast< " << xerces_ns << "::DOMDocument* > (" << + "d->cloneNode (true))" << endl + << ": 0);" + << endl + << xerces_ns << "::DOMDocument& doc (c.get () ? *c : *d);" + << "const " << xerces_ns << "::DOMElement& e (" << + "*doc.getDocumentElement ());" + << endl + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl + << "if (f & " << flags_type << "::keep_dom)" << endl + << "doc.setUserData (" << dom_node_key << "," << endl + << "(c.get () ? &c : &d)," << endl + << "0);" + << endl; + + if (poly) + { + os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< " << + poly_plate << ", " << char_type << " > ().create (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl; + + if (abst) + os << "0,"; + else + os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + + os << endl + << "true, true, e, n, f, 0));" + << endl + << "if (tmp.get () != 0)" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" + << "{"; + + if (fund) + { + os << auto_ptr << "< " << type << " > r (" << endl + << "new " << type << " (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " >::create (" << endl + << "e, f, 0)));"; + } + else + { + os << auto_ptr << "< " << type << " > r (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type << " >::create (" << endl + << "e, f, 0));"; + } + } + + if (poly) + { + os << endl + << auto_ptr << "< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + + os << "return r;" + << "}" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << ");" + << "}"; + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + void + generate_parser_source (Context& ctx, size_t first, size_t last) + { + ctx.os << "#include <istream>" << endl + << "#include <xsd/cxx/xml/sax/std-input-source.hxx>" << endl + << "#include <xsd/cxx/tree/error-handler.hxx>" << endl + << endl; + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + ElementFunction element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/parser-source.hxx b/xsd/cxx/tree/parser-source.hxx new file mode 100644 index 0000000..1bb70d9 --- /dev/null +++ b/xsd/cxx/tree/parser-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/parser-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_PARSER_SOURCE_HXX +#define XSD_CXX_TREE_PARSER_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_parser_source (Context&, size_t first, size_t last); + } +} + +#endif // XSD_CXX_TREE_PARSER_SOURCE_HXX diff --git a/xsd/cxx/tree/polymorphism-processor.cxx b/xsd/cxx/tree/polymorphism-processor.cxx new file mode 100644 index 0000000..4d07c69 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.cxx @@ -0,0 +1,740 @@ +// file : xsde/cxx/tree/polymorphism-processor.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <iostream> + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/polymorphism-processor.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + // + // + struct Type: Traversal::Type, + Traversal::Complex + { + Type (TypeNameSet& poly_types) + : poly_types_ (poly_types) + { + } + + virtual void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& ctx (t.context ()); + + if (!ctx.count ("polymorphic")) + ctx.set ("polymorphic", poly_types_.find (t)); + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (!ctx.count ("polymorphic")) + { + // First check our base. + // + bool pb (false); + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!b.context ().count ("polymorphic")) + dispatch (b); + + pb = b.context ().get<bool> ("polymorphic"); + } + + ctx.set ("polymorphic", pb || poly_types_.find (c)); + } + } + + private: + TypeNameSet& poly_types_; + }; + + struct FundType: Traversal::AnyType, + Traversal::AnySimpleType, + + 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::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 + { + FundType (TypeNameSet& poly_types, bool& valid) + : poly_types_ (poly_types), valid_ (valid) + { + } + + void + check (SemanticGraph::Type& t, bool fund) + { + SemanticGraph::Context& ctx (t.context ()); + + if (poly_types_.find (t)) + { + if (!fund) + ctx.set ("polymorphic", true); + else + { + wcerr << "error: built-in type '" << t.name () << "' cannot " + << "be polymorphic because it is mapped to a fundamental " + << "C++ type" + << endl; + + valid_ = false; + } + } + else + ctx.set ("polymorphic", false); + } + + // anyType & anySimpleType. + // + virtual void + traverse (SemanticGraph::AnyType& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::AnySimpleType& t) + { + check (t, false); + } + + // Boolean. + // + virtual void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + check (t, true); + } + + // Integral types. + // + virtual void + traverse (SemanticGraph::Fundamental::Byte& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Short& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Int& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Long& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Integer& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + check (t, true); + } + + // Floats. + // + virtual void + traverse (SemanticGraph::Fundamental::Float& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Double& t) + { + check (t, true); + } + + virtual void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + check (t, true); + } + + // Strings. + // + virtual void + traverse (SemanticGraph::Fundamental::String& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Token& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Name& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::NCName& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Language& t) + { + check (t, false); + } + + + // Qualified name. + // + virtual void + traverse (SemanticGraph::Fundamental::QName& t) + { + check (t, false); + } + + + // ID/IDREF. + // + virtual void + traverse (SemanticGraph::Fundamental::Id& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + check (t, false); + } + + // URI. + // + virtual void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + check (t, false); + } + + // Binary. + // + virtual void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + check (t, false); + } + + + // Date/time. + // + virtual void + traverse (SemanticGraph::Fundamental::Date& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Duration& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Day& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Month& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Year& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Time& t) + { + check (t, false); + } + + // Entity. + // + virtual void + traverse (SemanticGraph::Fundamental::Entity& t) + { + check (t, false); + } + + virtual void + traverse (SemanticGraph::Fundamental::Entities& t) + { + check (t, false); + } + + private: + TypeNameSet& poly_types_; + bool& valid_; + }; + + struct GlobalElement: Traversal::Element + { + GlobalElement (TypeNameSet& poly_types, + bool& valid, + const WarningSet& disabled_warnings) + : poly_types_ (poly_types), valid_ (valid), warning_ (true) + { + if (disabled_warnings.find ("all") != disabled_warnings.end () || + disabled_warnings.find ("T005") != disabled_warnings.end ()) + warning_ = false; + } + + virtual void + traverse (Type& e) + { + using SemanticGraph::Schema; + + if (!e.substitutes_p ()) + return; + + // If we are a substitution for some element, then mark + // that element's type as polymorphic. + // + Type& r (e.substitutes ().root ()); + SemanticGraph::Type& rt (r.type ()); + SemanticGraph::Context& ctx (rt.context ()); + + // We may need to override the previous value. + // + if (ctx.count ("polymorphic") && ctx.get<bool> ("polymorphic")) + return; + + // Built-in types that are mapped to fundamental types cannot + // be declared polymorphic. + // + bool fund (false); + IsFundamentalType test (fund); + test.dispatch (rt); + + if (fund) + { + wcerr << r.file () << ":" << r.line () << ":" << r.column () + << ": error: built-in type '" << rt.name () << "' " + << "is mapped to a fundamental C++ type and is expected " + << "to be polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + valid_ = false; + return; + } + + ctx.set ("polymorphic", true); + + if (!warning_) + return; + + Schema& es (dynamic_cast<Schema&> (e.scope ().scope ())); + Schema& rts (dynamic_cast<Schema&> (rt.scope ().scope ())); + + // If the root type and this element are in different schemas + // and the root type is not explicitly marked as polymorphic, + // then issue a warning. + // + if (&es != &rts && !sources_p (es, rts) && !poly_types_.find (rt)) + { + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": warning T005: assuming type '" << rt.name () << "' " + << "is polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": info: use --polymorphic-type to indicate this type " + << "is polymorphic when compiling schemas that " + << "reference it" << endl; + } + } + + private: + // Return true if root sources s. + // + bool + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a<Sources> ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + TypeNameSet& poly_types_; + bool& valid_; + bool warning_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (char const* seen_key) + : seen_key_ (seen_key) + { + } + + virtual void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Sources::traverse (sr); + } + } + + virtual void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Includes::traverse (i); + } + } + + virtual void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Imports::traverse (i); + } + } + + private: + char const* seen_key_; + }; + + char const* pass_one_key = "cxx-tree-polymorphism-processor-seen-one"; + char const* pass_two_key = "cxx-tree-polymorphism-processor-seen-two"; + + bool + process_impl (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&, + const WarningSet& disabled_warnings) + { + bool valid (true); + + // Prepare a set of polymorphic types. + // + + TypeNameSet poly_types (ops.polymorphic_type ().begin (), + ops.polymorphic_type ().end ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + if (i != tu.names_end () && + i->named ().name () == L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // First handle fundamental types. + // + { + Traversal::Schema schema; + Traversal::Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count (pass_two_key)) + { + // Pass one - check substitution groups. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_one_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalElement element (poly_types, valid, disabled_warnings); + + schema >> schema_names >> ns >> ns_names >> element; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_one_key, true); + + schema.dispatch (tu); + } + + // Pass two - process types. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_two_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (poly_types); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_two_key, true); + + schema.dispatch (tu); + } + } + } + + return valid; + } + } + + bool PolymorphismProcessor:: + process (options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file, + const WarningSet& disabled_warnings) + { + return process_impl (ops, tu, file, disabled_warnings); + } + } +} diff --git a/xsd/cxx/tree/polymorphism-processor.hxx b/xsd/cxx/tree/polymorphism-processor.hxx new file mode 100644 index 0000000..88019a8 --- /dev/null +++ b/xsd/cxx/tree/polymorphism-processor.hxx @@ -0,0 +1,30 @@ +// file : xsde/cxx/tree/polymorphism-processor.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX +#define XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX + +#include <libxsd-frontend/semantic-graph.hxx> + +#include <xsd/xsd.hxx> +#include <xsd/types.hxx> + +#include <xsd/cxx/tree/options.hxx> + +namespace CXX +{ + namespace Tree + { + class PolymorphismProcessor + { + public: + bool + process (options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // XSD_CXX_TREE_POLYMORPHISM_PROCESSOR_HXX diff --git a/xsd/cxx/tree/serialization-header.cxx b/xsd/cxx/tree/serialization-header.cxx new file mode 100644 index 0000000..5434441 --- /dev/null +++ b/xsd/cxx/tree/serialization-header.cxx @@ -0,0 +1,579 @@ +// file : xsd/cxx/tree/serialization-header.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/serialization-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + bool simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + struct ElementType: Traversal::Element, + GlobalElementBase, + Context + { + ElementType (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (doc_root_p (e)) + { + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << ename (e) << "&);" + << endl; + } + } + }; + + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eserializer (e)); + String const& error_handler (error_handler_type); + String const& namespace_infomap (namespace_infomap_type); + + if (doxygen) + { + os << "/**" << endl + << " * @name Serialization functions for the %" << + comment (e.name ()) << " document root." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl + << "//@{" << endl + << endl; + } + + if (!doxygen) + { + os << "// Serialize to std::ostream." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function uses exceptions to report " << + "serialization errors." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream with an " << + "error handler." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh An error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << error_handler << "& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream with a " << + "Xerces-C++ DOM" << endl + << " * error handler." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to xercesc::XMLFormatTarget." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function uses exceptions to report " << + "serialization errors." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target " << + "with an error" << endl + << " * handler." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh An error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << error_handler << "& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target " << + "with a" << endl + << " * Xerces-C++ DOM error handler." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to an existing xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to an existing Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A Xerces-C++ DOM document." << endl + << " * @param x An object model to serialize." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * Note that it is your responsibility to create the " << + "DOM document" << endl + << " * with the correct root element as well as set the " << + "necessary" << endl + << " * namespace mapping attributes." << endl + << " */" << endl; + } + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::DOMDocument& d," << endl + << "const " << type_name (e) << "& x," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to a new xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a new Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param f Serialization flags." << endl + << " * @return A pointer to the new Xerces-C++ DOM document." << endl + << " */" << endl; + } + + os << inst_exp + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument >" << endl + << name << " (const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + + } + + void + generate_serialization_header (Context& ctx) + { + bool elemen_type (ctx.options.generate_element_type ()); + + if (!elemen_type) + ctx.os << "#include <iosfwd>" << endl + << endl + << "#include <xercesc/dom/DOMDocument.hpp>" << endl + << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl + << "#include <xercesc/framework/XMLFormatter.hpp>" << endl + << endl + << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + ElementType element_type (ctx); + ElementFunction element_function (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (elemen_type) + names >> element_type; + else + names >> element_function; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/serialization-header.hxx b/xsd/cxx/tree/serialization-header.hxx new file mode 100644 index 0000000..08c58ab --- /dev/null +++ b/xsd/cxx/tree/serialization-header.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/serialization-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_SERIALIZATION_HEADER_HXX +#define XSD_CXX_TREE_SERIALIZATION_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_serialization_header (Context&); + } +} + +#endif // XSD_CXX_TREE_SERIALIZATION_HEADER_HXX diff --git a/xsd/cxx/tree/serialization-source.cxx b/xsd/cxx/tree/serialization-source.cxx new file mode 100644 index 0000000..08b81d6 --- /dev/null +++ b/xsd/cxx/tree/serialization-source.cxx @@ -0,0 +1,1499 @@ +// file : xsd/cxx/tree/serialization-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/serialization-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + enum schema_type + { + st_other, + st_double, + st_decimal + }; + + enum schema_type + schema_type (SemanticGraph::Type& t) + { + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + return st_double; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + return st_decimal; + else + return st_other; + } + + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with type factory map. If this type is anonymous + // but substitutes, then it will be registered as part of the + // substitution registration. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with type factory map. If this type is anonymous + // but substitutes, then it will be registered as part of the + // substitution registration. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // Register with type factory map. If this type is anonymous + // but substitutes, then it will be registered as part of the + // substitution registration. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (e.scope ())); + + bool ordered (ordered_p (c)); + + String const& aname (eaname (e)); + String ns (e.qualified_p () ? e.namespace_ ().name () : ""); + String type (scope + L"::" + etype (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + os << "// " << comment (e.name ()) << endl + << "//" << endl; + + if (ordered) + os << "case " << scope << "::" << + e.context ().get<String> ("ordered-id-name") << ":" + << "{"; + + if (poly) + { + os << (ordered ? "" : "{") + << "::xsd::cxx::tree::type_serializer_map< " << char_type + << " >& tsm (" << endl + << "::xsd::cxx::tree::type_serializer_map_instance< " << + poly_plate << ", " << char_type << " > ());" + << endl; + } + + if (max (e) != 1) + { + // sequence + // + // Always pass the sequence element reference to typeid() to + // suppress the Clang's 'expression with side effects will be + // evaluated despite being used as an operand to typeid' warning. + // + if (ordered) + os << "const " << type << "& x (i." << aname << + " ()[b->index]);" + << endl; + else + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{" + << "const " << type << "& x (*b);" << endl; + + if (poly) + { + os << "if (typeid (" << type << ") == typeid (x))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << x;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, x);"; + } + else + { + os << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << x;"; + break; + } + case st_double: + { + os << "s << " << as_double_type << " (x);"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << " (x);"; + break; + } + } + } + } + else if (min (e) == 0) + { + // optional + // + if (!ordered) + os << "if (i." << aname << " ())" + << "{"; + + if (poly) + { + os << "const " << type << "& x (*i." << aname << " ());" + << "if (typeid (" << type << ") == typeid (x))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << x;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, x);"; + } + else + { + os << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << *i." << aname << " ();"; + break; + } + case st_double: + { + os << "s << " << as_double_type << "(*i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << "(*i." << aname << " ());"; + break; + } + } + } + } + else + { + // one + // + if (poly) + { + os << "const " << type << "& x (i." << aname << " ());" + << "if (typeid (" << type << ") == typeid (x))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << x;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, x);"; + } + else + { + if (!ordered) + os << "{"; + + os << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << i." << aname << " ();"; + break; + } + case st_double: + { + os << "s << " << as_double_type << "(i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << "(i." << aname << " ());"; + break; + } + } + } + } + + if (ordered) + { + // See comment for bool text (false); below. + // + if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) + os << "text = true;"; + + os << "continue;" + << "}"; + } + else + { + os << "}"; + + if (poly && (max (e) != 1 || min (e) == 0)) + os << "}"; // There is no extra block for poly one. + } + } + + private: + String scope; + }; + + struct Any: Traversal::Any, Context + { + Any (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual void + traverse (Type& a) + { + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + bool ordered (ordered_p (c)); + + String const& aname (eaname (a)); + + os << "// " << ename (a) << endl + << "//" << endl; + + if (ordered) + os << "case " << scope << "::" << + a.context ().get<String> ("ordered-id-name") << ":"; + + if (max (a) != 1) + { + // sequence + // + if (!ordered) + os << "for (" << scope << "::" << econst_iterator (a) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)"; + + os << "{" + << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << + "::DOMElement* > (&(" << + (ordered ? (L"i." + aname + L" ()[b->index]") : L"*b") << + ")), true));"; + } + else if (min (a) == 0) + { + // optional + // + if (!ordered) + os << "if (i." << aname << " ())"; + + os << "{" + << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." << + aname << " ())), true));"; + } + else + { + // one + // + if (ordered) + os << "{"; + + os << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." << + aname << " ())), true));" + << endl; + } + + if (ordered) + { + // See comment for bool text (false); below. + // + if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) + os << "text = true;"; + + os << "continue;"; + } + + if (ordered || max (a) != 1 || min (a) == 0) + os << "}"; + } + + private: + String scope; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual void + traverse (Type& a) + { + String const& aname (eaname (a)); + String ns (a.qualified_p () ? a.namespace_ ().name () : ""); + + os << "// " << comment (a.name ()) << endl + << "//" << endl; + + if (a.optional_p () && !a.default_p ()) + { + os << "if (i." << aname << " ())" + << "{" + << xerces_ns << "::DOMAttr& a (" << endl + << "::xsd::cxx::xml::dom::create_attribute (" << endl + << strlit (a.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (a.type ())) + { + case st_other: + { + os << "a << *i." << aname << " ();"; + break; + } + case st_double: + { + os << "a << " << as_double_type << "(*i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "a << " << as_decimal_type << "(*i." << aname << " ());"; + break; + } + } + + os << "}"; + } + else + { + // Make sure we serialize required fixed attributes. + // + if (a.optional_p () && options.omit_default_attributes ()) + { + os << "if (i." << aname << " () != " << scope << + "::" << edefault_value (a) << " ())"; + } + + os << "{" + << xerces_ns << "::DOMAttr& a (" << endl + << "::xsd::cxx::xml::dom::create_attribute (" << endl + << strlit (a.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (a.type ())) + { + case st_other: + { + os << "a << i." << aname << " ();"; + break; + } + case st_double: + { + os << "a << " << as_double_type << "(i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "a << " << as_decimal_type << "(i." << aname << " ());"; + break; + } + } + + os << "}"; + } + } + + private: + String scope; + }; + + struct AnyAttribute: Traversal::AnyAttribute, Context + { + AnyAttribute (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual void + traverse (Type& a) + { + String const& aname (eaname (a)); + + os << "// " << ename (a) << endl + << "//" << endl; + + os << "for (" << scope << "::" << econst_iterator (a) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{" + << xerces_ns << "::DOMAttr* a (" << endl + << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));" + << endl + << "if (a->getLocalName () == 0)" << endl + << "e.setAttributeNode (a);" + << "else" << endl + << "e.setAttributeNodeNS (a);" + << "}"; + } + + private: + String scope; + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual void + traverse (Type& c) + { + SemanticGraph::Context& ctx (c.context ()); + + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{"; + + if (c.inherits_p ()) + { + os << "e << static_cast< const "; + inherits (c, inherits_); + os << "& > (i);" + << endl; + } + else + os << "e << static_cast< const " << any_type << "& > (i);" + << endl; + + // Serialize anyAttribute content first so that is gets + // overriden by schema-defined attributes. + // + if (options.generate_wildcard ()) + { + AnyAttribute any_attribute (*this, name); + Traversal::Names names (any_attribute); + + Complex::names (c, names); + } + + { + bool o (ordered_p (c)); + size_t start (0), count (0); + + if (o) + { + start = ctx.get<size_t> ("ordered-start"); + count = ctx.get<size_t> ("ordered-count"); + + if (start != count) + { + String const& ci (ctx.get<String> ("order-const-iterator")); + String const& an (ctx.get<String> ("order-aname")); + + // If we have mixed content and a base, then we have to + // skip the text content until we serialize one of "our" + // elements. + // + if (mixed_p (c) && start != 1) + os << "bool text (false);" + << endl; + + os << "for (" << name << "::" << ci << endl + << "b (i." << an << " ().begin ()), n (i." << an << + " ().end ());" << endl + << "b != n; ++b)" + << "{" + << "switch (b->id)" + << "{"; + } + } + + Traversal::Names names; + Any any (*this, name); + Element element (*this, name); + + names >> element; + + if (options.generate_wildcard ()) + names >> any; + + Complex::names (c, names); + + if (o) + { + if (start != count) + { + if (mixed_p (c)) + { + //@@ propagate mixed-ordered-id to derived + + os << "// text_content" << endl + << "//" << endl + << "case " << name << "::" << + ctx.get<String> ("mixed-ordered-id-name") << ":" + << "{"; + + // See the comment above. + // + if (start != 1) + os << "if (text)" << endl; + + os << "e.appendChild (" << endl + << "e.getOwnerDocument ()->createTextNode (" << endl + << "::xsd::cxx::xml::string (" << endl + << "i." << ctx.get<String> ("mixed-aname") << + " ()[b->index].c_str ()).c_str ()));"; + + // os << "e << i." << ctx.get<String> ("mixed-aname") << + // " ()[b->index];"; + + os << "continue;" + << "}"; + } + + // Ignore content before our id range and stop serializing + // if we see anything past. This handles inheritance. + // + os << "default:" + << "{"; + + if (start != 1) + os << "if (b->id < " << start << "UL)" << endl + << "continue;"; + + os << "break;" // Stop (see break below). + << "}"; + + os << "}" // switch + << "break;" // Unknown element past our elements. + << "}"; // for + } + } + } + + { + Attribute attribute (*this, name); + Traversal::Names names (attribute); + Complex::names (c, names); + } + + os << "}"; + + bool simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + bool hb (c.inherits_p ()); + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&" << + (hb ? " a" : "") << ", " << + "const " << name << "&" << (hb ? " i" : "") << ")" + << "{"; + + if (hb) + { + os << "a << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);"; + } + + os << "}"; + + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "&" << + (hb ? " l" : "") << "," << endl + << "const " << name << "&" << (hb ? " i" : "") << ")" + << "{"; + + if (hb) + { + os << "l << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);"; + } + + os << "}"; + } + + // Register with type factory map. If this type is anonymous + // but substitutes, then it will be registered as part of the + // substitution registration. + // + if (polymorphic && + polymorphic_p (c) && + !c.abstract_p () && + !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + + + // Generate substitution group map entry. + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c), type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual void + traverse (Type& e) + { + // Similar to parsing, we cannot just omit this element if it's + // abstract because it may serve as a "link" between the root of the + // substitution group and a non-abstract element that uses this + // element as its root (see + // element_serializer_map::find_substitution() for details). + // + if (polymorphic && e.substitutes_p ()) + { + SemanticGraph::Type& t (e.type ()); + + // Check if this element is abstract. + // + bool abst; + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + Type& r (e.substitutes ().root ()); + + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::element_serializer_initializer< " << + poly_plate << ", " << char_type << ", "; + + belongs (e, belongs_); + + os << " >" << endl + << "_xsd_" << name << "_element_serializer_init (" << endl + << strlit (r.name ()) << "," << endl + << strlit (r.namespace_ ().name ()) << "," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_ ().name ()) << "," << endl; + + if (abst) + os << "0"; + else + { + os << "&::xsd::cxx::tree::serializer_impl< "; + belongs (e, belongs_); + os << " >"; + } + + os << ");" + << endl + << endl; + } + } + + private: + Traversal::Belongs belongs_; + MemberTypeName type_name_; + + }; + + struct ElementType: Traversal::Element, + GlobalElementBase, + Context + { + ElementType (Context& c) + : GlobalElementBase (c), + Context (c), + element_map_ (c.options.generate_element_map ()) + { + } + + virtual void + traverse (Type& e) + { + if (doc_root_p (e)) + { + String const& name (ename (e)); + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << i." << eaname (e) << " ();" + << "}"; + + // Element map registration. + // + if (element_map_) + { + SemanticGraph::Context& ec (e.context ()); + String const& aname (ec.get<String> ("element-name")); + String const& ans (ec.get<String> ("element-ns")); + + os << "static " << endl + << "const ::xsd::cxx::tree::serializer_init< " << + name << ", " << char_type << ", " << any_type << " >" << endl + << "_xsd_" << name << "_serializer_init (" << + name << "::" << aname << " (), " << + name << "::" << ans << " ());" + << endl; + } + } + } + + private: + bool element_map_; + }; + + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eserializer (e)); + String ns (e.namespace_ ().name ()); + String const& error_handler (error_handler_type); + String const& namespace_infomap (namespace_infomap_type); + + SemanticGraph::Type& type (e.type ()); + + // Note that I am using fq-name in function calls because g++ gets + // confused if the name is 'type'. (see tests/schema/anonymous) + // + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. + // + bool poly (polymorphic && + polymorphic_p (type) && + !anonymous_p (type)); + + // To std::ostream. + // + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << + char_type << " > > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << error_handler << "& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + // To XMLFormatTarget. + // + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << + char_type << " > > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << error_handler << "& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + // To an existing DOM instance. + // + os << "void" << endl + << name << " (" << xerces_ns << "::DOMDocument& d," << endl + << "const " << type_name (e) << "& s," << endl + << flags_type << ")" + << "{" + << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl; + + if (poly) + { + os << "if (typeid (" << type_name (e) << ") == typeid (s))" + << "{"; + } + + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (ns) << ")" + << "{"; + + switch (schema_type (type)) + { + case st_other: + { + os << "e << s;"; + break; + } + case st_double: + { + os << "e << " << as_double_type << "(s);"; + break; + } + case st_decimal: + { + os << "e << " << as_decimal_type << "(s);"; + break; + } + } + + os << "}" + << "else" + << "{" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << ");" + << "}"; + + if (poly) + { + os << "}" + << "else" + << "{" + << "::xsd::cxx::tree::type_serializer_map_instance< " << + poly_plate << ", " << char_type << " > ().serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "e, n, s);" + << "}"; + } + + os << "}"; + + + // To a new DOM instance. + // + os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl + << name << " (const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << flags_type << " f)" + << "{"; + + if (poly) + { + os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;" + << endl + << "if (typeid (" << type_name (e) << ") == typeid (s))" + << "{" + << "d = ::xsd::cxx::xml::dom::serialize< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << "m, f);" + << "}" + << "else" + << "{" + << "d = ::xsd::cxx::tree::type_serializer_map_instance< " << + poly_plate << ", " << char_type << " > ().serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "m, s, f);" + << "}"; + } + else + { + os << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::serialize< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << "m, f));" + << endl; + } + + os << fq_name (e, "serializer") << " (*d, s, f);" + << "return d;" + << "}"; + + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + void + generate_serialization_source (Context& ctx, size_t first, size_t last) + { + bool elemen_type (ctx.options.generate_element_type ()); + + if (!elemen_type) + ctx.os << "#include <ostream>" << endl + << "#include <xsd/cxx/tree/error-handler.hxx>" << endl; + + ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl + << endl; + + if (ctx.polymorphic) + { + ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl + << endl; + + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "type_serializer_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "type_serializer_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "type_serializer_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "type_serializer_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{" + << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "type_serializer_plate_init;" + << "}"; + } + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + ElementType element_type (ctx); + ElementFunction element_function (ctx); + + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + names >> element; + + if (elemen_type) + names >> element_type; + else + names >> element_function; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/serialization-source.hxx b/xsd/cxx/tree/serialization-source.hxx new file mode 100644 index 0000000..75e57f3 --- /dev/null +++ b/xsd/cxx/tree/serialization-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/serialization-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX +#define XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_serialization_source (Context&, size_t first, size_t last); + } +} + +#endif // XSD_CXX_TREE_SERIALIZATION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/cxx/tree/stream-extraction-source.cxx new file mode 100644 index 0000000..5a5ed66 --- /dev/null +++ b/xsd/cxx/tree/stream-extraction-source.cxx @@ -0,0 +1,864 @@ +// file : xsd/cxx/tree/stream-extraction-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-extraction-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + size_t n (0); + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); + i != st.end (); ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (s, f, c)," << endl + << " " << base << " (s, f, this)" + << "{" + << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (l) && + (!anonymous_p (l) || anonymous_substitutes_p (l))) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + size_t n (0); + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, f, c)" + << "{" + << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (u) && + (!anonymous_p (u) || anonymous_substitutes_p (u))) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* base_enum (0); + IsEnumBasedType t (base_enum); + t.dispatch (e); + + enum_based = (base_enum != 0); + } + + String value; + if (string_based) + value = evalue (e); + + size_t n (0); + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": "; + + inherits (e, inherits_base_); + + if (string_based && !enum_based) + { + // Use copy c-tor to pass the flags and container. + // + os << " (" << endl; + inherits (e, inherits_base_); + os << " (_xsd_" << name << "_literals_[s.read_uint ()]), f, c)"; + } + else + os << " (s, f, c)"; + + os << "{"; + + if (string_based) + os << "_xsd_" << name << "_convert ();"; + + os << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (e) && + (!anonymous_p (e) || anonymous_substitutes_p (e))) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct CtorMember: Traversal::Member, Context + { + CtorMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + os << "," << endl + << " " << emember (m) << " (this)"; + } + }; + + struct CtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CtorAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& stream_) + : Context (c), stream (stream_) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + SemanticGraph::Type& t (e.type ()); + String type (etype (e)); + String tr (etraits (e)); // traits type name + + bool fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (t); + } + + // Figure out if we need to generate polymorphic code. If this + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. + // + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + // Check if this element is abstract. + // + bool abst (false); + if (poly) + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + char const* r ( + (poly || !fund) && std >= cxx_version::cxx11 + ? "::std::move (r)" + : "r"); + + if (max (e) != 1) + { + // sequence + // + String container (econtainer (e)); + + os << "{" + << "::std::size_t n;" + << "::xsd::cxx::tree::istream_common::as_size< " << + "::std::size_t > as (n);" + << "s >> as;" + << "if (n > 0)" + << "{" + << container << "& c (this->" << member << ");" + << "c.reserve (n);" + << "while (n--)" + << "{"; + + if (poly) + { + os << auto_ptr << "< " << type << " > r;"; + + if (!abst) + os << "bool d;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{"; + + os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();"; + + if (!abst) + os << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; + } + + os << "c.push_back (" << r << ");" + << "}" // while + << "}" // if + << "}"; + } + else if (min (e) == 0) + { + // optional + // + os << "{" + << "bool p;" + << "s >> p;" + << "if (p)" + << "{"; + + if (poly) + { + os << auto_ptr << "< " << type << " > r;"; + + if (!abst) + os << "bool d;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{"; + + os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();"; + + if (!abst) + os << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; + } + + os << "this->" << member << ".set (" << r << ");" + << "}" // if (p) + << "}"; + } + else + { + // one + // + os << "{"; + + if (poly) + { + os << auto_ptr << "< " << type << " > r;"; + + if (!abst) + os << "bool d;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{"; + + os << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();"; + + if (!abst) + os << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (s, f, this));"; + } + + os << "this->" << member << ".set (" << r << ");" + << "}"; + } + } + + private: + String stream; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + String type (etype (a)); + String tr (etraits (a)); // traits type name + + bool fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (a.type ()); + } + + if (a.optional_p () && !a.default_p ()) + { + os << "{" + << "bool p;" + << "s >> p;" + << "if (p)" + << "{"; + + if (fund) + { + os << type << " r;" + << "s >> r;" + << "this->" << member << ".set (r);"; + } + else + { + os << "this->" << member << ".set (" << tr << + "::create (s, f, this));"; + } + + os << "}" // if (p) + << "}"; + } + else + { + os << "{"; + + if (fund) + { + os << type << " r;" + << "s >> r;" + << "this->" << member << ".set (r);"; + } + else + { + os << "this->" << member << ".set (" << tr << + "::create (s, f, this));"; + } + + os << "}"; + } + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c), ctor_any_ (c), ctor_member_ (c) + { + inherits_ >> base_; + names_ctor_member_ >> ctor_member_; + + if (options.generate_wildcard ()) + names_ctor_member_ >> ctor_any_; + } + + virtual void + traverse (Type& c) + { + SemanticGraph::Context& ctx (c.context ()); + + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + bool has_members (has<Traversal::Member> (c)); + + bool facets (false); + if (c.inherits_p ()) + { + // See if we have any facets that we need to handle. + // + using SemanticGraph::Restricts; + using SemanticGraph::Fundamental::Decimal; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty () && + (r->facet_find ("fractionDigits") != r->facet_end () || + r->facet_find ("totalDigits") != r->facet_end ()) && + ultimate_base (c).is_a<Decimal> ()) + facets = true; + } + } + + size_t n (0); + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": "; + + if (c.inherits_p ()) + inherits (c, inherits_); + else + os << any_type; + + os << " (s, f, c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, names_ctor_member_); + + os << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);" + << endl; + + if (has_members) + os << "this->" << unclash (name, "parse") << " (s, f);"; + + os << "}"; + + // Parse + // + if (ordered || has_members) + { + os << "void " << name << "::" << endl + << unclash (name, "parse") << " (" << + istream_type << "< " << i->c_str () << " >& s," << endl + << flags_type << " f)" + << "{" + << "XSD_UNUSED (f);"; // Can be unused. + + // Read the order sequence. + // + if (ordered) + { + String const& t (ctx.get<String> ("order-type")); + String const& m (ctx.get<String> ("order-member")); + + os << "{" + << "::std::size_t n;" + << "::xsd::cxx::tree::istream_common::as_size< " << + "::std::size_t > na (n);" + << "s >> na;" + << "if (n > 0)" + << "{" + << "this->" << m << ".reserve (n);" + << "while (n--)" + << "{" + << "::std::size_t id, in;" + << "::xsd::cxx::tree::istream_common::as_size< " << + "::std::size_t > ida (id), ina (in);" + << "s >> ida;" + << "s >> ina;" + << "this->" << m << ".push_back (" << t << " (id, in));" + << "}" // while + << "}" // if + << "}"; + } + + { + Element element (*this, *i); + Attribute attribute (*this); + Traversal::Names names_; + + names_ >> element; + names_ >> attribute; + + names (c, names_); + } + + os << "}"; + } + + + // Register with type map. + // + if (polymorphic && + polymorphic_p (c) && + !c.abstract_p () && + (!anonymous_p (c) || anonymous_substitutes_p (c))) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + + CtorAny ctor_any_; + CtorMember ctor_member_; + + Traversal::Names names_ctor_member_; + }; + } + + void + generate_stream_extraction_source (Context& ctx) + { + if (ctx.polymorphic) + { + NarrowStrings const& st (ctx.options.generate_extraction ()); + + ctx.os << "#include <xsd/cxx/tree/stream-extraction-map.hxx>" << endl + << endl; + + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{"; + + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream (*i); + + ctx.os << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "stream_extraction_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "stream_extraction_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "stream_extraction_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;" + << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "stream_extraction_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;" + << "#endif" << endl; + } + + ctx.os << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + + } + + ctx.os << "namespace _xsd" + << "{"; + + size_t n (0); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream (*i); + + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_plate< " << + ctx.poly_plate << ", " << stream << ", " << ctx.char_type << + " >" << endl + << "stream_extraction_plate_init_" << n++ << ";"; + } + + ctx.os << "}"; + } + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/stream-extraction-source.hxx b/xsd/cxx/tree/stream-extraction-source.hxx new file mode 100644 index 0000000..8b58491 --- /dev/null +++ b/xsd/cxx/tree/stream-extraction-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/stream-extraction-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_EXTRACTION_SOURCE_HXX +#define XSD_CXX_TREE_EXTRACTION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_stream_extraction_source (Context&); + } +} + +#endif // XSD_CXX_TREE_EXTRACTION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-header.cxx b/xsd/cxx/tree/stream-header.cxx new file mode 100644 index 0000000..c8243c9 --- /dev/null +++ b/xsd/cxx/tree/stream-header.cxx @@ -0,0 +1,181 @@ +// file : xsd/cxx/tree/stream-header.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + // If we are based on an enum then the value type is just an + // alias and we don't need to generate this operator again. + // + if (string_based && !enum_based) + { + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, " << + name << "::" << evalue (e) << ");" + << endl; + } + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + } + + void + generate_stream_header (Context& ctx) + { + String c (ctx.char_type); + + ctx.os << "#include <iosfwd>" << endl + << endl; + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/stream-header.hxx b/xsd/cxx/tree/stream-header.hxx new file mode 100644 index 0000000..58481c2 --- /dev/null +++ b/xsd/cxx/tree/stream-header.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/stream-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_HEADER_HXX +#define XSD_CXX_TREE_STREAM_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_stream_header (Context&); + } +} + +#endif // XSD_CXX_TREE_STREAM_HEADER_HXX diff --git a/xsd/cxx/tree/stream-insertion-header.cxx b/xsd/cxx/tree/stream-insertion-header.cxx new file mode 100644 index 0000000..9eb4bc4 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-header.cxx @@ -0,0 +1,178 @@ +// file : xsd/cxx/tree/stream-insertion-header.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-insertion-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + } + + void + generate_stream_insertion_header (Context& ctx) + { + String c (ctx.char_type); + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/stream-insertion-header.hxx b/xsd/cxx/tree/stream-insertion-header.hxx new file mode 100644 index 0000000..597bea0 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-header.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/stream-insertion-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX +#define XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_stream_insertion_header (Context&); + } +} + +#endif // XSD_CXX_TREE_STREAM_INSERTION_HEADER_HXX diff --git a/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/cxx/tree/stream-insertion-source.cxx new file mode 100644 index 0000000..08391ef --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-source.cxx @@ -0,0 +1,623 @@ +// file : xsd/cxx/tree/stream-insertion-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-insertion-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + size_t n (0); + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{" + << "return s << static_cast< const " << base << "& > (x);" + << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (l) && + (!anonymous_p (l) || anonymous_substitutes_p (l))) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + size_t n (0); + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{" + << "return s << static_cast< const " << base << "& > (x);" + << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (u) && + (!anonymous_p (u) || anonymous_substitutes_p (u))) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* base_enum (0); + IsEnumBasedType t (base_enum); + t.dispatch (e); + + enum_based = (base_enum != 0); + } + + String value; + if (string_based) + value = evalue (e); + + size_t n (0); + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{"; + + if (!string_based || enum_based) + { + os << "return s << static_cast< const "; + inherits (e, inherits_base_); + os << "& > (x);"; + } + else + { + os << name << "::" << value << " v (x);" + << "return s << static_cast< unsigned int > (v);"; + } + + os << "}"; + + // Register with type map. + // + if (polymorphic && + polymorphic_p (e) && + (!anonymous_p (e) || anonymous_substitutes_p (e))) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_, String const& stream_) + : Context (c), scope (scope_), stream (stream_) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) return; + + String const& aname (eaname (e)); + SemanticGraph::Type& t (e.type ()); + String type (scope + L"::" + etype (e)); + + // Figure out if we need to generate polymorphic code. If this + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. + // + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + // Check if this element is abstract. + // + bool abst (false); + if (poly) + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + if (max (e) != 1) + { + // sequence + // + os << "{" + << "const " << scope << "::" << econtainer (e) << "& c (" << + "x." << aname << " ());" + << "s << ::xsd::cxx::tree::ostream_common::as_size< " << + "::std::size_t > (c.size ());"; + + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "i (c.begin ()), e (c.end ());" << endl + << "i != e; ++i)" + << "{"; + + if (poly) + { + if (!abst) + os << "bool d (typeid (" << type << ") != typeid (*i));" + << "s << d;" + << "if (!d)" << endl + << "s << *i;" + << "else" << endl; + + os << "::xsd::cxx::tree::stream_insertion_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().insert (s, *i);"; + } + else + os << "s << *i;"; + + os << "}" // for + << "}"; + } + else if (min (e) == 0) + { + // optional + // + os << "{" + << "bool p (x." << aname << " ());" + << "s << p;" + << "if (p)"; + + if (poly) + { + os << "{" + << "const " << type << "& i (*x." << aname << " ());"; + + if (!abst) + os << "bool d (typeid (" << type << ") != typeid (i));" + << "s << d;" + << "if (!d)" << endl + << "s << i;" + << "else" << endl; + + os << "::xsd::cxx::tree::stream_insertion_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().insert (s, i);" + << "}"; + } + else + os << endl + << "s << *x." << aname << " ();"; + + os << "}"; + } + else + { + // one + // + if (poly) + { + os << "{" + << "const " << type << "& i (x." << aname << " ());"; + + if (!abst) + os << "bool d (typeid (" << type << ") != typeid (i));" + << "s << d;" + << "if (!d)" << endl + << "s << i;" + << "else" << endl; + + os << "::xsd::cxx::tree::stream_insertion_map_instance< " << + poly_plate << ", " << stream << ", " << char_type << + " > ().insert (s, i);" + << "}"; + } + else + os << "s << x." << aname << " ();"; + } + } + + private: + String scope; + String stream; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& aname (eaname (a)); + + if (a.optional_p () && !a.default_p ()) + { + os << "{" + << "bool p (x." << aname << " ());" + << "s << p;" + << "if (p)" << endl + << "s << *x." << aname << " ();" + << "}"; + } + else + { + os << "s << x." << aname << " ();"; + } + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual void + traverse (Type& c) + { + SemanticGraph::Context& ctx (c.context ()); + + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + bool has_body (ordered || + has<Traversal::Member> (c) || + c.inherits_p ()); + + size_t n (0); + NarrowStrings const& st (options.generate_insertion ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "&" << (has_body ? " x" : "") << ")" + << "{"; + + if (c.inherits_p ()) + { + os << "s << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (x);"; + } + + // Write the order sequence. + // + if (ordered) + { + String const& ci (ctx.get<String> ("order-const-iterator")); + String const& an (ctx.get<String> ("order-aname")); + + os << "s << ::xsd::cxx::tree::ostream_common::as_size< " << + "::std::size_t > (" << endl + << "x." << an << " ().size ());" + << endl + << "for (" << name << "::" << ci << endl + << "b (x." << an << " ().begin ()), n (x." << an << + " ().end ());" << endl + << "b != n; ++b)" + << "{" + << "s << ::xsd::cxx::tree::ostream_common::as_size< " << + "::std::size_t > (b->id);" + << "s << ::xsd::cxx::tree::ostream_common::as_size< " << + "::std::size_t > (b->index);" + << "}"; + } + + { + Traversal::Names names_member; + Element element (*this, name, *i); + Attribute attribute (*this); + + names_member >> element; + names_member >> attribute; + + names (c, names_member); + } + + os << "return s;" + << "}"; + + + // Register with type map. + // + if (polymorphic && + polymorphic_p (c) && + !c.abstract_p () && + (!anonymous_p (c) || anonymous_substitutes_p (c))) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + poly_plate << ", " << i->c_str () << ", " << char_type << + ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + } + + void + generate_stream_insertion_source (Context& ctx) + { + if (ctx.polymorphic) + { + NarrowStrings const& st (ctx.options.generate_insertion ()); + + ctx.os << "#include <xsd/cxx/tree/stream-insertion-map.hxx>" << endl + << endl; + + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{"; + + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream (*i); + + ctx.os << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "stream_insertion_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "stream_insertion_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "stream_insertion_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;" + << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "stream_insertion_plate< " << ctx.poly_plate << ", " << + stream << ", " << ctx.char_type << " >;" + << "#endif" << endl; + } + + ctx.os << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{"; + + size_t n (0); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + String stream (*i); + + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_plate< " << + ctx.poly_plate << ", " << stream << ", " << ctx.char_type << + " >" << endl + << "stream_insertion_plate_init_" << n++ << ";"; + } + + ctx.os << "}"; + } + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/stream-insertion-source.hxx b/xsd/cxx/tree/stream-insertion-source.hxx new file mode 100644 index 0000000..ace8bf6 --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/stream-insertion-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_INSERTION_SOURCE_HXX +#define XSD_CXX_TREE_INSERTION_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_stream_insertion_source (Context&); + } +} + +#endif // XSD_CXX_TREE_INSERTION_SOURCE_HXX diff --git a/xsd/cxx/tree/stream-source.cxx b/xsd/cxx/tree/stream-source.cxx new file mode 100644 index 0000000..eeb3ca3 --- /dev/null +++ b/xsd/cxx/tree/stream-source.cxx @@ -0,0 +1,496 @@ +// file : xsd/cxx/tree/stream-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/stream-source.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && + polymorphic_p (l) && + (!anonymous_p (l) || anonymous_substitutes_p (l))) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const " << xs_string_type << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && + polymorphic_p (u) && + (!anonymous_p (u) || anonymous_substitutes_p (u))) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + // If we are based on an enum then the value type is just an + // alias and we don't need to generate this operator again. + // + if (string_based && !enum_based) + { + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + name << "::" << evalue (e) << " i)" + << "{" + << "return o << " << name << "::_xsd_" << name << + "_literals_[i];" + << "}"; + } + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && + polymorphic_p (e) && + (!anonymous_p (e) || anonymous_substitutes_p (e))) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (poly) + { + os << "{" + << "::xsd::cxx::tree::std_ostream_map< " << char_type + << " >& om (" << endl + << "::xsd::cxx::tree::std_ostream_map_instance< " << + poly_plate << ", " << char_type << " > ());" + << endl; + } + + if (max (e) != 1) + { + // sequence + // + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "b (i." << aname << " ().begin ()), " << + "e (i." << aname << " ().end ());" << endl + << "b != e; ++b)" + << "{" + << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << *b;"; + else + os << ";" + << "om.insert (o, *b);"; + + os << "}"; + } + else if (min (e) == 0) + { + // optional + // + + os << "if (i." << aname << " ())" + << "{" + << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << *i." << aname << " ();"; + else + os << ";" + << "om.insert (o, *i." << aname << " ());"; + + os << "}"; + } + else + { + // one + // + os << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << i." << aname << " ();"; + else + os << ";" + << "om.insert (o, i." << aname << " ());"; + } + + if (poly) + os << "}"; + } + + private: + String scope; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& aname (eaname (a)); + + if (a.optional_p () && !a.default_p ()) + { + os << "if (i." << aname << " ())" + << "{" + << "o << ::std::endl << " << strlit (a.name () + L": ") << + " << *i." << aname << " ();" + << "}"; + } + else + { + os << "o << ::std::endl << " << strlit (a.name () + L": ") << + " << i." << aname << " ();"; + } + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // + // + bool has_body (has<Traversal::Member> (c) || c.inherits_p ()); + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "&" << (has_body ? " i" : "") << ")" + << "{"; + + if (c.inherits_p ()) + { + os << "o << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);" + << endl; + } + + { + Traversal::Names names_member; + Element element (*this, name); + Attribute attribute (*this); + + names_member >> element; + names_member >> attribute; + + names (c, names_member); + } + + os << "return o;" + << "}"; + + // Register with ostream map. + // + if (polymorphic && + polymorphic_p (c) && + !c.abstract_p () && + (!anonymous_p (c) || anonymous_substitutes_p (c))) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + } + + void + generate_stream_source (Context& ctx, size_t first, size_t last) + { + String c (ctx.char_type); + + ctx.os << "#include <ostream>" << endl + << endl; + + if (ctx.polymorphic) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-map.hxx>" << endl + << endl; + + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "std_ostream_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "std_ostream_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "std_ostream_plate< " << ctx.poly_plate << ", " << ctx.char_type << + " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "std_ostream_plate< " << ctx.poly_plate << ", " << ctx.char_type << + " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{" + << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "std_ostream_plate_init;" + << "}"; + } + + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/stream-source.hxx b/xsd/cxx/tree/stream-source.hxx new file mode 100644 index 0000000..b2b4d5d --- /dev/null +++ b/xsd/cxx/tree/stream-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/stream-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_STREAM_SOURCE_HXX +#define XSD_CXX_TREE_STREAM_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_stream_source (Context&, size_t first, size_t last); + } +} + +#endif // XSD_CXX_TREE_STREAM_SOURCE_HXX diff --git a/xsd/cxx/tree/tree-forward.cxx b/xsd/cxx/tree/tree-forward.cxx new file mode 100644 index 0000000..b715abe --- /dev/null +++ b/xsd/cxx/tree/tree-forward.cxx @@ -0,0 +1,325 @@ +// file : xsd/cxx/tree/tree-forward.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd/cxx/tree/tree-forward.hxx> +#include <xsd/cxx/tree/fundamental-header.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String const& name (ename (l)); + + if (String custom = custom_type (l)) + { + String new_name; + renamed_type (l, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String const& name (ename (u)); + + if (String custom = custom_type (u)) + { + String new_name; + renamed_type (u, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + String const& name (ename (e)); + + if (String custom = custom_type (e)) + { + String new_name; + renamed_type (e, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + String const& name (ename (c)); + + if (String custom = custom_type (c)) + { + String new_name; + renamed_type (c, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + } + + void + generate_forward (Context& ctx) + { + NarrowString xml_schema (ctx.options.extern_xml_schema ()); + + // Inlcude or Emit fundamental types. + // + if (xml_schema) + { + String name (ctx.hxx_expr->replace (xml_schema)); + + ctx.os << "#include " << ctx.process_include_path (name) << endl + << endl; + } + else + { + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/types.hxx>" << endl + << endl; + + if (!ctx.options.suppress_parsing () || + ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl + << endl; + } + + if (!ctx.options.suppress_parsing () || + ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + } + + bool element_map (ctx.options.generate_element_map ()); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl + << endl; + + // I need to include all the "optional" headers here (instead of + // later in the individual generators for each feature because + // those headers provide implementation for the fundamental types. + // + if (!ctx.options.suppress_parsing ()) + { + ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "parsing"); + + schema >> implies >> xsd >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl + << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "serialization"); + + schema >> implies >> xsd >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.generate_ostream ()) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl + << endl; + } + + NarrowStrings const& ist (ctx.options.generate_insertion ()); + if (!ist.empty ()) + { + for (NarrowStrings::const_iterator i (ist.begin ()); i != ist.end (); + ++i) + { + if (*i == "ACE_OutputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl + << endl; + } + + NarrowStrings const& est (ctx.options.generate_extraction ()); + if (!est.empty ()) + { + for (NarrowStrings::const_iterator i (est.begin ()); i != est.end (); + ++i) + { + if (*i == "ACE_InputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl + << endl; + } + + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + FundamentalNamespace ns (ctx); + + schema >> implies >> xsd >> names >> ns; + + schema.dispatch (ctx.schema_root); + } + + // First emit header includes. + // + if (ctx.options.generate_forward ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::forward); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + ctx.os << "// Forward declarations." << endl + << "//" << endl; + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + + ctx.os << endl; + } + } +} diff --git a/xsd/cxx/tree/tree-forward.hxx b/xsd/cxx/tree/tree-forward.hxx new file mode 100644 index 0000000..0610999 --- /dev/null +++ b/xsd/cxx/tree/tree-forward.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/tree-forward.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_FORWARD_HXX +#define XSD_CXX_TREE_TREE_FORWARD_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_forward (Context&); + } +} + +#endif // XSD_CXX_TREE_TREE_FORWARD_HXX diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx new file mode 100644 index 0000000..99a9b17 --- /dev/null +++ b/xsd/cxx/tree/tree-header.cxx @@ -0,0 +1,4337 @@ +// file : xsd/cxx/tree/tree-header.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-header.hxx> +#include <xsd/cxx/tree/default-value.hxx> +#include <xsd/cxx/tree/fundamental-header.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + // List mapping. + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + if (doxygen) + { + os << "/**" << endl + << " * @brief List class corresponding to the %" << + comment (l.name ()) << endl + << " * schema type." << endl + << " *" << endl + << " * This class has an interface of a standard C++ " << + "sequence (e.g.," << endl + << " * std::vector)." << endl; + + if (l.annotated_p ()) + { + os << " *" << endl; + write_annotation (l.annotation ()); + } + + os << " */" << endl; + } + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String item_name (item_type_name (item_type)); + String base_type (L"::xsd::cxx::tree::list< " + item_name + L", " + + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base_type += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + + base_type += L" >"; + + os << "class " << type_exp << name << + ": public " << any_simple_type << "," << endl + << " public " << base_type + << "{" + << "public:" << endl; + + // c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Creates an empty list." << endl + << " */" << endl; + } + os << name << " ();" + << endl; + + // c-tor (size_type, const X& x) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create a list with copies of the specified " << + "element." << endl + << " *" << endl + << " * @param n A number of elements to copy." << endl + << " * @param x An element to copy." << endl + << " *" << endl + << " * This constructor creates a list with @a n copies " << + "of @a x." << endl + << " */" << endl; + } + + String size_type (name != L"size_type" + ? String (L"size_type") + : base_type + L"::size_type"); + + os << name << " (" << size_type << " n, const " << item_name << + "& x);" + << endl; + + // c-tor (const I& begin, const I& end) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create a list from an iterator range." << endl + << " *" << endl + << " * @param begin An iterator pointing to the first " << + "element." << endl + << " * @param end An iterator pointing to the one past " << + "the last element." << endl + << " *" << endl + << " * This constructor creates a list consisting of " << + "copies of the" << endl + << " * elements in the range [begin,end)." << endl + << " */" << endl; + } + + String iter_type (unclash (name, "I")); + + os << "template < typename " << iter_type << " >" << endl + << name << " (const " << iter_type << "& begin, const " << + iter_type << "& end)" << endl + << ": " << base_type << " (begin, end, this)" + << "{" + << "}"; + + // c-tor (istream&) + // + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + os << "#ifdef XSD_CXX11" << endl + << name << "&" << endl + << "operator= (const " << name << "&) = default;" + << "#endif" << endl + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();"; + + os << "};"; + + // Comparison operators. + // + if (options.generate_comparison ()) + { + os << inst_exp + << "bool" << endl + << "operator== (const " << name << "&, const " << name << "&);" + << endl; + + os << inst_exp + << "bool" << endl + << "operator!= (const " << name << "&, const " << name << "&);" + << endl + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + // Union mapping. + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Union class corresponding to the %" << + comment (u.name ()) << endl + << " * schema type." << endl + << " *" << endl + << " * The mapping represents unions as strings." << endl; + + if (u.annotated_p ()) + { + os << " *" << endl; + write_annotation (u.annotation ()); + } + + os << " */" << endl; + } + + os << "class " << type_exp << name << + ": public " << xs_string_type + << "{" + << "public:" << endl + << endl; + + if (options.generate_default_ctor ()) + { + // c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor may leave the " << + "instance in an" << endl + << " * invalid state." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (const char*) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + os << name << " (const " << char_type << "* v);" + << endl; + + // c-tor (string const&) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + os << name << " (const " << string_type << "& v);" + << endl; + + // c-tor (istream&) + // + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + os << "#ifdef XSD_CXX11" << endl + << name << "&" << endl + << "operator= (const " << name << "&) = default;" + << "#endif" << endl + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + os << "};"; + } + }; + + // Enum mapping. + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (doxygen && e.annotated_p ()) + { + os << "/**" << endl; + write_annotation (e.annotation ()); + os << " */" << endl; + } + + os << ename (e); + } + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), + base_ (c), + member_ (c), + enumerator_ (c) + { + inherits_base_ >> base_; + inherits_member_ >> member_; + + names_ >> enumerator_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + SemanticGraph::Enumeration* base_enum (0); + + if (string_based) + { + IsEnumBasedType t (base_enum); + t.dispatch (e); + + if (base_enum != 0) + enum_based = true; + } + + String value; + if (string_based) + value = evalue (e); + + // Get to the ultimate base and see if is a fundamental type. + // + bool fund_based (false); + SemanticGraph::Type& ult_base (ultimate_base (e)); + { + IsFundamentalType t (fund_based); + t.dispatch (ult_base); + } + + // Count enumerators. + // + size_t enum_count (0); + + for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); + i != end; ++i) + ++enum_count; + + // + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Enumeration class corresponding to the %" << + comment (e.name ()) << endl + << " * schema type." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl; + } + + os << "class " << type_exp << name << ": public "; + + // Enumeration always has a base. + // + inherits (e, inherits_base_); + + os << "{" + << "public:" << endl; + + if (string_based) + { + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Underlying enum type." << endl + << " */" << endl; + } + + if (enum_based) + { + os << "typedef "; + + inherits (e, inherits_base_); + + os << "::" << evalue (*base_enum) << " " << value << ";" + << endl; + } + else + { + os << "enum " << value + << "{"; + + names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + + os << "};"; + } + } + + // default c-tor + // + bool list_based ( + ult_base.is_a<SemanticGraph::List> () || + ult_base.is_a<SemanticGraph::Fundamental::NameTokens> () || + ult_base.is_a<SemanticGraph::Fundamental::IdRefs> () || + ult_base.is_a<SemanticGraph::Fundamental::Entities> ()); + + if (options.generate_default_ctor () || list_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor may leave the " << + "instance in an" << endl + << " * invalid state." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (value) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "underlying enum value." << endl + << " *" << endl + << " * @param v A enum value." << endl + << " */" << endl; + } + + os << name << " (" << value << " v);" + << endl; + } + + // c-tor (const char*) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + + os << name << " (const " << char_type << "* v);" + << endl; + } + + // c-tor (const std::string&) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& v);" + << endl; + } + + // c-tor (fundamental) + // + if (fund_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a fundamental " << + "type value." << endl + << " *" << endl + << " * @param v A fundamental type value." << endl + << " */" << endl; + } + + os << name << " ("; + + member_.dispatch (ult_base); + + os << " v);" + << endl; + } + + // c-tor (base) + // + // If the ultimate is also our immediate base and it is a + // fundamental type then this c-tor clashes with c-tor + // (fundamental) above. + // + if (!fund_based || &ult_base != &e.inherits ().base ()) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "base value." << endl + << " *" << endl + << " * @param v A base value." << endl + << " */" << endl; + } + + os << name << " (const "; + + inherits (e, inherits_member_); + + os << "& v);" + << endl; + } + + + // c-tor (istream&) + // + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + os << "#ifdef XSD_CXX11" << endl + << name << "&" << endl + << "operator= (const " << name << "&) = default;" + << "#endif" << endl + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + // operator= (value) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Assign the underlying enum value." << endl + << " *" << endl + << " * @param v A enum value." << endl + << " * @return A refernce to the instance." << endl + << " */" << endl; + } + + os << name << "&" << endl + << "operator= (" << value << " v);" + << endl; + } + + // operator value () + // + // Name lookup differences in various compilers make generation + // of this operator outside of the class a really hard task. So + // we are going to make it "always inline". + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Implicit conversion operator to the " << + "underlying" << endl + << " * enum value." << endl + << " *" << endl + << " * @return A enum value." << endl + << " */" << endl; + } + + os << "virtual" << endl + << "operator " << value << " () const" + << "{" + << "return _xsd_" << name << "_convert ();" + << "}"; + } + + // + // + if (string_based) + { + if (doxygen) + os << "//@cond" << endl + << endl; + + os << "protected:" << endl + << value << endl + << "_xsd_" << name << "_convert () const;" + << endl; + + os << "public:" << endl; + + if (enum_based) + { + // We are going to reuse our base's literals. + // + os << "static const " << char_type << "* const* " << + "_xsd_" << name << "_literals_;"; + } + else + { + os << "static const " << char_type << "* const " << + "_xsd_" << name << "_literals_[" << enum_count << "];"; + } + + os << "static const " << value << + " _xsd_" << name << "_indexes_[" << enum_count << "];"; + + if (doxygen) + os << endl + << "//@endcond" << endl + << endl; + } + + os << "};"; + } + + virtual void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + + Traversal::Inherits inherits_member_; + MemberTypeName member_; + + Traversal::Names names_; + Enumerator enumerator_; + }; + + + // + // + struct MemberFunction: Traversal::Member, Context + { + MemberFunction (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& aname (eaname (m)); + String const& mname (emname (m)); + String kind (m.is_a<SemanticGraph::Element> () + ? "element" : "attribute"); + + bool fund (false); + { + IsFundamentalType t (fund); + t.dispatch (m.type ()); + } + + bool def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + String container (econtainer (m)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the element" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "element sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy elements from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "makes a copy and adds it " << endl + << " * to the sequence. Note that this operation " << + "completely changes the " << endl + << " * sequence and all old elements will be lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + String const& type (etype (m)); + String container (econtainer (m)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the " << kind << endl + << " * container." << endl + << " *" << endl + << " * @return A constant reference to the optional " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + kind << " container." << endl + << " *" << endl + << " * @return A reference to the optional container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the " << kind << "." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x An optional container with the new value " << + "to set." << endl + << " *" << endl + << " * If the value is present in @a x then this function " << + "makes a copy " << endl + << " * of this value and sets it as the new value of the " << + kind << "." << endl + << " * Otherwise the " << kind << " container is set " << + "the 'not present' state." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly instead" << endl + << " * of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << auto_ptr << "< " << type << " > p);" + << endl; + } + } + else + { + // one + // + String const& type (etype (m)); + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the " << kind << "." << endl + << " *" << endl + << " * @return A constant reference to the " << kind << + "." << endl + << " */" << endl; + } + + os << "const " << type << "&" << endl + << aname << " () const;" + << endl; + + // Do not generate modifiers for fixed attributes. + // + if (!(def_attr && m.fixed_p ())) + { + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + kind << "." << endl + << " *" << endl + << " * @return A reference to the " << kind << "." << endl + << " */" << endl; + } + + os << type << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the " << kind << "." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << auto_ptr << "< " << type << " > p);" + << endl; + + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Detach the " << kind << " value from " << + "the object model." << endl + << " *" << endl + << " * @return A pointer to the " << kind << " value." << endl + << " *" << endl + << " * Note that this function leaves the required " << + kind << " in " << endl + << " * the original object model uninitialized." << endl + << " */" << endl; + } + + os << auto_ptr << "< " << type << " >" << endl + << edname (m) << " ();" + << endl; + } + } + } + + // default_value + // + if (m.default_p ()) + { + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + bool lit (false); + { + IsLiteralValue test (lit); + test.dispatch (m.type ()); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the default value for the " << + kind << "." << endl + << " *" << endl; + + if (lit) + os << " * @return The " << kind << "'s default value." << endl; + else + os << " * @return A read-only (constant) reference to the " + << kind << "'s" << endl + << " * default value." << endl; + + os << " */" << endl; + } + + if (lit) + os << "static " << etype (m) << endl; + else + os << "static const " << etype (m) << "&" << endl; + + os << edefault_value (m) << " ();" + << endl; + } + } + } + }; + + struct AnyFunction: Traversal::Any, Context + { + AnyFunction (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + if (max (a) != 1) + { + // sequence + // + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy elements from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "makes a copy and adds" << endl + << " * it to the wildcard element sequence. Note that " << + "this operation" << endl + << " * completely changes the sequence and all old " << + "elements will be" << endl + << " * lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + else if (min (a) == 0) + { + // optional + // + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element container." << endl + << " *" << endl + << " * @return A constant reference to the optional " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element" << endl + << " * container." << endl + << " *" << endl + << " * @return A reference to the optional container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param e A new element to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new wildcard content." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e);" + << endl; + + // void + // name (type*); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content without copying." << endl + << " *" << endl + << " * @param p A new element to use." << endl + << " *" << endl + << " * This function will use the passed element " << + "directly instead" << endl + << " * of making a copy. For this to work the element " << + "should belong" << endl + << " * to the DOM document associated with this instance." << endl + << " *" << endl + << " * @see " << edom_document (c) << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << xerces_ns << "::DOMElement* p);" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param x An optional container with the new " << + "element to set." << endl + << " *" << endl + << " * If the element is present in @a x then this function " << + "makes a " << endl + << " * copy of this element and sets it as the new wildcard " << + "content." << endl + << " * Otherwise the element container is set the 'not " << + "present' state." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& x);" + << endl; + } + else + { + // one + // + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element." << endl + << " *" << endl + << " * @return A constant reference to the DOM element." << endl + << " */" << endl; + } + + os << "const " << xerces_ns << "::DOMElement&" << endl + << aname << " () const;" + << endl; + + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element." << endl + << " *" << endl + << " * @return A reference to the DOM element." << endl + << " */" << endl; + } + + os << xerces_ns << "::DOMElement&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param e A new element to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new wildcard content." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e);" + << endl; + + // void + // name (const*); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content without copying." << endl + << " *" << endl + << " * @param p A new element to use." << endl + << " *" << endl + << " * This function will use the passed element " << + "directly instead" << endl + << " * of making a copy. For this to work the element " << + "should belong" << endl + << " * to the DOM document associated with this instance." << endl + << " *" << endl + << " * @see " << edom_document (c) << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << xerces_ns << "::DOMElement* p);" + << endl; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the" << endl + << " * attribute set." << endl + << " *" << endl + << " * @return A constant reference to the set " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "attribute set." << endl + << " *" << endl + << " * @return A reference to the set container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy attributes from a given set." << endl + << " *" << endl + << " * @param s A set to copy elements from." << endl + << " *" << endl + << " * For each attribute in @a s this function " << + "makes a copy and adds" << endl + << " * it to the set. Note that this operation " << + "completely changes the " << endl + << " * set and all old attributes will be lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + }; + + // + // + struct Member: Traversal::Member, Context + { + Member (Context& c) + : Context (c), + type_name_ (c), + member_function_ (c) + { + belongs_ >> type_name_; + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (m.scope ())); + + String const& type (etype (m)); + bool el (m.is_a<SemanticGraph::Element> ()); + + bool def_attr (m.default_p () && !el); + + if (doxygen) + { + os << "/**" << endl + << " * @name " << comment (m.name ()) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the %" << + comment (m.name ()) << endl + << " * "; + + if (max (m) != 1) + { + os << "sequence element." << endl; + } + else if (min (m) == 0) + { + if (def_attr) + os << "optional attribute with a default value." << endl; + else + os << "optional " << (el ? "element." : "attribute.") << endl; + } + else + { + os << "required " << (el ? "element." : "attribute.") << endl; + } + + if (m.annotated_p ()) + { + os << " *" << endl; + write_annotation (m.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << comment (m.name ()) << endl + << "//" << endl; + } + + // Typedefs. + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " type." << endl + << " */" << endl; + } + + os << "typedef "; + + belongs (m, belongs_); + + os << " " << type << ";"; + + if (max (m) != 1) + { + String const& container (econtainer (m)); + bool isense (options.generate_intellisense ()); + + // sequence + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element sequence container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::sequence< " << type << " > " << + container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element iterator type." << endl + << " */" << endl; + } + + // IntelliSense does not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << container << "::iterator " << + eiterator (m) << ";"; + else + os << "typedef xsd::cxx::tree::sequence< " << type << + " >::iterator " << eiterator (m) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element constant iterator type." << endl + << " */" << endl; + } + + if (!isense) + os << "typedef " << container << "::const_iterator " << + econst_iterator (m) << ";"; + else + os << "typedef xsd::cxx::tree::sequence< " << type << + " >::const_iterator " << econst_iterator (m) << ";"; + + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " optional container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::optional< " << type << " > " << + econtainer (m) << ";"; + } + else + { + // one + // + } + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " traits type." << endl + << " */" << endl; + } + os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + SemanticGraph::Type& t (m.type ()); + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " > " << etraits (m) << ";" + << endl; + + + // Element id. + // + if (el && ordered_p (c)) + { + if (doxygen) + os << "/**" << endl + << " * @brief Element id used for capturing content " << + "order." << endl + << " */" << endl; + + SemanticGraph::Context& ctx (m.context ()); + + os << "static const ::std::size_t " << + ctx.get<String> ("ordered-id-name") << " = " << + ctx.get<size_t> ("ordered-id") << "UL;" << endl; + } + + member_function_.traverse (m); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + MemberTypeName type_name_; + Traversal::Belongs belongs_; + + MemberFunction member_function_; + }; + + + struct Any: Traversal::Any, + Traversal::AnyAttribute, + Context + { + Any (Context& c) + : Context (c), any_function_ (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + if (doxygen) + { + os << "/**" << endl + << " * @name " << ename (a) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "any wildcard." << endl; + + if (a.annotated_p ()) + { + os << " *" << endl; + write_annotation (a.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << ename (a) << endl + << "//" << endl; + } + + // Typedefs. + // + if (max (a) != 1) + { + String const& container (econtainer (a)); + + // sequence + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element sequence container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::element_sequence " << + container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::iterator " << + eiterator (a) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element constant iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::const_iterator " << + econst_iterator (a) << ";" + << endl; + + } + else if (min (a) == 0) + { + // optional + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element optional container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::element_optional " << + econtainer (a) << ";" + << endl; + } + else + { + // one + // + if (doxygen) + os << endl; + } + + // Wildcard id. + // + if (ordered_p (c)) + { + if (doxygen) + os << "/**" << endl + << " * @brief Wildcard id used for capturing content " << + "order." << endl + << " */" << endl; + + SemanticGraph::Context& ctx (a.context ()); + + os << "static const ::std::size_t " << + ctx.get<String> ("ordered-id-name") << " = " << + ctx.get<size_t> ("ordered-id") << "UL;" << endl; + } + + any_function_.traverse (a); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& container (econtainer (a)); + + if (doxygen) + { + os << "/**" << endl + << " * @name " << ename (a) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "anyAttribute" << endl + << " * wildcard." << endl; + + if (a.annotated_p ()) + { + os << " *" << endl; + write_annotation (a.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << ename (a) << endl + << "//" << endl; + } + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute set container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::attribute_set< " << char_type << + " > " << container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::iterator " << + eiterator (a) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute constant iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::const_iterator " << + econst_iterator (a) << ";" + << endl; + + any_function_.traverse (a); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + AnyFunction any_function_; + }; + + struct DataMember: Traversal::Member, Context + { + DataMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) return; + + String const& member (emember (m)); + + bool def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + os << econtainer (m) << " " << member << ";"; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + os << econtainer (m) << " " << member << ";"; + } + else + { + // one + // + os << "::xsd::cxx::tree::one< " << etype (m) << " > " << + member << ";"; + } + + // default_value + // + if (m.default_p ()) + { + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + bool lit (false); + { + IsLiteralValue test (lit); + test.dispatch (m.type ()); + } + + if (!lit) + { + os << "static const " << etype (m) << " " << + edefault_value_member (m) << ";"; + } + } + } + } + }; + + struct DataAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + DataAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + + if (max (a) != 1) + { + // sequence + // + os << econtainer (a) << " " << member << ";"; + } + else if (min (a) == 0) + { + // optional + // + os << econtainer (a) << " " << member << ";"; + } + else + { + // one + // + os << "::xsd::cxx::tree::element_one " << member << ";"; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + os << econtainer (a) << " " << emember (a) << ";"; + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + base_name_ (c), + member_name_ (c), + any_ (c), + member_ (c), + data_any_ (c), + data_member_ (c) + { + inherits_base_ >> base_name_; + inherits_member_ >> member_name_; + + names_ >> member_; + if (options.generate_wildcard ()) + names_ >> any_; + + names_data_ >> data_member_; + if (options.generate_wildcard ()) + names_data_ >> data_any_; + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + bool renamed (renamed_type (c, name)); + if (renamed && !name) + return; + + SemanticGraph::Context& ctx (c.context ()); + + bool has_members (has<Traversal::Member> (c)); + + bool hae (has<Traversal::Any> (c)); + bool haa (has<Traversal::AnyAttribute> (c)); + + bool gen_wildcard (options.generate_wildcard ()); + + bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + + bool simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (c); + } + + SemanticGraph::Enumeration* enum_base (0); + { + IsEnumBasedType t (enum_base); + t.dispatch (c); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Class corresponding to the %" << + comment (c.name ()) << " schema type." << endl; + + if (c.annotated_p ()) + { + os << " *" << endl; + write_annotation (c.annotation ()); + } + + os << " *" << endl + << " * @nosubgrouping" << endl + << " */" << endl; + } + + os << "class " << type_exp << name << ": public "; + + if (c.inherits_p ()) + inherits (c, inherits_base_); + else + os << any_type; + + os << "{" + << "public:" << endl; + + // Members. + // + names (c, names_); + + // Mixed content. + // + if (mixed) + { + String const& type (ctx.get<String> ("mixed-type")); + String const& cont (ctx.get<String> ("mixed-container")); + String const& iter (ctx.get<String> ("mixed-iterator")); + String const& citer (ctx.get<String> ("mixed-const-iterator")); + + if (doxygen) + os << "/**" << endl + << " * @name " << comment ("text_content") << endl + << " *" << endl + << " * @brief Accessor and modifier functions for text " << + "content." << endl + << " */" << endl + << "//@{" << endl; + else + os << "// text_content" << endl + << "//" << endl; + + // Typedefs. + // + bool isense (options.generate_intellisense ()); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content type." << endl + << " */" << endl; + + os << "typedef " << xs_string_type << " " << type << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content sequence container type." << endl + << " */" << endl; + + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " > " << cont << ";"; + + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content iterator type." << endl + << " */" << endl; + + // IntelliSense does not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << cont << "::iterator " << iter<< ";"; + else + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " >::iterator " << iter << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Text content constant iterator type." << endl + << " */" << endl; + + if (!isense) + os << "typedef " << cont << "::const_iterator " << citer<< ";"; + else + os << "typedef ::xsd::cxx::tree::sequence< " << type << + " >::const_iterator " << citer << ";"; + + os << endl; + + // Content id. + // + if (doxygen) + os << "/**" << endl + << " * @brief Text content id used for capturing content " << + "order." << endl + << " */" << endl; + + os << "static const ::std::size_t " << + ctx.get<String> ("mixed-ordered-id-name") << " = " << + ctx.get<size_t> ("mixed-ordered-id") << "UL;" << endl; + + // Accessors and modifiers. + // + String const& aname (ctx.get<String> ("mixed-aname")); + String const& mname (ctx.get<String> ("mixed-mname")); + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the text" << endl + << " * content sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + + os << "const " << cont << "&" << endl + << aname << " () const;" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "text content" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + + os << cont << "&" << endl + << aname << " ();" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy entries from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "add it to the sequence." << endl + << " * Note that this operation " << + "completely changes the sequence and" << endl + << " * all old elements will be lost." << endl + << " */" << endl; + + os << "void" << endl + << mname << " (const " << cont << "& s);" + << endl; + + if (doxygen) + os << "//@}" << endl + << endl; + } + + // dom_document accessors. + // + if (edom_document_member_p (c)) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the DOM" << endl + << " * document associated with this instance." << endl + << " *" << endl + << " * @return A constant reference to the DOM document." << endl + << " *" << endl + << " * The DOM document returned by this function is " << + "used to store" << endl + << " * the raw XML content corresponding to wildcards." << endl + << " */" << endl; + } + else + os << "// DOMDocument for wildcard content." << endl + << "//" << endl; + + os << "const " << xerces_ns << "::DOMDocument&" << endl + << edom_document (c) << " () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the DOM " << + "document" << endl + << " * associated with this instance." << endl + << " *" << endl + << " * @return A reference to the DOM document." << endl + << " *" << endl + << " * The DOM document returned by this function is " << + "used to store" << endl + << " * the raw XML content corresponding to wildcards." << endl + << " */" << endl; + } + os << xerces_ns << "::DOMDocument&" << endl + << edom_document (c) << " ();" + << endl; + } + + // Order container. + // + if (ordered) + { + String const& type (ctx.get<String> ("order-type")); + String const& cont (ctx.get<String> ("order-container")); + String const& iter (ctx.get<String> ("order-iterator")); + String const& citer (ctx.get<String> ("order-const-iterator")); + + String const ct (options.order_container_specified () + ? options.order_container () + : "::std::vector"); + + if (doxygen) + os << "/**" << endl + << " * @name " << comment ("content_order") << endl + << " *" << endl + << " * @brief Accessor and modifier functions for content " << + "order." << endl + << " */" << endl + << "//@{" << endl; + else + os << "// content_order" << endl + << "//" << endl; + + // Typedefs. + // + bool isense (options.generate_intellisense ()); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order entry type." << endl + << " */" << endl; + + os << "typedef " << ns_name (xs_ns ()) << "::" << + xs_ns ().context ().get<String> ("content-order") << " " << + type << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order sequence container type." << endl + << " */" << endl; + + os << "typedef " << ct << "< " << type << " > " << cont << ";"; + + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order iterator type." << endl + << " */" << endl; + + // IntelliSense does not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << cont << "::iterator " << iter<< ";"; + else + os << "typedef " << ct << "< " << type << " >::iterator " << + iter << ";"; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Content order constant iterator type." << endl + << " */" << endl; + + if (!isense) + os << "typedef " << cont << "::const_iterator " << citer<< ";"; + else + os << "typedef " << ct << "< " << type << + " >::const_iterator " << citer << ";"; + + os << endl; + + // Accessors and modifiers. + // + String const& aname (ctx.get<String> ("order-aname")); + String const& mname (ctx.get<String> ("order-mname")); + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the content" << endl + << " * order sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + + os << "const " << cont << "&" << endl + << aname << " () const;" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "content order" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + + os << cont << "&" << endl + << aname << " ();" + << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy entries from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "add it to the sequence." << endl + << " * Note that this operation " << + "completely changes the sequence and" << endl + << " * all old elements will be lost." << endl + << " */" << endl; + + os << "void" << endl + << mname << " (const " << cont << "& s);" + << endl; + + if (doxygen) + os << "//@}" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @name Constructors" << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Constructors." << endl + << "//" << endl; + } + + bool generate_no_base_ctor (false); + { + GenerateWithoutBaseCtor t (generate_no_base_ctor); + t.traverse (c); + } + + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // default c-tor + // + if (options.generate_default_ctor ()) + { + // c-tor (ultimate-base, all-non-optional-members) will become + // default c-tor if our inheritance hierarchy has no required + // members and no simple base. We can also collide with + // c-tor (all-non-optional-members) if we have no required + // members. + // + bool generate (false); + { + GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); + t.traverse (c); + } + + if (generate) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor leaves required " << + "elements and" << endl + << " * attributes uninitialized." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + } + + // c-tor (base, all-non-optional-members) + // + if (options.generate_from_base_ctor ()) + { + // c-tor (base, all-non-optional-members) will be equivalent to + // c-tor (ultimate-base, all-non-optional-members) unless our + // immediate base's hierarchy has some non-optional members. + // We also need to generate this c-tor when one of the types + // in our inheritance hierarchy was customized since the + // customized version may not necessarily be convertible to + // the base without loss of information. + // + bool generate (false); + { + GenerateFromBaseCtor t (*this, generate); + t.traverse (c); + } + + if (generate) + { + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args (*this, CtorArgType::type, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes" << endl + << " * (" << auto_ptr << " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args ( + *this, CtorArgType::complex_auto_ptr, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes" << endl + << " * (" << auto_ptr << " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args ( + *this, CtorArgType::poly_auto_ptr, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + } + } + } + + // c-tor (all-non-optional-members) + // + if (generate_no_base_ctor) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::type, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. One case where + // this c-tor will be generated is restriction of anyType. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes (" << auto_ptr << + " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::complex_auto_ptr, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes (" << auto_ptr << + " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::poly_auto_ptr, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + } + } + + if (string_based) + { + // We might not have the value type if this enum is customized. + // + if (enum_base != 0 && enum_base->context ().count ("value")) + { + // c-tor (enum-value, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "underlying enum value" << endl + << " * and initializers for required elements and " << + "attributes." << endl + << " */" << endl; + } + + os << name << " (" << fq_name (*enum_base) << "::" << + evalue (*enum_base); + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (const char*, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string and " << + "initializers" << endl + << " * for required elements and attributes." << endl + << " */" << endl; + } + + os << name << " (const " << char_type << "*"; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + + // c-tor (const std::string&, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string and" << + "initializers" << endl + << " * for required elements and attributes." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "&"; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgType::type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (ultimate-base, all-non-optional-members) + // + + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgType::type); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes" << endl + << " * (" << auto_ptr << " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgType::complex_auto_ptr); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes" << endl + << " * (" << auto_ptr << " version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgType::poly_auto_ptr); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (istream&) + // + NarrowStrings const& st (options.generate_extraction ()); + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + + if (simple) + { + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const"; + + // Make the _clone() function pure virtual if the type is + // abstract or we are generating a polymorphic base for a + // custom implementation (in which case the base must be + // inherited from and _clone() overridden). + // + if (c.abstract_p () || + (renamed && polymorphic && polymorphic_p (c))) + os << " = 0"; + + os << ";" + << endl; + + // operator= + // + bool priv (false); + bool asop (true); + + if (!simple) + { + if (options.suppress_assignment ()) + { + asop = false; + + priv = true; + os << "private:" << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Disabled copy assignment operator." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @return A reference to itself." << endl + << " */" << endl; + } + + os << name << "&" << endl + << "operator= (const " << name << "& x);" + << endl; + } + else if (has_members || (gen_wildcard && (hae || haa))) + { + asop = false; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy assignment operator." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @return A reference to itself." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << "&" << endl + << "operator= (const " << name << "& x);" + << endl; + } + } + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + if (priv) + os << "public:" << endl; + + if (asop) + { + os << "#ifdef XSD_CXX11" << endl + << name << "&" << endl + << "operator= (const " << name << "&) = default;" + << "#endif" << endl + << endl; + } + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();" + << endl; + + // Data members and implementation functions. + // + if (has_members || hae || (haa && gen_wildcard) || ordered || mixed) + { + os << "// Implementation." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "//@cond" << endl + << endl; + + if (!options.suppress_parsing () && + (has_members || hae || (haa && gen_wildcard) || mixed)) + { + // parse () + // + os << "protected:" << endl + << "void" << endl + << unclash (name, "parse") << " (" << + parser_type << "&," << endl + << flags_type << ");" + << endl; + } + + os << "protected:" + << endl; + + // parse (istream) + // + if (has_members) + { + for (NarrowStrings::const_iterator i (st.begin ()); i != st.end (); + ++i) + { + os << "void" << endl + << unclash (name, "parse") << " (" << + istream_type << "< " << i->c_str () << " >&," << endl + << flags_type << ");" + << endl; + } + } + + // DOM document. + // + if (edom_document_member_p (c)) + { + os << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > " << edom_document_member (c) << ";" + << endl; + } + + // Mixed text content. + // + if (mixed) + { + os << ctx.get<String> ("mixed-container") << " " << + ctx.get<String> ("mixed-member") << ";" + << endl; + } + + // Order container. + // + if (ordered) + { + os << ctx.get<String> ("order-container") << " " << + ctx.get<String> ("order-member") << ";" + << endl; + } + + // + // + names (c, names_data_); + + if (doxygen) + os << endl + << "//@endcond" << endl; + } + + os << "};"; + + // Comparison operators. + // + if (options.generate_comparison () && + (has_members || !c.inherits_p () || + ((hae || haa) && gen_wildcard))) + { + os << inst_exp + << "bool" << endl + << "operator== (const " << name << "&, const " << name << "&);" + << endl; + + os << inst_exp + << "bool" << endl + << "operator!= (const " << name << "&, const " << name << "&);" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_name_; + + Traversal::Inherits inherits_member_; + MemberTypeName member_name_; + + Traversal::Names names_; + Any any_; + Member member_; + + Traversal::Names names_data_; + DataAny data_any_; + DataMember data_member_; + }; + + + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c), type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + SemanticGraph::Type& t (e.type ()); + + bool fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + bool simple (true); + if (!fund) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Class corresponding to the %" << + comment (e.name ()) << " root element." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " *" << endl + << " * @nosubgrouping" << endl + << " */" << endl; + } + + String const& name (ename (e)); + + os << "class " << type_exp << name << ": public " << element_type + << "{" + << "public:" << endl + << endl; + + String const& type (etype (e)); + + if (doxygen) + { + os << "/**" << endl + << " * @name Element value" << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "element value." << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Element value." << endl + << "//" << endl; + } + + // Typedefs. + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Element value type." << endl + << " */" << endl; + } + + os << "typedef "; + + belongs (e, belongs_); + + os << " " << type << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element value traits type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " > " << etraits (e) << ";" + << endl; + + // Accessors/modifiers. + // + String const& aname (eaname (e)); + String const& mname (emname (e)); + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the element" << endl + << " * value." << endl + << " *" << endl + << " * @return A constant reference to the element value." << + endl + << " */" << endl; + } + + os << "const " << type << "&" << endl + << aname << " () const;" + << endl; + + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "element value." << endl + << " *" << endl + << " * @return A reference to the element value." << endl + << " */" << endl; + } + + os << type << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the element value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the element." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the element value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << auto_ptr << "< " << type << " > p);" + << endl; + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Detach the element value from " << + "the object." << endl + << " *" << endl + << " * @return A pointer to the element value." << endl + << " *" << endl + << " * Note that this function leaves the element " << + "object uninitialized." << endl + << " */" << endl; + } + + os << auto_ptr << "< " << type << " >" << endl + << edname (e) << " ();" + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) pointer " << + "to the element" << endl + << " * value." << endl + << " *" << endl + << " * @return A constant pointer to the element value " << + "or 0 if this" << endl + << " * element is of a fundamental type." << endl + << " */" << endl; + } + + os << "virtual const " << any_type << "*" << endl + << "_value () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a pointer to the element value." << endl + << " *" << endl + << " * @return A pointer to the element value or 0 if this " << + "element is" << endl + << " * of a fundamental type." << endl + << " */" << endl; + } + os << "virtual " << any_type << "*" << endl + << "_value ();" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // Constructor. + // + + if (doxygen) + { + os << "/**" << endl + << " * @name Constructors" << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Constructors." << endl + << "//" << endl; + } + + // default c-tor + // + if (options.generate_default_ctor ()) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor leaves the element " << + "value" << endl + << " * uninitialized." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (value) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from an initializer " << + "for the element" << endl + << " * value." << endl + << " *" << endl + << " * @param x Element value." << endl + << " */" << endl; + } + + os << name << " (const " << type << "& x);" + << endl; + + + // If the element value is a complex type (has elements, + // attributes, or wildcards) then also generate the auto_ptr + // version. If we are generating polymorphic code then we + // also need to provide auto_ptr version for simple types. + // + if (!simple || (polymorphic && polymorphic_p (t))) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from an initializer " << + "for" << endl + << " * the element value (" << auto_ptr << + " version)." << endl + << " *" << endl + << " * @param p Element value to use." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "value directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << name << " (" << auto_ptr << "< " << type << " > p);" + << endl; + } + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e, " << + flags_type << " f = 0);" + << endl; + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x, " << + flags_type << " f = 0);" + << endl; + + os << "#ifdef XSD_CXX11" << endl + << name << "&" << endl + << "operator= (const " << name << "&) = default;" + << "#endif" << endl + << endl; + + // _clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0) const;" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // Element name and namespace accessors. + // + if (doxygen) + { + os << "/**" << endl + << " * @name Element name and namespace" << endl + << " *" << endl + << " * @brief Accessor functions for the element name " << + "and namespace." << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Element name and namespace." << endl + << "//" << endl; + } + + SemanticGraph::Context& ec (e.context ()); + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element name (static function)." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * name." << endl + << " */" << endl; + } + os << "static const " << string_type << "&" << endl + << ec.get<String> ("element-name") << " ();" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element namespace (static " << + "function)." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * namespace." << endl + << " */" << endl; + } + os << "static const " << string_type << "&" << endl + << ec.get<String> ("element-ns") << " ();" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element name." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * name." << endl + << " */" << endl; + } + os << "virtual const " << string_type << "&" << endl + << "_name () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element namespace." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * namespace." << endl + << " */" << endl; + } + os << "virtual const " << string_type << "&" << endl + << "_namespace () const;" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();" + << endl; + + // Data member. + // + + if (doxygen) + os << "//@cond" << endl + << endl; + + os << "protected:" << endl + << "::xsd::cxx::tree::one< " << type << " > " << + emember (e) << ";" + << "static const " << string_type << " " << + ec.get<String> ("element-name-member") << ";" + << "static const " << string_type << " " << + ec.get<String> ("element-ns-member") << ";"; + + if (doxygen) + os << endl + << "//@endcond" << endl; + + os << "};"; + } + + private: + Traversal::Belongs belongs_; + MemberTypeName type_name_; + }; + } + + void + generate_tree_header (Context& ctx) + { + if (ctx.generate_xml_schema) + { + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/types.hxx>" << endl + << endl; + + if (!ctx.options.suppress_parsing () || + ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl + << endl; + } + + if (!ctx.options.suppress_parsing () || + ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + } + + bool element_map (ctx.options.generate_element_map ()); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl + << endl; + + // I need to include all the "optional" headers here (instead of + // later in the individual generators for each feature because + // those headers provide implementation for the fundamental types. + // + if (!ctx.options.suppress_parsing ()) + { + ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + + Traversal::Schema schema; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "parsing"); + + schema >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.generate_serialization ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl + << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + + Traversal::Schema schema; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "serialization"); + + schema >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.generate_ostream ()) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl + << endl; + } + + NarrowStrings const& ist (ctx.options.generate_insertion ()); + if (!ist.empty ()) + { + for (NarrowStrings::const_iterator i (ist.begin ()); i != ist.end (); + ++i) + { + if (*i == "ACE_OutputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl + << endl; + } + + NarrowStrings const& est (ctx.options.generate_extraction ()); + if (!est.empty ()) + { + for (NarrowStrings::const_iterator i (est.begin ()); i != est.end (); + ++i) + { + if (*i == "ACE_InputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl + << endl; + } + + // Emit fundamental types. + // + { + Traversal::Schema schema; + Traversal::Names names; + FundamentalNamespace ns (ctx); + + schema >> names >> ns; + + schema.dispatch (ctx.schema_root); + } + } + else + { + bool inline_ (ctx.options.generate_inline ()); + + ctx.os << "#include <memory> // " << ctx.auto_ptr << endl + << "#include <limits> // std::numeric_limits" << endl + << "#include <algorithm> // std::binary_search" << endl; + + if (ctx.std >= cxx_version::cxx11) + ctx.os << "#include <utility> // std::move" << endl; + + if (!ctx.options.ordered_type ().empty () || + ctx.options.ordered_type_all ()) + { + ctx.os << "#include <cstddef> // std::size_t" << endl; + + if (!ctx.options.order_container_specified ()) + ctx.os << "#include <vector>" << endl; + } + + ctx.os << endl; + + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/containers.hxx>" << endl + << "#include <xsd/cxx/tree/list.hxx>" << endl + << endl; + + if (!ctx.options.suppress_parsing ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/parsing-header.hxx>" << endl + << endl; + } + + if (ctx.options.generate_wildcard ()) + { + if (ctx.options.suppress_parsing () || + !ctx.options.generate_serialization ()) + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl; + + ctx.os << "#include <xsd/cxx/tree/containers-wildcard.hxx>" << endl + << endl; + } + + if (!ctx.options.generate_extraction ().empty ()) + ctx.os << "#include <xsd/cxx/tree/istream-fwd.hxx>" << endl + << endl; + + // Emit header includes. + // + { + if (inline_) + { + ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << "#define XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + + Traversal::Schema schema; + Includes includes (ctx, Includes::header); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + + if (inline_) + { + ctx.os << "#undef XSD_DONT_INCLUDE_INLINE" << endl + << "#else" << endl + << endl; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + + + { + Traversal::Schema schema; + + Sources sources; + Traversal::Names names_ns, names; + + DocumentedNamespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.options.generate_element_type ()) + names >> element; + + schema.dispatch (ctx.schema_root); + } + + // Emit inline includes. + // + if (inline_) + { + ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << endl; + + Traversal::Schema schema; + Includes ixx_includes (ctx, Includes::inline_); + schema >> ixx_includes; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + } + } +} diff --git a/xsd/cxx/tree/tree-header.hxx b/xsd/cxx/tree/tree-header.hxx new file mode 100644 index 0000000..d0e9ea6 --- /dev/null +++ b/xsd/cxx/tree/tree-header.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/tree-header.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_HEADER_HXX +#define XSD_CXX_TREE_TREE_HEADER_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_tree_header (Context&); + } +} + +#endif // XSD_CXX_TREE_TREE_HEADER_HXX diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx new file mode 100644 index 0000000..aa8b726 --- /dev/null +++ b/xsd/cxx/tree/tree-inline.cxx @@ -0,0 +1,1161 @@ +// file : xsd/cxx/tree/tree-inline.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-inline.hxx> +#include <xsd/cxx/tree/default-value.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String item_name (item_type_name (item_type)); + String base_type (L"::xsd::cxx::tree::list< " + item_name + + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base_type += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + + base_type += L" >"; + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base_type << " (this)" + << "{" + << "}"; + + // c-tor (size_type, const X& x) + // + String size_type (name != L"size_type" + ? String (L"size_type") + : base_type + L"::size_type"); + + os << inl + << name << "::" << endl + << name << " (" << size_type << " n, const " << item_name << + "& x)" << endl + << ": " << base_type << " (n, x, this)" + << "{" + << "}"; + + // copy c-tor () + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& o," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (o, f, c)," << endl + << " " << base_type << " (o, f, this)" + << "{" + << "}"; + + // Comparison operators. + // + if (options.generate_comparison ()) + { + os << inl + << "bool" << endl + << "operator== (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "const " << base_type << "& bx (x);" + << "return bx == y;" + << "}"; + + os << inl + << "bool" << endl + << "operator!= (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "return !(x == y);" + << "}"; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (options.generate_default_ctor ()) + { + // c-tor () + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()" + << "{" + << "}"; + } + + // c-tor (const char*) + // + os << inl + << name << "::" << endl + << name << " (const " << char_type << "* s)" << endl + << ": " << base << " (s)" + << "{" + << "}"; + + // c-tor (string const&) + // + os << inl + << name << "::" << endl + << name << " (const " << string_type << "& s)" << endl + << ": " << base << " (s)" + << "{" + << "}"; + + // copy c-tor () + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& o," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (o, f, c)" + << "{" + << "}"; + } + }; + + // Enumeration + // + + // Generate a sequence of explicit c-tor calls until we reach + // one of the fundamental string types that can be constructed + // from char literals. + // + struct CtorCallSequence: Traversal::Complex, + Traversal::Fundamental::Type, + Context + { + CtorCallSequence (Context& c, String const& arg) + : Context (c), arg_ (arg), base_type_name_ (c) + { + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + // This type should be ultimately string based. + // + assert (c.inherits_p ()); + + os << ename (c) << " (" << endl; + + dispatch (c.inherits ().base ()); + + os << ")"; + } + + virtual void + traverse (SemanticGraph::Fundamental::Type& t) + { + base_type_name_.dispatch (t); + + os << " (" << arg_ << ")"; + } + + private: + String arg_; + BaseTypeName base_type_name_; + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), member_ (c) + { + inherits_member_ >> member_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + bool enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + String value; + if (string_based) + value = evalue (e); + + // Get to the ultimate base and see if is a fundamental type. + // + bool fund_based (false); + SemanticGraph::Type& ult_base (ultimate_base (e)); + { + IsFundamentalType t (fund_based); + t.dispatch (ult_base); + } + + // + // + String base; // base type name + { + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + inherits (e, inherits_type); + base = o.str (); + } + + os << "// " << name << endl + << "//" << endl + << endl; + + // default c-tor + // + bool list_based ( + ult_base.is_a<SemanticGraph::List> () || + ult_base.is_a<SemanticGraph::Fundamental::NameTokens> () || + ult_base.is_a<SemanticGraph::Fundamental::IdRefs> () || + ult_base.is_a<SemanticGraph::Fundamental::Entities> ()); + + if (options.generate_default_ctor () || list_based) + { + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()" + << "{" + << "}"; + } + + // c-tor (value) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (" << value << " v)" << endl + << ": "; + + // If we are enum-based then we can just use the corresponding + // base c-tor directly. Otherwise we will use the from-string + // c-tor. + // + if (enum_based) + os << base << " (v)"; + else + { + CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); + t.dispatch (e.inherits ().base ()); + } + + os << "{" + << "}"; + } + + // c-tor (const char*) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (const " << char_type << "* v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (const std::string&) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (const " << string_type << "& v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (fundamental) + // + if (fund_based) + { + os << inl + << name << "::" << endl + << name << " ("; + + member_.dispatch (ult_base); + + os << " v)" + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (base) + // + // If the ultimate is also our immediate base and it is a + // fundamental type then this c-tor clashes with c-tor + // (fundamental) above. + // + if (!fund_based || &ult_base != &e.inherits ().base ()) + { + os << inl + << name << "::" << endl + << name << " (const "; + + inherits (e, inherits_member_); + + os << "& v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // copy c-tor + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& v," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (v, f, c)" + << "{" + << "}"; + + // operato= (value) + // + if (string_based) + { + os << inl + << name << "& " << name << "::" << endl + << "operator= (" << value << " v)" + << "{" + << "static_cast< " << base << "& > (*this) = "; + + // If we are enum-based then we can just use the corresponding + // base assignment directly. Otherwise we will use the from- + // base assignment and a from-string base c-tor. + // + if (enum_based) + os << "v"; + else + { + os << endl; + + CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); + t.dispatch (e.inherits ().base ()); + } + + os << ";" + << endl + << "return *this;" + << "}"; + } + + os << endl; + } + + private: + Traversal::Inherits inherits_member_; + MemberTypeName member_; + }; + + struct Member: Traversal::Member, Context + { + Member (Context& c, String const& scope) + : Context (c), scope_ (scope), lit_value_ (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& aname (eaname (m)); + String const& mname (emname (m)); + String const& member (emember (m)); + + bool fund (false); + { + IsFundamentalType t (fund); + t.dispatch (m.type ()); + } + + bool def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + String container (econtainer (m)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + String type (etype (m)); + String container (econtainer (m)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& x)" + << "{" + << "this->" << member << " = x;" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << auto_ptr << "< " << type << " > x)" + << "{" + << "this->" << member << ".set (" << + (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" + << "}"; + } + else + { + // one + // + String type (etype (m)); + String q_type (scope_ + L"::" + type); + + // type const& + // name () const; + // + os << inl + << "const " << q_type << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // Do not generate modifiers for fixed attributes. + // + if (!(def_attr && m.fixed_p ())) + { + // type& + // name (); + // + os << inl + << q_type << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << auto_ptr << "< " << type << " > x)" + << "{" + << "this->" << member << ".set (" << + (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" + << "}"; + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + os << inl + << auto_ptr << "< " << q_type << " > " << + scope_ << "::" << endl + << edname (m) << " ()" + << "{" + << "return this->" << member << ".detach ();" + << "}"; + } + } + + + // default_value + // + if (m.default_p ()) + { + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + String lit (lit_value_.dispatch (m.type (), m.value ())); + + os << inl; + + if (lit) + os << scope_ << "::" << etype (m) << " "; + else + os << "const " << scope_ << "::" << etype (m) << "& "; + + os << scope_ << "::" << endl + << edefault_value (m) << " ()" + << "{"; + + if (lit) + os << "return " << etype (m) << " (" << lit << ");"; + else + os << "return " << edefault_value_member (m) << ";"; + + os << "}"; + } + } + } + + private: + String scope_; + LiteralValue lit_value_; + }; + + struct Any: Traversal::Any, + Traversal::AnyAttribute, + Context + { + Any (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String const& member (emember (a)); + + if (max (a) != 1) + { + // sequence + // + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + else if (min (a) == 0) + { + // optional + // + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (type*); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << xerces_ns << "::DOMElement* e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& x)" + << "{" + << "this->" << member << " = x;" + << "}"; + } + else + { + // one + // + + // type const& + // name () const; + // + os << inl + << "const " << xerces_ns << "::DOMElement& " << + scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // type& + // name (); + // + os << inl + << xerces_ns << "::DOMElement& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (type*); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << xerces_ns << "::DOMElement* e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String const& member (emember (a)); + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + + private: + String scope_; + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + os << "// " << name << endl + << "//" << endl + << endl; + + // Generate accessors and modifiers. + // + Any any (*this, name); + Member member (*this, name); + Traversal::Names names; + + if (options.generate_wildcard ()) + names >> any; + + names >> member; + + Complex::names (c, names); + + // Mixed text content. + // + if (mixed_p (c) && !c.context ().count ("mixed-in-base")) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& cont (ctx.get<String> ("mixed-container")); + String const& memb (ctx.get<String> ("mixed-member")); + + String const& aname (ctx.get<String> ("mixed-aname")); + String const& mname (ctx.get<String> ("mixed-mname")); + + os << inl + << "const " << name << "::" << cont << "& " << + name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << name << "::" << cont << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << "void " << name << "::" << endl + << mname << " (const " << cont << "& s)" + << "{" + << "this->" << memb << " = s;" + << "}"; + } + + // dom_document accessors. + // + if (edom_document_member_p (c)) + { + os << inl + << "const " << xerces_ns << "::DOMDocument& " << + name << "::" << endl + << edom_document (c) << " () const" + << "{" + << "return *this->" << edom_document_member (c) << ";" + << "}"; + + os << inl + << xerces_ns << "::DOMDocument& " << name << "::" << endl + << edom_document (c) << " ()" + << "{" + << "return *this->" << edom_document_member (c) << ";" + << "}"; + } + + // Order container. + // + if (ordered_p (c) && !c.context ().count ("order-in-base")) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& cont (ctx.get<String> ("order-container")); + String const& memb (ctx.get<String> ("order-member")); + + String const& aname (ctx.get<String> ("order-aname")); + String const& mname (ctx.get<String> ("order-mname")); + + os << inl + << "const " << name << "::" << cont << "& " << + name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << name << "::" << cont << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << memb << ";" + << "}"; + + os << inl + << "void " << name << "::" << endl + << mname << " (const " << cont << "& s)" + << "{" + << "this->" << memb << " = s;" + << "}"; + } + + os << endl; + } + }; + + + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + bool fund (false); + { + IsFundamentalType test (fund); + test.dispatch (e.type ()); + } + + String const& name (ename (e)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // Accessors/modifiers. + // + String const& type (etype (e)); + String const& aname (eaname (e)); + String const& mname (emname (e)); + String const& member (emember (e)); + + // type const& + // name () const; + // + os << inl + << "const " << name << "::" << type << "& " << name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // type& + // name (); + // + os << inl + << name << "::" << type << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << name << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + os << inl + << "void " << name << "::" << endl + << mname << " (" << auto_ptr << "< " << type << " > x)" + << "{" + << "this->" << member << ".set (" << + (std >= cxx_version::cxx11 ? "std::move (x)" : "x") << ");" + << "}"; + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + os << inl + << auto_ptr << "< " << name << "::" << type << " > " << + name << "::" << endl + << edname (e) << " ()" + << "{" + << "return this->" << member << ".detach ();" + << "}"; + } + }; + } + + void + generate_tree_inline (Context& ctx, size_t first, size_t last) + { + // Generate includes. + // + if (ctx.options.generate_inline ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::inline_); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + else + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.options.generate_element_type ()) + names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/tree-inline.hxx b/xsd/cxx/tree/tree-inline.hxx new file mode 100644 index 0000000..dad4c24 --- /dev/null +++ b/xsd/cxx/tree/tree-inline.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/tree-inline.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_INLINE_HXX +#define XSD_CXX_TREE_TREE_INLINE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_tree_inline (Context&, size_t first, size_t last); + } +} + +#endif // XSD_CXX_TREE_TREE_INLINE_HXX diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx new file mode 100644 index 0000000..89419af --- /dev/null +++ b/xsd/cxx/tree/tree-source.cxx @@ -0,0 +1,3912 @@ +// file : xsd/cxx/tree/tree-source.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <map> +#include <list> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/tree-source.hxx> +#include <xsd/cxx/tree/default-value.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (e, f, c)," << endl + << " " << base << " (e, f, this)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (a, f, c)," << endl + << " " << base << " (a, f, this)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (s, e, f, c)," << endl + << " " << base << " (s, e, f, this)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (l) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + + if ((!anonymous_p (l) || anonymous_substitutes_p (l)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (u) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + + if ((!anonymous_p (u) || anonymous_substitutes_p (u)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + }; + + + // Enumeration mapping. + // + + struct EnumeratorLiteral: Traversal::Enumerator, Context + { + EnumeratorLiteral (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + os << strlit (e.name ()); + } + }; + + + // + // + struct LiteralInfo + { + LiteralInfo (String const& value, String const& name) + : value_ (value), name_ (name) + { + } + + String value_; + String name_; + }; + + bool + operator< (LiteralInfo const& x, LiteralInfo const& y) + { + return x.value_ < y.value_; + } + + typedef list<LiteralInfo> LiteralInfoList; + + + // Populate LiteralInfoList + // + struct EnumeratorLiteralInfo: Traversal::Enumerator, Context + + { + EnumeratorLiteralInfo (Context& c, LiteralInfoList& list) + : Context (c), list_ (list) + { + } + + virtual void + traverse (Type& e) + { + list_.push_back (LiteralInfo (e.name (), ename (e))); + } + + private: + LiteralInfoList& list_; + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), enumerator_literal_ (c) + { + names_enumerator_literal_ >> enumerator_literal_; + } + + virtual void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + SemanticGraph::Enumeration* be (0); + bool enum_based (false); + if (string_based) + { + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + String value; + if (string_based) + value = evalue (e); + + size_t enum_count (0); + + for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); + i != end; ++i) + ++enum_count; + + String base; // base type name + { + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + inherits (e, inherits_type); + base = o.str (); + } + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{"; + + if (string_based) + os << "_xsd_" << name << "_convert ();"; + + os << "}"; + + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // convert + // + // @@ TODO: expected list + // + if (string_based) + { + String i_name (L"_xsd_" + name + L"_indexes_"); + + os << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_convert () const" + << "{" + << "::xsd::cxx::tree::enum_comparator< " << char_type << + " > c (_xsd_" << name << "_literals_);" + << "const " << value << "* i (::std::lower_bound (" << endl + << i_name << "," << endl + << i_name << " + " << enum_count << "," << endl + << "*this," << endl + << "c));" + << endl + << "if (i == " << i_name << " + " << enum_count << " || " << + "_xsd_" << name << "_literals_[*i] != *this)" + << "{" + << "throw ::xsd::cxx::tree::unexpected_enumerator < " << + char_type << " > (*this);" + << "}" + << "return *i;" + << "}"; + } + + // literals and indexes + // + if (string_based) + { + if (enum_based) + { + os << "const " << char_type << "* const* " << name << "::" << endl + << "_xsd_" << name << "_literals_ = " << + fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;" + << endl; + } + else + { + os << "const " << char_type << "* const " << name << "::" << endl + << "_xsd_" << name << "_literals_[" << enum_count << "] =" + << "{"; + + names<Enumeration> ( + e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma); + + os << "};"; + } + + + LiteralInfoList l; + { + EnumeratorLiteralInfo enumerator (*this, l); + Traversal::Names names_enumerator (enumerator); + names (e, names_enumerator); + } + + l.sort (); + + os << "const " << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_indexes_[" << enum_count << "] =" + << "{"; + + String fq_name (ns_scope + L"::" + name); + + for (LiteralInfoList::iterator + b (l.begin ()), i (b), end (l.end ()); i != end; ++i) + { + if (i != b) + os << "," << endl; + + os << fq_name << "::" << i->name_; + } + + os << "};"; + } + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (e) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + + if ((!anonymous_p (e) || anonymous_substitutes_p (e)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + } + + virtual void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Names names_enumerator_literal_; + EnumeratorLiteral enumerator_literal_; + + }; + + // + // + struct Member: Traversal::Member, Context + { + Member (Context& c, String const& scope) + : Context (c), scope_ (scope), init_value_ (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + // default_value + // + if (m.default_p ()) + { + SemanticGraph::Type& t (m.type ()); + bool simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + if (simple) + { + bool lit (false); + { + IsLiteralValue test (lit); + test.dispatch (t); + } + + if (!lit) + { + InitKind::Kind kind (InitKind::simple); + { + InitKind test (kind); + test.dispatch (t); + } + + String const& member (edefault_value_member (m)); + + String init_name; + + 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; + + 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; + } + } + } + } + + private: + String scope_; + InitValue init_value_; + }; + + + struct Element: Traversal::Element, Context + { + Element (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (e.scope ())); + + String const& member (emember (e)); + + String tr (etraits (e)); // traits type name + String type (etype (e)); + + SemanticGraph::Type& t (e.type ()); + + bool fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (t); + } + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + os << "// " << comment (e.name ()) << endl + << "//" << endl; + + if (poly) + { + os << "{" + << auto_ptr << "< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< " << + poly_plate << ", " << char_type << " > ().create (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << "," << endl; + + SemanticGraph::Complex* tc; + if ((tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p ()) + os << "0,"; + else + os << "&::xsd::cxx::tree::factory_impl< " << type << " >,"; + + os << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", " << + "i, n, f, this));" + << endl + << "if (tmp.get () != 0)" + << "{"; + } + else + { + if (e.qualified_p () && e.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ () == " << strlit (e.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + if (!fund) + { + os << auto_ptr << "< " << type << " > r (" << endl + << tr << "::create (i, f"; + + if (t.is_a<SemanticGraph::AnyType> () && + options.generate_any_type ()) + os << " | " << flags_type << "::extract_content"; + + os << ", this));" + << endl; + } + } + + + // Checks. Disabled at the moment since they make it impossible to + // parse valid instances where the same element is used in both + // base and derived types. See the cxx/tree/name-clash/inheritance + // test for details. + // + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + + if (poly || !fund) + { + if (poly) + { + // Cast to static type. + // + os << auto_ptr << "< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + + char const* r (std >= cxx_version::cxx11 ? "::std::move (r)" : "r"); + + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (" << r << ");"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (" << r << ");"; + } + else + { + // one + // + os << "this->" << member << ".set (" << r << ");"; + } + } + else + { + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (" << tr << + "::create (i, f, this));"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + else + { + // one + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + } + + // Capture order. + // + if (ordered_p (c)) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& t (ctx.get<String> ("order-type")); + String const& m (ctx.get<String> ("order-member")); + + os << "this->" << m << ".push_back (" << endl + << t << " (" << + e.context ().get<String> ("ordered-id-name"); + + // sequence + // + if (max (e) != 1) + os << ", " << "this->" << member << ".size () - 1"; + + os << "));"; + } + + os << "continue;"; + + // End of check block. + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + + if (poly) + os << "}"; + } + }; + + struct ElementTest: Traversal::Element, Context + { + ElementTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& e) + { + if (skip (e)) + return; + + if (max (e) == 1 && min (e) == 1) + { + // one + // + os << "if (!" << emember (e) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << ");" + << "}"; + } + } + }; + + struct Any: Traversal::Any, Context + { + Any (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc (edom_document (c)); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "true"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () && " << + "n.namespace_ () != " << strlit (ns) << ")"; + } + else + os << "!n.namespace_ ().empty ()"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{"; + + + // Checks. + // + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + os << xerces_ns << "::DOMElement* r (" << endl + << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));"; + + if (max (a) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (r);"; + } + else if (min (a) == 0) + { + // optional + // + os << "this->" << member << ".set (r);"; + } + else + { + // one + // + os << "this->" << member << ".set (r);"; + } + + // Capture order. + // + if (ordered_p (c)) + { + SemanticGraph::Context& ctx (c.context ()); + + String const& t (ctx.get<String> ("order-type")); + String const& m (ctx.get<String> ("order-member")); + + os << "this->" << m << ".push_back (" << endl + << t << " (" << + a.context ().get<String> ("ordered-id-name") << ", "; + + if (max (a) != 1) + // sequence + // + os << "this->" << member << ".size () - 1"; + else + // optional & one + // + os << "0"; + + os << "));"; + } + + os << "continue;"; + + // End of check block. + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + } + }; + + struct AnyTest: Traversal::Any, Context + { + AnyTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + if (max (a) == 1 && min (a) == 1) + { + // one + // + os << "if (!" << emember (a) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << L << "\"*\"," << endl + << strlit (*a.namespace_begin ()) << ");" + << "}"; + } + } + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& tr (etraits (a)); // traits type name + + if (a.qualified_p () && a.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ () == " << strlit (a.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + + os << "continue;" + << "}"; + + } + }; + + struct AnyAttribute: Traversal::AnyAttribute, Context + { + AnyAttribute (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + // Note that we need to filter out namespaces for xmlns and + // xsi. + // + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "(n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << strlit (ns) << " &&" <<endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{" + << xerces_ns << "::DOMAttr* r (" << endl + << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));" + << "this->" << member << " .insert (r);" + << "continue;" + << "}"; + } + }; + + + struct AttributeTest: Traversal::Attribute, Context + { + AttributeTest (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& a) + { + String const& member (emember (a)); + + if (!a.optional_p () || a.default_p ()) + { + os << "if (!" << member << ".present ())" + << "{"; + + if (a.default_p ()) + { + os << "this->" << member << ".set (" << + edefault_value (a) << " ());"; + } + else + os << "throw ::xsd::cxx::tree::expected_attribute< " << + char_type << " > (" << endl + << strlit (a.name ()) << "," << endl + << (a.qualified_p () + ? strlit (a.namespace_ ().name ()) + : L + String ("\"\"")) << ");"; + + os << "}"; + } + } + }; + + + // + // + struct CtorBase: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Context + { + // If base_arg is empty then no base argument is generated. + // + CtorBase (Context& c, CtorArgType at, String const& base_arg) + : Context (c), args_ (c, at, base_arg) + { + } + + virtual void + traverse (SemanticGraph::Type&) + { + if (args_.base_arg_) + os << args_.base_arg_; + } + + virtual void + traverse (SemanticGraph::Enumeration&) + { + if (args_.base_arg_) + os << args_.base_arg_; + } + + void + traverse (SemanticGraph::Complex& c) + { + args_.traverse (c); + } + + private: + // No need to traverse AnyAttribute since it is always mapped + // to a sequence. + // + struct Args: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + Args (Context& c, CtorArgType at, String const& base_arg) + : Context (c), + arg_type_ (at), base_arg_ (base_arg), first_ (true) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual void + traverse (SemanticGraph::Type&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual void + traverse (SemanticGraph::Enumeration&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual void + traverse (SemanticGraph::Any& a) + { + if (!options.generate_wildcard ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + // one + // + os << comma () << ename (a); + } + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + { + // one + // + bool move (false); + + if (std >= cxx_version::cxx11) + { + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + move = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + move = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + } + + os << comma () << (move ? "std::move (" : "") << ename (e) << + (move ? ")" : ""); + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not including attributes with default + // or required fixed values here. + // + if (min (a) == 1 && !a.fixed_p ()) + { + // one + // + os << comma () << ename (a); + } + } + + using Complex::traverse; + + private: + String + comma () + { + bool tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + public: + CtorArgType arg_type_; + String base_arg_; + + private: + bool first_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + Args args_; + }; + + + struct CtorMember: Traversal::Element, + Traversal::Attribute, + Context + { + CtorMember (Context& c, CtorArgType at) + : Context (c), arg_type_ (at) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + if (max (e) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (this)"; + } + else if (min (e) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (this)"; + } + else + { + // one + // + bool move (false); + + if (std >= cxx_version::cxx11) + { + switch (arg_type_) + { + case CtorArgType::complex_auto_ptr: + { + bool simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + move = !simple; + break; + } + case CtorArgType::poly_auto_ptr: + { + move = polymorphic && polymorphic_p (e.type ()); + break; + } + case CtorArgType::type: + break; + } + } + + os << "," << endl + << " " << member << " (" << (move ? "std::move (" : "") << + ename (e) << (move ? ")" : "") << ", this)"; + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + bool def (a.default_p ()); + + if (min (a) == 0 && !def) + { + // optional + // + os << "," << endl + << " " << member << " (this)"; + } + else + { + // one + // + + if (def) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), this)"; + } + else + { + os << "," << endl + << " " << member << " (" << ename (a) << ", this)"; + } + } + } + + private: + CtorArgType arg_type_; + }; + + struct CtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CtorAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + if (max (a) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else if (min (a) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else + { + // one + // + os << "," << endl + << " " << member << " (" << ename (a) << ", this->" << + dom_doc << " ())"; + } + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << emember (a) << " (this->" << dom_doc << " ())"; + } + }; + + + struct CopyMember: Traversal::Member, Context + { + CopyMember (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", f, this)"; + } + + private: + String arg_name; + }; + + struct CopyAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CopyAny (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + private: + String arg_name; + }; + + struct AssignMember: Traversal::Member, Context + { + AssignMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + os << "this->" << member << " = x." << member << ";"; + } + }; + + struct AssignAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + AssignAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + os << "this->" << member << " = x." << member << ";"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + os << "this->" << member << " = x." << member << ";"; + } + }; + + + // Element parsing c-tor initializers. + // + struct ElementCtorMember: Traversal::Member, Context + { + ElementCtorMember (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (this)"; + } + }; + + struct ElementCtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + ElementCtorAny (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + + // Default c-tor member initializer. + // + struct DefaultCtorMemberInit: Traversal::Element, + Traversal::Attribute, + Context + { + DefaultCtorMemberInit (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + os << "," << endl + << " " << member << " (this)"; + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + if (a.default_p ()) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), this)"; + } + else + os << "," << endl + << " " << member << " (this)"; + } + }; + + struct DefaultCtorAnyInit: Traversal::Any, + Traversal::AnyAttribute, + Context + { + DefaultCtorAnyInit (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + // Test whether the base has comparison operators. + // + struct HasComparisonOperator: Traversal::Fundamental::Type, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Traversal::Enumeration, + Traversal::Member, + Traversal::Any, + Traversal::AnyAttribute, + Context + { + // generate should initially be false. + // + HasComparisonOperator (Context& c, bool& generate) + : Context (c), generate_ (generate) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual void + traverse (SemanticGraph::Fundamental::Type&) + { + // All built-in types are comparable. + generate_ = true; + } + + virtual void + traverse (SemanticGraph::List&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Union&) + { + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Enumeration& e) + { + Traversal::Enumeration::inherits (e); + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + Complex::names (c); + + if (!generate_) + Complex::inherits (c); + } + + virtual void + traverse (SemanticGraph::Member& m) + { + if (!skip (m)) + generate_ = true; + } + + virtual void + traverse (SemanticGraph::Any&) + { + if (options.generate_wildcard ()) + generate_ = true; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.generate_wildcard ()) + generate_ = true; + } + + private: + bool& generate_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // + // + struct MemberComparison: Traversal::Element, + Traversal::Attribute, + Context + { + MemberComparison (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (!poly) + { + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + else + { + os << "{" + << "::xsd::cxx::tree::comparison_map< " << char_type + << " >& cm (" << endl + << "::xsd::cxx::tree::comparison_map_instance< " << + poly_plate << ", " << char_type << " > ());" + << endl; + + if (max (e) != 1) + { + // sequence + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (a.size () != b.size ())" << endl + << "return false;" + << endl; + + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "ai (a.begin ()), bi (b.begin ()), " << + "ae (a.end ()), be (b.end ());" << endl + << "ai != ae; ++ai, ++bi)" + << "{" + << "if (!cm.compare (*ai, *bi))" << endl + << "return false;" + << "}"; + } + else if (min (e) == 0) + { + // optional + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (!a || !b)" + << "{" + << "if (a.present () != b.present ())" << endl + << "return false;" + << "}" + << "else" + << "{" + << "if (!cm.compare (*a, *b))" << endl + << "return false;" + << "}"; + } + else + { + // one + // + os << "if (!cm.compare (x." << aname << " (), y." << + aname << " ()))" << endl + << "return false;"; + } + + os << "}"; + } + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + struct AnyComparison: Traversal::Any, + Traversal::AnyAttribute, + Context + { + AnyComparison (Context& c) + : Context (c) + { + } + + virtual void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + + if (max (a) == 1 && min (a) == 1) + os << "if (!x." << aname << " ().isEqualNode (&y." << + aname << " ()))"; + else + os << "if (!(x." << aname << " () == y." << aname << " ()))"; + + os << endl + << "return false;" + << endl; + } + + virtual void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + // Check whether a type has a parse() function (i.e., has any + // members, recursively). + // + struct HasParseFunction: Traversal::Complex, + Traversal::Element, + Traversal::Any, + Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + HasParseFunction (Context& c, bool& has_el, bool& has_at) + : Context (c), has_el_ (has_el), has_at_ (has_at) + { + *this >> names_ >> *this; + *this >> inherits_ >> *this; + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + if (mixed_p (c) && !c.context ().count ("mixed-in-base")) + has_el_ = true; + + names (c); + + if (!(has_el_ && has_at_)) + inherits (c); + } + + virtual void + traverse (SemanticGraph::Element&) + { + has_el_ = true; + } + + virtual void + traverse (SemanticGraph::Any&) + { + has_el_ = true; + } + + virtual void + traverse (SemanticGraph::Attribute&) + { + has_at_ = true; + } + + virtual void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.generate_wildcard ()) + has_at_ = true; + } + + private: + bool& has_el_; + bool& has_at_; + + Traversal::Names names_; + Traversal::Inherits inherits_; + }; + + // + // + struct FacetArray: Traversal::Complex, Context + { + FacetArray (Context& c) + : Context (c) + { + } + + virtual void + traverse (Type& c) + { + Facets f; + FacetCollector col (f); + col.traverse (c); + + for (Facets::const_iterator i (f.begin ()); i != f.end (); ++i) + { + if (i->first == L"fractionDigits") + os << "{::xsd::cxx::tree::facet::fraction_digits, " << + i->second << "UL}," << endl; + else if (i->first == L"totalDigits") + os << "{::xsd::cxx::tree::facet::total_digits, " << + i->second << "UL}," << endl; + } + } + + private: + typedef map<String, String> Facets; + + struct FacetCollector: Traversal::Complex + { + FacetCollector (Facets& facets) + : facets_ (facets) + { + *this >> inherits_ >> *this; + } + + virtual void + traverse (Type& c) + { + if (c.inherits_p ()) + { + // First collect our base so that we can override its + // facets. + // + inherits (c); + + using SemanticGraph::Restricts; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty ()) + { + Restricts::FacetIterator i (r->facet_find ("totalDigits")); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + + i = r->facet_find ("fractionDigits"); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + } + } + } + } + + private: + Traversal::Inherits inherits_; + Facets& facets_; + }; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + member_name_ (c), + any_ (c), + element_ (c), + any_test_ (c), + element_test_ (c), + attribute_ (c), + attribute_test_ (c), + any_attribute_ (c), + default_ctor_any_init_ (c), + default_ctor_member_init_ (c), + ctor_any_ (c), + ctor_member_ (c, CtorArgType::type), + element_ctor_any_ (c), + element_ctor_member_ (c), + assign_any_ (c), + assign_member_ (c), + comparison_any_ (c), + comparison_member_ (c), + facet_array_ (c) + { + bool gen_wildcard (options.generate_wildcard ()); + + inherits_member_ >> member_name_; + + names_element_ >> element_; + if (gen_wildcard) + names_element_ >> any_; + + names_element_test_ >> element_test_; + if (gen_wildcard) + names_element_test_ >> any_test_; + + names_attribute_ >> attribute_; + names_attribute_test_ >> attribute_test_; + names_any_attribute_ >> any_attribute_; + + default_ctor_init_names_ >> default_ctor_member_init_; + if (gen_wildcard) + default_ctor_init_names_ >> default_ctor_any_init_; + + ctor_names_ >> ctor_member_; + if (gen_wildcard) + ctor_names_ >> ctor_any_; + + element_ctor_names_ >> element_ctor_member_; + if (gen_wildcard) + element_ctor_names_ >> element_ctor_any_; + + assign_names_ >> assign_member_; + if (gen_wildcard) + assign_names_ >> assign_any_; + + comparison_names_ >> comparison_member_; + if (gen_wildcard) + comparison_names_ >> comparison_any_; + } + + + virtual void + traverse (Type& c) + { + bool gen_wildcard (options.generate_wildcard ()); + + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + bool renamed (renamed_type (c, name)); + if (renamed && !name) + return; + + SemanticGraph::Context& ctx (c.context ()); + + bool mixed (mixed_p (c) && !ctx.count ("mixed-in-base")); + bool ordered (ordered_p (c) && !ctx.count ("order-in-base")); + + bool string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (c); + } + + SemanticGraph::Enumeration* enum_base (0); + { + IsEnumBasedType t (enum_base); + t.dispatch (c); + } + + bool facets (false); + String base; // base type name + if (c.inherits_p ()) + { + // Get base name. + // + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + // Cannot use inherits_none here because need the + // result in a string. + // + inherits (c, inherits_type); + + base = o.str (); + + // See if we have any facets that we need to handle. + // + using SemanticGraph::Restricts; + using SemanticGraph::Fundamental::Decimal; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty () && + (r->facet_find ("fractionDigits") != r->facet_end () || + r->facet_find ("totalDigits") != r->facet_end ()) && + ultimate_base (c).is_a<Decimal> ()) + facets = true; + } + } + else + base = any_type; + + os << "// " << name << endl + << "//" << endl + << endl; + + // + // + { + Member member (*this, name); + Traversal::Names names_member (member); + names (c, names_member); + } + + // facets + // + if (facets) + { + os << "static const ::xsd::cxx::tree::facet _xsd_" << name << + "_facet_table[] = " + << "{"; + + facet_array_.traverse (c); + + os << "{::xsd::cxx::tree::facet::none, 0UL}" + << "};"; + } + + // c-tors + // + bool generate_no_base_ctor (false); + { + GenerateWithoutBaseCtor t (generate_no_base_ctor); + t.traverse (c); + } + + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // default c-tor + // + if (options.generate_default_ctor ()) + { + bool generate (false); + { + GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); + t.traverse (c); + } + + if (generate) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, default_ctor_init_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + // c-tor (base, all-non-optional-members) + // + if (options.generate_from_base_ctor ()) + { + bool generate (false); + { + GenerateFromBaseCtor t (*this, generate); + t.traverse (c); + } + + if (generate) + { + bool has_complex_non_op_args (false); + bool has_poly_non_op_args (false); + bool complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + String base_arg ( + L"_xsd_" + ename (c.inherits ().base ()) + L"_base"); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, CtorArgType::type, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, at, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, at, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + } + + // c-tor (all-non-optional-members) + // + if (generate_no_base_ctor) + { + CtorArgType const at (CtorArgType::type); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. One case where + // this c-tor will be generated is restriction of anyType. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args (*this, at, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, at, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + if (string_based) + { + // We might not have the value type if this enum is customized. + // + if (enum_base != 0 && enum_base->context ().count ("value")) + { + // c-tor (enum-value, all-non-optional-members) + // + CtorArgType const at (CtorArgType::type); + String base_arg (L"_xsd_" + ename (*enum_base) + L"_base"); + + os << name << "::" << endl + << name << " (" << fq_name (*enum_base) << "::" << + evalue (*enum_base) << " " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + CtorArgType const at (CtorArgType::type); + String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base"); + + // c-tor (const char*, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << char_type << "* " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + + // c-tor (const std::string&, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << string_type << "& " << base_arg; + + { + CtorArgsWithoutBase ctor_args (*this, at, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + // Cannot be mixed. + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // c-tor (ultimate-base, all-non-optional-members) + // + { + CtorArgType const at (CtorArgType::type); + + os << name << "::" << endl + << name << " ("; + + String base_arg; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + CtorArgType const at (CtorArgType::complex_auto_ptr); + String base_arg; + + os << name << "::" << endl + << name << " ("; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + CtorArgType const at (CtorArgType::poly_auto_ptr); + String base_arg; + + os << name << "::" << endl + << name << " ("; + + { + CtorArgs ctor_args (*this, at, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, at, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + { + CtorMember t (*this, at); + Traversal::Names n (t); + + if (gen_wildcard) + n >> ctor_any_; + + names (c, n); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + + // copy c-tor + // + + os << name << "::" << endl + << name << " (const " << name << "& x," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (x, f, c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + String const& m (ctx.get<String> ("mixed-member")); + os << "," << endl + << " " << m << " (x." << m << ", f, this)"; + } + + if (ordered) + { + String const& m (ctx.get<String> ("order-member")); + os << "," << endl + << " " << m << " (x." << m << ")"; + } + + { + CopyAny copy_any (*this, "x"); + CopyMember copy_member (*this, "x"); + Traversal::Names names; + + names >> copy_member; + + if (gen_wildcard) + names >> copy_any; + + Complex::names (c, names); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // + // + bool he (has<Traversal::Element> (c)); + bool hae (has<Traversal::Any> (c)); + + bool ha (has<Traversal::Attribute> (c)); + bool haa (has<Traversal::AnyAttribute> (c)); + + // + // + if (!options.suppress_parsing ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f"; + + if (he || ha || hae || (haa && gen_wildcard) || mixed) + os << " | " << flags_type << "::base"; + + os << ", c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + if (mixed) + { + os << "," << endl + << " " << ctx.get<String> ("mixed-member") << " (this)"; + } + + names (c, element_ctor_names_); + + os << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);" + << endl; + + bool base_has_el (false), base_has_at (false); + + // We are only interested in this information if we are + // generating our own parse(). + // + if (he || ha || hae || (haa && gen_wildcard) || mixed) + { + if (c.inherits_p ()) + { + HasParseFunction test (*this, base_has_el, base_has_at); + test.dispatch (c.inherits ().base ()); + } + } + + //@@ Throw if p is not exhausted at the end. + // + if (he || ha || hae || (haa && gen_wildcard) || mixed) + os << "if ((f & " << flags_type << "::base) == 0)" + << "{" + << parser_type << " p (e, " << + (he || hae || base_has_el || mixed_p (c) ? "true, " : "false, ") << + (mixed_p (c) ? "true, " : "false, ") << + (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false") + << ");" + << "this->" << unclash (name, "parse") << " (p, f);" + << "}"; + + os << "}"; + + bool simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + } + + if (he || ha || hae || (haa && gen_wildcard) || mixed) + { + os << "void " << name << "::" << endl + << unclash (name, "parse") << " (" << + parser_type << "& p," << endl + << flags_type << + (he || ha || base_has_el || base_has_at ? " f" : "") << ")" + << "{"; + + // Allow the base to parse its part. + // + if (base_has_el || base_has_at) + os << "this->" << base << "::parse (p, f);" + << endl; + + if (he || hae || mixed_p (c)) + { + bool m (mixed_p (c)); + + os << "for (; p.more_content (); p.next_content (" << + (m ? "true" : "false") << "))" + << "{"; + + if (m) + { + String const& ma (ctx.get<String> ("mixed-aname")); + String const& mi (ctx.get<String> ("mixed-ordered-id-name")); + String const& oa (ctx.get<String> ("order-aname")); + String const& ot (ctx.get<String> ("order-type")); + + os << "if (p.cur_is_text ())" + << "{" + << "const " << xerces_ns << "::DOMText& t (" << + "p.cur_text ());" + << "this->" << ma << " ().push_back (" << endl + << "::xsd::cxx::xml::transcode< " << char_type << " > (" << + "t.getData (), t.getLength ()));" + << "this->" << oa << " ().push_back (" << endl + << ot << " (" << mi << "," << endl + << "this->" << ma << " ().size () - 1));" + << "continue;" + << "}"; + } + + if (he || hae) + { + os << "const " << xerces_ns << "::DOMElement& i (" << + "p.cur_element ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_element_); + } + + os << "break;" + << "}"; + + // Make sure all non-optional elements are set. + // + names (c, names_element_test_); + } + + if (ha || (haa && gen_wildcard)) + { + if (base_has_at) + os << "p.reset_attributes ();" + << endl; + + os << "while (p.more_attributes ())" + << "{" + << "const " << xerces_ns << "::DOMAttr& i (" << + "p.next_attribute ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_attribute_); + + // Generate anyAttribute code after all the attributes. + // + if (gen_wildcard) + names (c, names_any_attribute_); + + + // os << "{" // else block + // @@ + // This doesn't play well with inheritance because we + // don't expect base's attributes. Also there are other + // "special" attributes such as xmlns, etc. + // + // << "throw ::xsd::cxx::tree::unexpected_attribute ... " + // << "}"; + + os << "}"; // while loop + + // Make sure all non-optional attributes are set. + // + names (c, names_attribute_test_); + } + + os << "}"; + } + } + + // _clone + // + if (!(c.abstract_p () || + (renamed && polymorphic && polymorphic_p (c)))) + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // operator= + // + if (!options.suppress_assignment () && + (he || ha || (gen_wildcard && (hae || haa)))) + { + os << name << "& " << name << "::" << endl + << "operator= (const " << name << "& x)" + << "{" + << "if (this != &x)" + << "{" + << "static_cast< " << base << "& > (*this) = x;"; + + // Note that here we don't assign the DOMDocument that is + // used to hold wildcard fragments. Each document has its + // own copy. + + // Mixed text content. + // + if (mixed) + { + String const& m (ctx.get<String> ("mixed-member")); + os << "this->" << m << " = x." << m << ";"; + } + + // Order container. + // + if (ordered) + { + String const& m (ctx.get<String> ("order-member")); + os << "this->" << m << " = x." << m << ";"; + } + + names (c, assign_names_); + + os << "}" + << "return *this;" + << "}"; + } + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (c) && !c.abstract_p ()) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + // If this type is anonymous but substitutes, then it will + // be registered as part of the substitution registration. + // + if (!anonymous_p (c) && !options.suppress_parsing ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + + if ((!anonymous_p (c) || anonymous_substitutes_p (c)) && + options.generate_comparison ()) + { + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< " << + poly_plate << ", " << char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + + // Comparison operators. + // + if (options.generate_comparison () && + (he || ha || mixed || ordered || !c.inherits_p () || + ((hae || haa) && gen_wildcard))) + { + bool base_comp (false); + + if (c.inherits_p ()) + { + HasComparisonOperator test (*this, base_comp); + test.dispatch (c.inherits ().base ()); + } + + bool has_body (he || ha || ordered || mixed || base_comp || + ((hae || haa) && gen_wildcard)); + + os << "bool" << endl + << "operator== (const " << name << "&" << + (has_body ? " x" : "") << ", " << + "const " << name << "&" << (has_body ? " y" : "") << ")" + << "{"; + + if (base_comp) + os << "if (!(static_cast< const " << base << "& > (x) ==" << endl + << "static_cast< const " << base << "& > (y)))" << endl + << "return false;" + << endl; + + { + Complex::names (c, comparison_names_); + } + + if (mixed) + { + String const& an (ctx.get<String> ("mixed-aname")); + os << "if (!(x." << an << " () == y." << an << " ()))" << endl + << "return false;" + << endl; + } + + if (ordered) + { + String const& an (ctx.get<String> ("order-aname")); + os << "if (!(x." << an << " () == y." << an << " ()))" << endl + << "return false;" + << endl; + } + + os << "return true;" + << "}"; + + os << "bool" << endl + << "operator!= (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "return !(x == y);" + << "}"; + } + } + + private: + Traversal::Inherits inherits_member_; + MemberTypeName member_name_; + + Traversal::Names names_element_; + Traversal::Names names_element_test_; + + Traversal::Names names_attribute_; + Traversal::Names names_any_attribute_; + Traversal::Names names_attribute_test_; + + Any any_; + Element element_; + + AnyTest any_test_; + ElementTest element_test_; + + Attribute attribute_; + AttributeTest attribute_test_; + + AnyAttribute any_attribute_; + + DefaultCtorAnyInit default_ctor_any_init_; + DefaultCtorMemberInit default_ctor_member_init_; + Traversal::Names default_ctor_init_names_; + + CtorAny ctor_any_; + CtorMember ctor_member_; + Traversal::Names ctor_names_; + + ElementCtorAny element_ctor_any_; + ElementCtorMember element_ctor_member_; + Traversal::Names element_ctor_names_; + + AssignAny assign_any_; + AssignMember assign_member_; + Traversal::Names assign_names_; + + AnyComparison comparison_any_; + MemberComparison comparison_member_; + Traversal::Names comparison_names_; + + FacetArray facet_array_; + }; + + + // Generate element types and substitution group map entries. + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), + Context (c), + element_type_ (c.options.generate_element_type ()), + element_map_ (c.options.generate_element_map ()), + type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual void + traverse (Type& e) + { + SemanticGraph::Type& t (e.type ()); + + // Check if this element is abstract. + // + bool abst; + { + SemanticGraph::Complex* tc; + abst = (tc = dynamic_cast<SemanticGraph::Complex*> (&t)) != 0 && + tc->abstract_p (); + } + + if (!abst && element_type_ && doc_root_p (e)) + { + bool fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + bool simple (true); + if (!fund) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + String const& name (ename (e)); + String const& type (etype (e)); + String const& member (emember (e)); + + os << "// " << name << endl + << "//" << endl + << endl; + + // Virtual accessors. + // + os << "const " << any_type << "* " << name << "::" << endl + << "_value () const" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + os << any_type << "* " << name << "::" << endl + << "_value ()" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + // default c-tor + // + if (options.generate_default_ctor ()) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << member << " (0)" + << "{" + << "}"; + } + + // c-tor (value) + // + os << name << "::" << endl + << name << " (const " << type << "& x)" << endl + << ": " << member << " (x, 0)" + << "{" + << "}"; + + + // c-tor (auto_ptr<value>) + // + if (!simple || (polymorphic && polymorphic_p (t))) + { + os << name << "::" << endl + << name << " (" << auto_ptr << "< " << type << " > p)" << endl + << ": " << member << " (" << + (std >= cxx_version::cxx11 ? "::std::move (p)" : "p") << ", 0)" + << "{" + << "}"; + } + + // c-tor (xercesc::DOMElement) + // + SemanticGraph::Context& ec (e.context ()); + String const& name_member (ec.get<String> ("element-name-member")); + String const& ns_member (ec.get<String> ("element-ns-member")); + + bool parsing (!options.suppress_parsing ()); + if (parsing) + { + String const& tr (etraits (e)); + + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e, " << + flags_type << " f)" << endl + << ": " << member << " (0)" + << "{" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl + << "if (n.name () == " << name_member << " && " << + "n.namespace_ () == " << ns_member << ")" << endl + << "this->" << member << ".set (" << tr << + "::create (e, f, 0));" + << "else" << endl + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name (), n.namespace_ ()," << endl + << name_member << ", " << ns_member << ");" + << "}"; + } + + // copy c-tor + // + os << name << "::" << endl + << name << " (const " << name << "& x, " << + flags_type << " f)" << endl + << ": " << element_type << " ()," << endl + << " " << member << " (x." << member << ", f, 0)" + << "{" + << "}"; + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f) const" + << "{" + << "return new class " << name << " (*this, f);" + << "}"; + + // Element name and namespace accessors. + // + String const& aname (ec.get<String> ("element-name")); + String const& ans (ec.get<String> ("element-ns")); + + os << "const " << string_type << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << ans << " ()" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_name () const" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_namespace () const" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << " " << name << "::" << endl + << name_member << " (" << strlit (e.name ()) << ");" + << endl + << "const " << string_type << " " << name << "::" << endl + << ns_member << " (" << strlit (e.namespace_ ().name ()) << ");" + << endl; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Element map registration. + // + if (element_map_ && parsing) + { + os << "static " << endl + << "const ::xsd::cxx::tree::parser_init< " << name << ", " << + char_type << ", " << any_type << " >" << endl + << "_xsd_" << name << "_parser_init (" << + name << "::" << aname << " (), " << + name << "::" << ans << " ());" + << endl; + } + } + + // Note that we cannot just omit this element if it's abstract + // because it may serve as a "link" between the root of the + // substitution group and a non-abstract element that uses this + // element as its root (see element_factory_map::find_substitution() + // for details). + // + if (polymorphic && e.substitutes_p () && !options.suppress_parsing ()) + { + String const& name (ename (e)); + Type& r (e.substitutes ().root ()); + + os << "static" << endl + << "const ::xsd::cxx::tree::element_factory_initializer< " << + poly_plate << ", " << char_type << " >" << endl + << "_xsd_" << name << "_element_factory_init (" << endl + << strlit (r.name ()) << "," << endl + << strlit (r.namespace_ ().name ()) << "," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_ ().name ()) << "," << endl; + + if (abst) + os << "0"; + else + { + os << "&::xsd::cxx::tree::factory_impl< "; + belongs (e, belongs_); + os << " >"; + } + + os << ");" + << endl + << endl; + } + } + + private: + bool element_type_; + bool element_map_; + Traversal::Belongs belongs_; + MemberTypeName type_name_; + }; + } + + void + generate_tree_source (Context& ctx, size_t first, size_t last) + { + if (ctx.options.generate_wildcard ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/wildcard-source.hxx>" << endl + << endl; + } + + if (!ctx.options.suppress_parsing ()) + ctx.os << "#include <xsd/cxx/xml/dom/parsing-source.hxx>" << endl + << endl; + + if (ctx.polymorphic) + { + bool parsing (!ctx.options.suppress_parsing ()); + bool comparison (ctx.options.generate_comparison ()); + + if (parsing) + ctx.os << "#include <xsd/cxx/tree/type-factory-map.hxx>" << endl + << endl; + + if (comparison) + ctx.os << "#include <xsd/cxx/tree/comparison-map.hxx>" << endl + << endl; + + if (parsing || comparison) + { + bool import_maps (ctx.options.import_maps ()); + bool export_maps (ctx.options.export_maps ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (parsing && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (parsing && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl; + + if (parsing) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl; + + if (parsing) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "type_factory_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "comparison_plate< " << ctx.poly_plate << ", " << + ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{"; + + if (parsing) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "type_factory_plate_init;" + << endl; + + if (comparison) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::comparison_plate< " << + ctx.poly_plate << ", " << ctx.char_type << " >" << endl + << "comparison_plate_init;" + << endl; + + ctx.os << "}"; + } + } + + Traversal::Schema schema; + Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/cxx/tree/tree-source.hxx b/xsd/cxx/tree/tree-source.hxx new file mode 100644 index 0000000..66dcff7 --- /dev/null +++ b/xsd/cxx/tree/tree-source.hxx @@ -0,0 +1,18 @@ +// file : xsd/cxx/tree/tree-source.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_TREE_SOURCE_HXX +#define XSD_CXX_TREE_TREE_SOURCE_HXX + +#include <xsd/cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + void + generate_tree_source (Context&, size_t first, size_t last); + } +} + +#endif // XSD_CXX_TREE_TREE_SOURCE_HXX diff --git a/xsd/cxx/tree/validator.cxx b/xsd/cxx/tree/validator.cxx new file mode 100644 index 0000000..9785560 --- /dev/null +++ b/xsd/cxx/tree/validator.cxx @@ -0,0 +1,676 @@ +// file : xsd/cxx/tree/validator.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <set> +#include <iostream> + +#include <xsd/cxx/tree/validator.hxx> + +#include <libxsd-frontend/semantic-graph.hxx> +#include <libxsd-frontend/traversal.hxx> + +#include <xsd/cxx/tree/elements.hxx> + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + class ValidationContext: public Context + { + public: + ValidationContext (SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + Tree::options const& ops, + const WarningSet& disabled_warnings, + Counts const& counts, + bool generate_xml_schema, + bool& valid_) + : Context (std::wcerr, + root, + path, + ops, + counts, + generate_xml_schema, + 0, + 0, + 0, + 0), + disabled_warnings_ (disabled_warnings), + disabled_warnings_all_ (false), + valid (valid_), + subst_group_warning_issued (subst_group_warning_issued_), + subst_group_warning_issued_ (false) + { + if (disabled_warnings_.find ("all") != disabled_warnings_.end ()) + disabled_warnings_all_ = true; + } + + public: + bool + is_disabled (char const* w) + { + return disabled_warnings_all_ || + disabled_warnings_.find (w) != disabled_warnings_.end (); + } + + public: + String + xpath (SemanticGraph::Nameable& n) + { + if (n.is_a<SemanticGraph::Namespace> ()) + return L"<namespace-level>"; // There is a bug if you see this. + + if (n.named_p ()) + { + SemanticGraph::Scope& scope (n.scope ()); + + if (scope.is_a<SemanticGraph::Namespace> ()) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + else + { + return L"(anonymous type for " + + n.context ().get<String> ("instance-name") + L")"; + } + } + + protected: + ValidationContext (ValidationContext& c) + : Context (c), + disabled_warnings_ (c.disabled_warnings_), + disabled_warnings_all_ (c.disabled_warnings_all_), + valid (c.valid), + subst_group_warning_issued (c.subst_group_warning_issued) + { + } + + protected: + const WarningSet& disabled_warnings_; + bool disabled_warnings_all_; + + bool& valid; + + bool& subst_group_warning_issued; + bool subst_group_warning_issued_; + }; + + + // + // + struct Any: Traversal::Any, ValidationContext + { + Any (ValidationContext& c) + : ValidationContext (c) + { + } + + struct Element: Traversal::Element, ValidationContext + { + Element (ValidationContext& c, SemanticGraph::Any& any) + : ValidationContext (c), + any_ (any), + ns_ (any.definition_namespace ().name ()) + { + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + using SemanticGraph::Any; + + bool q (e.qualified_p ()); + String ns (q ? e.namespace_ ().name () : ""); + + for (Any::NamespaceIterator i (any_.namespace_begin ()); + i != any_.namespace_end (); ++i) + { + bool failed (false); + + if (*i == L"##any") + { + failed = true; + } + else if (*i == L"##other") + { + if (ns_) + { + // Note that here I assume that ##other does not + // include names without target namespace. This + // is not what the spec says but that seems to be + // the consensus. + // + failed = q && ns != ns_; + } + else + { + // No target namespace. + // + failed = q && ns != L""; + } + } + else if (*i == L"##local") + { + failed = !q || ns == L""; + } + else if (*i == L"##targetNamespace") + { + failed = (q && ns_ == ns) || (!q && ns_ == L""); + } + else + { + failed = q && *i == ns; + } + + if (failed) + { + Any& a (any_); + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning T001: namespace '" << *i << "' allows for " + << "element '" << e.name () << "'" << endl; + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning T001: generated code may not associate element '" + << e.name () << "' correctly if it appears in place of " + << "this wildcard" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: element '" << e.name () << "' is defined " + << "here" << endl; + } + } + } + + private: + SemanticGraph::Any& any_; + String ns_; + }; + + struct Complex: Traversal::Complex + { + Complex () + : up_ (true), down_ (true) + { + } + + virtual void + post (Type& c) + { + // Go down the inheritance hierarchy. + // + if (down_) + { + bool up = up_; + up_ = false; + + if (c.inherits_p ()) + dispatch (c.inherits ().base ()); + + up_ = up; + } + + // Go up the inheritance hierarchy. + // + if (up_) + { + bool down = down_; + down_ = false; + + for (Type::BegetsIterator i (c.begets_begin ()); + i != c.begets_end (); ++i) + { + dispatch (i->derived ()); + } + + down_ = down; + } + } + + private: + bool up_, down_; + }; + + virtual void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Compositor; + + // Find our complex type. + // + Compositor* c (&a.contained_particle ().compositor ()); + + while(!c->contained_compositor_p ()) + c = &c->contained_particle ().compositor (); + + SemanticGraph::Complex& type ( + dynamic_cast<SemanticGraph::Complex&> ( + c->contained_compositor ().container ())); + + Complex complex; + Traversal::Names names; + Element element (*this, a); + + complex >> names >> element; + + complex.dispatch (type); + } + }; + + + // + // + struct Traverser: Traversal::Schema, + Traversal::Complex, + Traversal::Type, + Traversal::Element, + ValidationContext + { + using Schema::traverse; + + Traverser (ValidationContext& c) + : ValidationContext (c), any_ (c) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_; + + names_ >> *this >> names_; + + // Any + // + if (!is_disabled ("T001")) + { + *this >> contains_compositor_ >> compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> any_; + } + } + + virtual void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Schema; + + traverse (static_cast<SemanticGraph::Type&> (c)); + + if (c.inherits_p ()) + { + SemanticGraph::Type& t (c.inherits ().base ()); + + if (t.named_p () && + types_.find ( + t.scope ().name () + L"#" + t.name ()) == types_.end ()) + { + // Don't worry about types that are in included/imported + // schemas. + // + Schema& s (dynamic_cast<Schema&> (t.scope ().scope ())); + + if (&s == &schema_root || sources_p (schema_root, s)) + { + valid = false; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": error: type '" << xpath (c) << "' inherits from " + << "yet undefined type '" << xpath (t) << "'" << endl; + + os << t.file () << ":" << t.line () << ":" << t.column () + << ": info: '" << xpath (t) << "' is defined here" + << endl; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": info: inheritance from a yet-undefined type is " + << "not supported" << endl; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": info: re-arrange your schema and try again" + << endl; + } + } + } + + Complex::traverse (c); + } + + virtual void + traverse (SemanticGraph::Type& t) + { + // This is also used to traverse Complex. + // + if (t.named_p ()) + { + types_.insert (t.scope ().name () + L"#" + t.name ()); + } + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (is_disabled ("T002")) + return; + + // Note that there is no test for generate_p since we want + // to catch cases when things are not being generated but + // most likely should have been. + // + if (e.substitutes_p () && !polymorphic && + !subst_group_warning_issued) + { + subst_group_warning_issued = true; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": warning T002: substitution groups are used but " + << "--generate-polymorphic was not specified" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: generated code may not be able to handle " + << "some conforming instances" << endl; + } + } + + // Return true if root sources s. + // + bool + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a<Sources> ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + set<String> types_; + + Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + + // Any. + // + Any any_; + Traversal::Compositor compositor_; + Traversal::ContainsParticle contains_particle_; + Traversal::ContainsCompositor contains_compositor_; + }; + + + struct AnonymousType: Traversal::Schema, + Traversal::Complex, + Traversal::Element, + Traversal::Attribute, + ValidationContext + { + using Schema::traverse; + using Complex::traverse; + + AnonymousType (ValidationContext& c) + : ValidationContext (c), + anonymous_error_issued_ (false) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + *this >> names_; + } + + bool + traverse_common (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named_p () + && !t.is_a<SemanticGraph::Fundamental::IdRef> () + && !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) + { + if (!anonymous_error_issued_) + { + valid = false; + anonymous_error_issued_ = true; + + wcerr << t.file () + << ": error: anonymous types detected" + << endl; + + wcerr << t.file () + << ": info: " + << "anonymous types are not supported in this mapping" + << endl; + + wcerr << t.file () + << ": info: consider explicitly naming these types or " + << "remove the --preserve-anonymous option to " + << "automatically name them" + << endl; + + if (!options.show_anonymous ()) + wcerr << t.file () + << ": info: use --show-anonymous option to see these " + << "types" << endl; + } + + return true; + } + + return false; + } + + virtual void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) return; + + if (traverse_common (e)) + { + if (options.show_anonymous ()) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: element '" << xpath (e) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Element::traverse (e); + } + + virtual void + traverse (SemanticGraph::Attribute& a) + { + if (traverse_common (a)) + { + if (options.show_anonymous ()) + { + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: attribute '" << xpath (a) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Attribute::traverse (a); + } + + private: + bool anonymous_error_issued_; + + set<String> types_; + + Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + }; + } + + bool Validator:: + validate (options const& ops, + SemanticGraph::Schema& schema, + SemanticGraph::Path const& path, + const WarningSet& disabled_warnings, + Counts const& counts) + { + bool valid (true); + ValidationContext ctx ( + schema, path, ops, disabled_warnings, counts, false, valid); + + // + // + bool import_maps (ops.import_maps ()); + bool export_maps (ops.export_maps ()); + + if (import_maps && export_maps) + { + wcerr << "error: --import-maps and --export-maps are " + << "mutually exclusive" << endl; + + return false; + } + + if (import_maps && !ctx.polymorphic) + { + wcerr << "error: --import-maps can only be specified together with " + << "--generate-polymorphic" << endl; + + return false; + } + + if (export_maps && !ctx.polymorphic) + { + wcerr << "error: --export-maps can only be specified together " << + "with --generate-polymorphic" << endl; + + return false; + } + + // + // + if (ops.char_type () != "char" && + ops.char_type () != "wchar_t" && + !ctx.is_disabled ("T003")) + { + wcerr << "warning T003: unknown base character type '" << + ops.char_type ().c_str () << "'" << endl; + } + + // + // + NarrowString tn (ops.type_naming ()); + + if (tn != "knr" && tn != "ucc" && tn != "java") + { + wcerr << "error: unknown type naming style specified: '" << + tn.c_str () << "'" << endl; + + return false; + } + + NarrowString fn (ops.function_naming ()); + + if (fn != "knr" && fn != "lcc" && fn != "ucc" && fn != "java") + { + wcerr << "error: unknown function naming style specified: '" << + fn.c_str () << "'" << endl; + + return false; + } + + // + // + bool element_type (ops.generate_element_type ()); + bool par (!ops.suppress_parsing ()); + bool ser (ops.generate_serialization ()); + + if (ops.generate_element_map ()) + { + if (!element_type) + { + wcerr << "error: --generate-element-map can only be specified " << + "together with --generate-element-type" << endl; + + return false; + } + + if (!(par || ser)) + { + wcerr << "error: --generate-element-map is specified but " << + "neither parsing nor serialization code is generated" << endl; + + return false; + } + } + + // Issue a warning if there are more than one global element + // and we are generating parsing/serialization functions or + // element types for all of them by default. + // + + if (counts.global_elements > 1 && + (element_type || par || ser) && + !ops.root_element_first () && + !ops.root_element_last () && + !ops.root_element_all () && + !ops.root_element_none () && + ops.root_element ().empty () && + !ctx.is_disabled ("T004")) + { + wcerr << schema.file () << ": warning T004: generating "; + + if (element_type) + wcerr << "element types"; + else + { + wcerr << (par ? "parsing " : "") << + (ser ? (par ? "and serialization " : "serialization ") : "") << + "functions"; + } + wcerr << " for " << counts.global_elements << " global elements" << + endl; + + wcerr << schema.file () << ": info: use --root-element-* options " + << "to specify document root(s)" << endl; + } + + + // Test for anonymout types. + // + { + AnonymousType traverser (ctx); + traverser.dispatch (schema); + } + + // Test the rest. + // + if (valid) + { + Traverser traverser (ctx); + traverser.dispatch (schema); + } + + return valid; + + // T005 is used in polymorphism-processor.cxx. + // + } + } +} diff --git a/xsd/cxx/tree/validator.hxx b/xsd/cxx/tree/validator.hxx new file mode 100644 index 0000000..23f3f04 --- /dev/null +++ b/xsd/cxx/tree/validator.hxx @@ -0,0 +1,29 @@ +// file : xsd/cxx/tree/validator.hxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef XSD_CXX_TREE_VALIDATOR_HXX +#define XSD_CXX_TREE_VALIDATOR_HXX + +#include <xsd/cxx/tree/elements.hxx> +#include <xsd/cxx/tree/options.hxx> + +#include <xsd/xsd.hxx> + +namespace CXX +{ + namespace Tree + { + class Validator + { + public: + bool + validate (options const&, + SemanticGraph::Schema&, + SemanticGraph::Path const& tu, + const WarningSet& disabled_warnings, + Counts const& counts); + }; + } +} + +#endif // XSD_CXX_TREE_VALIDATOR_HXX |