From 5e527213a2430bb3018e5eebd909aef294edf9b5 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 18 Dec 2020 18:48:46 +0300 Subject: Switch to build2 --- xsd/xsd/cxx/tree/counter.cxx | 260 ++ xsd/xsd/cxx/tree/counter.hxx | 25 + xsd/xsd/cxx/tree/default-value.cxx | 1273 ++++++++ xsd/xsd/cxx/tree/default-value.hxx | 355 ++ xsd/xsd/cxx/tree/elements.cxx | 1409 ++++++++ xsd/xsd/cxx/tree/elements.hxx | 2118 ++++++++++++ xsd/xsd/cxx/tree/fundamental-header.hxx | 1335 ++++++++ xsd/xsd/cxx/tree/generator.cxx | 1227 +++++++ xsd/xsd/cxx/tree/generator.hxx | 44 + xsd/xsd/cxx/tree/name-processor.cxx | 2399 ++++++++++++++ xsd/xsd/cxx/tree/name-processor.hxx | 28 + xsd/xsd/cxx/tree/options.cli | 479 +++ xsd/xsd/cxx/tree/order-processor.cxx | 243 ++ xsd/xsd/cxx/tree/order-processor.hxx | 29 + xsd/xsd/cxx/tree/parser-header.cxx | 472 +++ xsd/xsd/cxx/tree/parser-header.hxx | 19 + xsd/xsd/cxx/tree/parser-source.cxx | 541 ++++ xsd/xsd/cxx/tree/parser-source.hxx | 18 + xsd/xsd/cxx/tree/polymorphism-processor.cxx | 740 +++++ xsd/xsd/cxx/tree/polymorphism-processor.hxx | 30 + xsd/xsd/cxx/tree/serialization-header.cxx | 579 ++++ xsd/xsd/cxx/tree/serialization-header.hxx | 18 + xsd/xsd/cxx/tree/serialization-source.cxx | 1468 +++++++++ xsd/xsd/cxx/tree/serialization-source.hxx | 18 + xsd/xsd/cxx/tree/stream-extraction-source.cxx | 864 +++++ xsd/xsd/cxx/tree/stream-extraction-source.hxx | 18 + xsd/xsd/cxx/tree/stream-header.cxx | 181 ++ xsd/xsd/cxx/tree/stream-header.hxx | 18 + xsd/xsd/cxx/tree/stream-insertion-header.cxx | 178 + xsd/xsd/cxx/tree/stream-insertion-header.hxx | 18 + xsd/xsd/cxx/tree/stream-insertion-source.cxx | 623 ++++ xsd/xsd/cxx/tree/stream-insertion-source.hxx | 18 + xsd/xsd/cxx/tree/stream-source.cxx | 496 +++ xsd/xsd/cxx/tree/stream-source.hxx | 18 + xsd/xsd/cxx/tree/tree-forward.cxx | 325 ++ xsd/xsd/cxx/tree/tree-forward.hxx | 18 + xsd/xsd/cxx/tree/tree-header.cxx | 4299 +++++++++++++++++++++++++ xsd/xsd/cxx/tree/tree-header.hxx | 18 + xsd/xsd/cxx/tree/tree-inline.cxx | 1161 +++++++ xsd/xsd/cxx/tree/tree-inline.hxx | 18 + xsd/xsd/cxx/tree/tree-source.cxx | 3900 ++++++++++++++++++++++ xsd/xsd/cxx/tree/tree-source.hxx | 18 + xsd/xsd/cxx/tree/validator.cxx | 671 ++++ xsd/xsd/cxx/tree/validator.hxx | 29 + 44 files changed, 28016 insertions(+) create mode 100644 xsd/xsd/cxx/tree/counter.cxx create mode 100644 xsd/xsd/cxx/tree/counter.hxx create mode 100644 xsd/xsd/cxx/tree/default-value.cxx create mode 100644 xsd/xsd/cxx/tree/default-value.hxx create mode 100644 xsd/xsd/cxx/tree/elements.cxx create mode 100644 xsd/xsd/cxx/tree/elements.hxx create mode 100644 xsd/xsd/cxx/tree/fundamental-header.hxx create mode 100644 xsd/xsd/cxx/tree/generator.cxx create mode 100644 xsd/xsd/cxx/tree/generator.hxx create mode 100644 xsd/xsd/cxx/tree/name-processor.cxx create mode 100644 xsd/xsd/cxx/tree/name-processor.hxx create mode 100644 xsd/xsd/cxx/tree/options.cli create mode 100644 xsd/xsd/cxx/tree/order-processor.cxx create mode 100644 xsd/xsd/cxx/tree/order-processor.hxx create mode 100644 xsd/xsd/cxx/tree/parser-header.cxx create mode 100644 xsd/xsd/cxx/tree/parser-header.hxx create mode 100644 xsd/xsd/cxx/tree/parser-source.cxx create mode 100644 xsd/xsd/cxx/tree/parser-source.hxx create mode 100644 xsd/xsd/cxx/tree/polymorphism-processor.cxx create mode 100644 xsd/xsd/cxx/tree/polymorphism-processor.hxx create mode 100644 xsd/xsd/cxx/tree/serialization-header.cxx create mode 100644 xsd/xsd/cxx/tree/serialization-header.hxx create mode 100644 xsd/xsd/cxx/tree/serialization-source.cxx create mode 100644 xsd/xsd/cxx/tree/serialization-source.hxx create mode 100644 xsd/xsd/cxx/tree/stream-extraction-source.cxx create mode 100644 xsd/xsd/cxx/tree/stream-extraction-source.hxx create mode 100644 xsd/xsd/cxx/tree/stream-header.cxx create mode 100644 xsd/xsd/cxx/tree/stream-header.hxx create mode 100644 xsd/xsd/cxx/tree/stream-insertion-header.cxx create mode 100644 xsd/xsd/cxx/tree/stream-insertion-header.hxx create mode 100644 xsd/xsd/cxx/tree/stream-insertion-source.cxx create mode 100644 xsd/xsd/cxx/tree/stream-insertion-source.hxx create mode 100644 xsd/xsd/cxx/tree/stream-source.cxx create mode 100644 xsd/xsd/cxx/tree/stream-source.hxx create mode 100644 xsd/xsd/cxx/tree/tree-forward.cxx create mode 100644 xsd/xsd/cxx/tree/tree-forward.hxx create mode 100644 xsd/xsd/cxx/tree/tree-header.cxx create mode 100644 xsd/xsd/cxx/tree/tree-header.hxx create mode 100644 xsd/xsd/cxx/tree/tree-inline.cxx create mode 100644 xsd/xsd/cxx/tree/tree-inline.hxx create mode 100644 xsd/xsd/cxx/tree/tree-source.cxx create mode 100644 xsd/xsd/cxx/tree/tree-source.hxx create mode 100644 xsd/xsd/cxx/tree/validator.cxx create mode 100644 xsd/xsd/cxx/tree/validator.hxx (limited to 'xsd/xsd/cxx/tree') diff --git a/xsd/xsd/cxx/tree/counter.cxx b/xsd/xsd/cxx/tree/counter.cxx new file mode 100644 index 0000000..94bcc87 --- /dev/null +++ b/xsd/xsd/cxx/tree/counter.cxx @@ -0,0 +1,260 @@ +// file : xsd/cxx/tree/counter.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include + +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; + + 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/xsd/cxx/tree/counter.hxx b/xsd/xsd/cxx/tree/counter.hxx new file mode 100644 index 0000000..bc1dc79 --- /dev/null +++ b/xsd/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 +#include + +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/xsd/cxx/tree/default-value.cxx b/xsd/xsd/cxx/tree/default-value.cxx new file mode 100644 index 0000000..aefeda3 --- /dev/null +++ b/xsd/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 + +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 ( + 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 ( + xs_ns ().find ("IDREF").first->named ())); + } + + // URI. + // + void InitValue:: + traverse (SemanticGraph::Fundamental::AnyURI&) + { + collapse (value_); + os << strlit (value_); + } + + // Binary. + // + static unsigned char + base64_decode (unsigned char c) + { + unsigned char r = 0xFF; + + if (c >= 'A' && c <= 'Z') + r = static_cast (c - 'A'); + else if (c >= 'a' && c <= 'z') + r = static_cast (c - 'a' + 26); + else if (c >= '0' && c <= '9') + r = static_cast (c - '0' + 52); + else if (c == '+') + r = 62; + else if (c == '/') + r = 63; + + return r; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::Base64Binary& 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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << v; + + v = static_cast ((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 ((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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast ((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 ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << v; + + v = static_cast ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << v; + + v = static_cast ((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 (unsigned char c) + { + unsigned char r = 0xFF; + + if (c >= '0' && c <= '9') + r = static_cast (c - '0'); + else if (c >= 'A' && c <= 'F') + r = static_cast (10 + (c - 'A')); + else if (c >= 'a' && c <= 'f') + r = static_cast (10 + (c - 'a')); + + return r; + } + + void InitValue:: + traverse (SemanticGraph::Fundamental::HexBinary& 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 ((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 ( + 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/xsd/cxx/tree/default-value.hxx b/xsd/xsd/cxx/tree/default-value.hxx new file mode 100644 index 0000000..5485669 --- /dev/null +++ b/xsd/xsd/cxx/tree/default-value.hxx @@ -0,0 +1,355 @@ +// 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 +#include + +#include + +namespace CXX +{ + namespace Tree + { + struct IsLiteralValue: IsFundamentalType, Traversal::Complex + { + 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 + { + 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 + { + 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/xsd/cxx/tree/elements.cxx b/xsd/xsd/cxx/tree/elements.cxx new file mode 100644 index 0000000..fc080c8 --- /dev/null +++ b/xsd/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 + +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 ("container"); + flags_type = xs_name + L"::" + xsc.get ("flags"); + + if (ops.generate_element_type ()) + element_type = xs_name + L"::" + xsc.get ("element-type"); + + properties_type = xs_name + L"::" + xsc.get ("properties"); + + if (!ops.suppress_parsing () || ops.generate_serialization ()) + { + error_handler_type = xs_name + L"::" + + xsc.get ("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 ("tree-node-key"); + + if (ops.generate_serialization ()) + { + as_double_type_ = xs_name + L"::" + + xsc.get ("as-double"); + + as_decimal_type_ = xs_name + L"::" + + xsc.get ("as-decimal"); + + list_stream_type = xs_name + L"::" + + xsc.get ("list-stream"); + + namespace_infomap_type = xs_name + L"::" + + xsc.get ("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 (u)); + } + } + } + + bool Context:: + polymorphic_p (SemanticGraph::Type& t) + { + // IDREF templates cannot be polymorphic. + // + if (!t.named_p () && + (t.is_a () || + t.is_a ())) + return false; + + if (polymorphic_all) + { + bool fund (false); + IsFundamentalType test (fund); + test.dispatch (t); + return !fund; + } + else + return t.context ().get ("polymorphic"); + } + + bool Context:: + anonymous_substitutes_p (SemanticGraph::Type& t) + { + // IDREF templates cannot match. + // + if (!t.named_p () && + (t.is_a () || + t.is_a ())) + 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 (&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 () && + !b.is_a (); + } + } + + 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 (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 () || + (n.is_a () && generate_p (dynamic_cast (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 ("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/xsd/cxx/tree/elements.hxx b/xsd/xsd/cxx/tree/elements.hxx new file mode 100644 index 0000000..ed5eb77 --- /dev/null +++ b/xsd/xsd/cxx/tree/elements.hxx @@ -0,0 +1,2118 @@ +// 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 +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +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 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 + 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 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 RegexCustomTypeMap; + typedef std::map 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 ("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 ("aname"); + } + + static String const& + eaname (SemanticGraph::Any const& a) + { + return a.context ().get ("aname"); + } + + static String const& + eaname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("aname"); + } + + // Modifier name. + // + static String const& + emname (SemanticGraph::Member const& m) + { + return m.context ().get ("mname"); + } + + static String const& + emname (SemanticGraph::Any const& a) + { + return a.context ().get ("mname"); + } + + static String const& + emname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("mname"); + } + + // Detach name. + // + static String const& + edname (SemanticGraph::Member const& m) + { + return m.context ().get ("dname"); + } + + // + // + static String const& + etype (SemanticGraph::Member const& m) + { + return m.context ().get ("type"); + } + + static String const& + etraits (SemanticGraph::Member const& m) + { + return m.context ().get ("traits"); + } + + static String const& + econtainer (SemanticGraph::Member const& m) + { + return m.context ().get ("container"); + } + + static String const& + econtainer (SemanticGraph::Any const& a) + { + return a.context ().get ("container"); + } + + static String const& + econtainer (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("container"); + } + + static String const& + eiterator (SemanticGraph::Member const& m) + { + return m.context ().get ("iterator"); + } + + static String const& + eiterator (SemanticGraph::Any const& a) + { + return a.context ().get ("iterator"); + } + + static String const& + eiterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Member const& m) + { + return m.context ().get ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Any const& a) + { + return a.context ().get ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("const-iterator"); + } + + static String const& + emember (SemanticGraph::Member const& m) + { + return m.context ().get ("member"); + } + + static String const& + emember (SemanticGraph::Any const& a) + { + return a.context ().get ("member"); + } + + static String const& + emember (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get ("member"); + } + + static String const& + edefault_value (SemanticGraph::Member const& m) + { + return m.context ().get ("default-value"); + } + + static String const& + edefault_value_member (SemanticGraph::Member const& m) + { + return m.context ().get ("default-value-member"); + } + + // Underlying enum value type. + // + static String const& + evalue (SemanticGraph::Enumeration const& e) + { + return e.context ().get ("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 ("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 ("dom-document-member"); + } + + // Parsing and serialization function names. + // + static String const& + eparser (SemanticGraph::Element const& e) + { + return e.context ().get ("parser"); + } + + static String const& + eserializer (SemanticGraph::Element const& e) + { + return e.context ().get ("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 NamespaceStack; + typedef std::deque 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 + // + 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 + // + 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 + { + // 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 + { + 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 " + << endl; + + return true; + } + + private: + String prefix_; + bool long_; + bool unsigned_long_; + }; + } +} + +#endif // XSD_CXX_TREE_ELEMENTS_HXX diff --git a/xsd/xsd/cxx/tree/fundamental-header.hxx b/xsd/xsd/cxx/tree/fundamental-header.hxx new file mode 100644 index 0000000..a470154 --- /dev/null +++ b/xsd/xsd/cxx/tree/fundamental-header.hxx @@ -0,0 +1,1335 @@ +// 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 +#include +#include + +#include +#include + +#include + +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 + { + 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 ("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 + << "//" < ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("flags"), "::xsd::cxx::tree::flags"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Parsing properties." << endl + << " */" << endl; + + gen_typedef (c.get ("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 ("severity"), + "::xsd::cxx::tree::severity"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Error condition." << endl + << " */" << endl; + + gen_typedef (c.get ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 StringSet; + typedef std::vector 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/xsd/cxx/tree/generator.cxx b/xsd/xsd/cxx/tree/generator.cxx new file mode 100644 index 0000000..5601f4e --- /dev/null +++ b/xsd/xsd/cxx/tree/generator.cxx @@ -0,0 +1,1227 @@ +// file : xsd/cxx/tree/generator.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +using namespace std; +using namespace cutl; +using namespace XSDFrontend::SemanticGraph; + +// +// +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 Tools CC gives\n" + "// permission to link this program with the Xerces-C++ library (or with\n" + "// modified versions of Xerces-C++ that use the same license as Xerces-C++),\n" + "// and distribute linked combinations including the two. You must obey\n" + "// the GNU General Public License version 2 in all respects for all of\n" + "// the code used other than Xerces-C++. If you modify this copy of the\n" + "// program, you may extend this exception to your version of the program,\n" + "// but you are not obligated to do so. If you do not wish to do so, delete\n" + "// this exception statement from your version.\n" + "//\n" + "// Furthermore, Code Synthesis Tools CC makes a special exception for\n" + "// the Free/Libre and Open Source Software (FLOSS) which is described\n" + "// in the accompanying 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" + "// Tools CC prior to generating this code. See the license text for\n" + "// 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 Paths; + typedef vector > 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 ()); + + // 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 ()); + + Regex dep_expr (ops.dep_regex ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + dep_suffix + "#" + : ops.dep_regex ()); + + 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); + 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 ()) + { + hxx_path = out_dir / hxx_path; + ixx_path = out_dir / ixx_path; + fwd_path = out_dir / fwd_path; + 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 dep; + WideOutputFileStreams cxx; + + // DEP + // + if (gen_dep) + { + dep.open (dep_path.string ().c_str (), ios_base::out); + + if (!dep.is_open ()) + { + wcerr << dep_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (dep_path); + file_list.push_back (dep_path.string ()); + } + + // FWD + // + if (gen_cxx && forward) + { + 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 (gen_cxx && header) + { + 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 (gen_cxx && inline_) + { + 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 (gen_cxx && source) + { + for (Paths::iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + { + shared_ptr 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 (); + } + + unlinks.add (*i); + file_list.push_back (i->string ()); + cxx.push_back (s); + } + } + + // 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 + ind_filter; + + typedef + compiler::ostream_filter + 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 (); + + 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 " << endl + << endl + << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + fwd << "#include " << endl + << endl; + + // Generate. + // + { + ind_filter ind (fwd); // We don't want to indent prologues/epilogues. + generate_forward (ctx); + } + + fwd << "#include " << 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 " << endl + << endl + << "#if (LIBXSD_VERSION != " << XSD_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + hxx << "#include " << 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); + } + } + + 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 << "#include " << endl + << endl; + + // Copy 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; + + 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; + + // Generate. + // + { + ind_filter ind (ixx); // We don't want to indent prologues/epilogues. + generate_tree_inline (ctx, 1, 0); + } + + // 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 " << 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 " << 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/xsd/cxx/tree/generator.hxx b/xsd/xsd/cxx/tree/generator.hxx new file mode 100644 index 0000000..a9b96fe --- /dev/null +++ b/xsd/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 // Path +#include + +#include +#include + +#include +#include + +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/xsd/cxx/tree/name-processor.cxx b/xsd/xsd/cxx/tree/name-processor.cxx new file mode 100644 index 0000000..e26a5d8 --- /dev/null +++ b/xsd/xsd/cxx/tree/name-processor.cxx @@ -0,0 +1,2399 @@ +// file : xsd/cxx/tree/name-processor.cxx +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include +#include +#include +#include + +#include + +#include +#include + +using namespace std; + +namespace CXX +{ + namespace Tree + { + namespace + { + // + // + typedef set 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 (,type), three components + // (,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 (,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 + { + // 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 + { + // 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 == "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 == "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 + { + // 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 + { + void + push_back (String const& r) + { + vector::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 global_type_names_; + map 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& global_type_names; + map& 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 ("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 (m.scope ())); + + size_t max (Tree::Context::max (m)); + size_t min (Tree::Context::min (m)); + + String const& s (m.context ().get ("stem")); + String const& b (m.context ().get ("name")); + + bool def_attr (m.default_p () && + m.is_a ()); + + // 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 ()) + { + 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 () && 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 (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 ("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 ("cxx-tree-name-processor-stem-set")); + + NameSet& member_set ( + ctx.get ("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 () && + !base.is_a ()) + { + if (!base.context ().count ( + "cxx-tree-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_stem_set ( + base.context ().get ( + "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 ( + "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 ( + &p->inherits ().base ())) + { + if (mixed_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("mixed-type", bctx.get ("mixed-type")); + ctx.set ("mixed-const-iterator", + bctx.get ("mixed-const-iterator")); + ctx.set ("mixed-ordered-id-name", + bctx.get ("mixed-ordered-id-name")); + ctx.set ("mixed-aname", bctx.get ("mixed-aname")); + ctx.set ("mixed-member", bctx.get ("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 ( + &p->inherits ().base ())) + { + if (base->context ().count ("dom-document")) + { + c.context ().set ( + "dom-document", + base->context ().get ("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 ( + &p->inherits ().base ())) + { + if (ordered_p (*b)) + { + SemanticGraph::Context& bctx (b->context ()); + ctx.set ("order-type", bctx.get ("order-type")); + ctx.set ("order-const-iterator", + bctx.get ("order-const-iterator")); + ctx.set ("order-aname", bctx.get ("order-aname")); + ctx.set ("order-member", bctx.get ("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 + { + 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 + 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/xsd/cxx/tree/name-processor.hxx b/xsd/xsd/cxx/tree/name-processor.hxx new file mode 100644 index 0000000..632b05e --- /dev/null +++ b/xsd/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 + +#include +#include + +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/xsd/cxx/tree/options.cli b/xsd/xsd/cxx/tree/options.cli new file mode 100644 index 0000000..1f0b23f --- /dev/null +++ b/xsd/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 ; // std::size_t + +include ; // NarrowString, NarrowStrings + +include ; + +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 + { + "", + "Indicate that 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 . The 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 + { + "", + "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 + { + "", + "Indicate that element order in 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 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 + { + "", + "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 + { + "", + "Generate data representation stream insertion operators for the + 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 + { + "", + "Generate data representation stream extraction constructors for the + 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" + { + "