diff options
Diffstat (limited to 'xsd/xsd/cxx/tree')
42 files changed, 26536 insertions, 0 deletions
diff --git a/xsd/xsd/cxx/tree/cli.hxx b/xsd/xsd/cxx/tree/cli.hxx new file mode 100644 index 0000000..171711d --- /dev/null +++ b/xsd/xsd/cxx/tree/cli.hxx @@ -0,0 +1,228 @@ +// file : xsd/cxx/tree/cli.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_CLI_HXX +#define CXX_TREE_CLI_HXX + +#include <cult/types.hxx> + +#include <cult/containers/vector.hxx> + +#include <cult/cli/options.hxx> +#include <cult/cli/options-spec.hxx> + +namespace CXX +{ + namespace Tree + { + namespace CLI + { + using namespace Cult::Types; + + typedef Char const Key[]; + + extern Key char_type; + extern Key char_encoding; + extern Key output_dir; + extern Key generate_polymorphic; + extern Key polymorphic_type; + extern Key polymorphic_type_all; + extern Key generate_serialization; + extern Key generate_inline; + extern Key generate_ostream; + extern Key generate_doxygen; + extern Key generate_comparison; + extern Key generate_default_ctor; + extern Key generate_from_base_ctor; + extern Key generate_detach; + extern Key generate_wildcard; + extern Key generate_insertion; + extern Key generate_extraction; + extern Key generate_forward; + extern Key generate_xml_schema; + extern Key extern_xml_schema; + extern Key suppress_parsing; + extern Key generate_element_type; + extern Key generate_element_map; + extern Key generate_intellisense; + extern Key omit_default_attributes; + extern Key namespace_map; + extern Key namespace_regex; + extern Key namespace_regex_trace; + extern Key reserved_name; + extern Key type_naming; + extern Key function_naming; + extern Key type_regex; + extern Key accessor_regex; + extern Key one_accessor_regex; + extern Key opt_accessor_regex; + extern Key seq_accessor_regex; + extern Key modifier_regex; + extern Key one_modifier_regex; + extern Key opt_modifier_regex; + extern Key seq_modifier_regex; + extern Key parser_regex; + extern Key serializer_regex; + extern Key enumerator_regex; + extern Key element_type_regex; + extern Key name_regex_trace; + extern Key include_with_brackets; + extern Key include_prefix; + extern Key include_regex; + extern Key include_regex_trace; + extern Key guard_prefix; + extern Key root_element_first; + extern Key root_element_last; + extern Key root_element_all; + extern Key root_element_none; + extern Key root_element; + extern Key custom_type; + extern Key custom_type_regex; + extern Key hxx_suffix; + extern Key ixx_suffix; + extern Key cxx_suffix; + extern Key fwd_suffix; + extern Key hxx_regex; + extern Key ixx_regex; + extern Key cxx_regex; + extern Key fwd_regex; + extern Key hxx_prologue; + extern Key ixx_prologue; + extern Key cxx_prologue; + extern Key fwd_prologue; + extern Key prologue; + extern Key hxx_epilogue; + extern Key ixx_epilogue; + extern Key cxx_epilogue; + extern Key fwd_epilogue; + extern Key epilogue; + extern Key hxx_prologue_file; + extern Key ixx_prologue_file; + extern Key cxx_prologue_file; + extern Key fwd_prologue_file; + extern Key prologue_file; + extern Key hxx_epilogue_file; + extern Key ixx_epilogue_file; + extern Key cxx_epilogue_file; + extern Key fwd_epilogue_file; + extern Key epilogue_file; + extern Key parts; + extern Key parts_suffix; + extern Key export_symbol; + extern Key export_xml_schema; + extern Key export_maps; + extern Key import_maps; + extern Key show_anonymous; + extern Key show_sloc; + extern Key proprietary_license; + extern Key disable_multi_import; // Undocumented. + + + typedef Cult::CLI::Options< + + char_type, NarrowString, + char_encoding, NarrowString, + output_dir, NarrowString, + generate_polymorphic, Boolean, + polymorphic_type, Cult::Containers::Vector<NarrowString>, + polymorphic_type_all, Boolean, + generate_serialization, Boolean, + generate_inline, Boolean, + generate_ostream, Boolean, + generate_doxygen, Boolean, + generate_comparison, Boolean, + generate_default_ctor, Boolean, + generate_from_base_ctor, Boolean, + generate_detach, Boolean, + generate_wildcard, Boolean, + generate_insertion, Cult::Containers::Vector<NarrowString>, + generate_extraction, Cult::Containers::Vector<NarrowString>, + generate_forward, Boolean, + generate_xml_schema, Boolean, + extern_xml_schema, NarrowString, + suppress_parsing, Boolean, + generate_element_type, Boolean, + generate_element_map, Boolean, + generate_intellisense, Boolean, + omit_default_attributes, Boolean, + namespace_map, Cult::Containers::Vector<NarrowString>, + namespace_regex, Cult::Containers::Vector<NarrowString>, + namespace_regex_trace, Boolean, + reserved_name, Cult::Containers::Vector<NarrowString>, + type_naming, NarrowString, + function_naming, NarrowString, + type_regex, Cult::Containers::Vector<NarrowString>, + accessor_regex, Cult::Containers::Vector<NarrowString>, + one_accessor_regex, Cult::Containers::Vector<NarrowString>, + opt_accessor_regex, Cult::Containers::Vector<NarrowString>, + seq_accessor_regex, Cult::Containers::Vector<NarrowString>, + modifier_regex, Cult::Containers::Vector<NarrowString>, + one_modifier_regex, Cult::Containers::Vector<NarrowString>, + opt_modifier_regex, Cult::Containers::Vector<NarrowString>, + seq_modifier_regex, Cult::Containers::Vector<NarrowString>, + parser_regex, Cult::Containers::Vector<NarrowString>, + serializer_regex, Cult::Containers::Vector<NarrowString>, + enumerator_regex, Cult::Containers::Vector<NarrowString>, + element_type_regex, Cult::Containers::Vector<NarrowString>, + name_regex_trace, Boolean, + include_with_brackets, Boolean, + include_prefix, NarrowString, + include_regex, Cult::Containers::Vector<NarrowString>, + include_regex_trace, Boolean, + guard_prefix, NarrowString, + root_element_first, Boolean, + root_element_last, Boolean, + root_element_all, Boolean, + root_element_none, Boolean, + root_element, Cult::Containers::Vector<NarrowString>, + custom_type, Cult::Containers::Vector<NarrowString>, + custom_type_regex, Cult::Containers::Vector<NarrowString>, + hxx_suffix, NarrowString, + ixx_suffix, NarrowString, + cxx_suffix, NarrowString, + fwd_suffix, NarrowString, + hxx_regex, NarrowString, + ixx_regex, NarrowString, + cxx_regex, NarrowString, + fwd_regex, NarrowString, + hxx_prologue, Cult::Containers::Vector<NarrowString>, + ixx_prologue, Cult::Containers::Vector<NarrowString>, + cxx_prologue, Cult::Containers::Vector<NarrowString>, + fwd_prologue, Cult::Containers::Vector<NarrowString>, + prologue, Cult::Containers::Vector<NarrowString>, + hxx_epilogue, Cult::Containers::Vector<NarrowString>, + ixx_epilogue, Cult::Containers::Vector<NarrowString>, + cxx_epilogue, Cult::Containers::Vector<NarrowString>, + fwd_epilogue, Cult::Containers::Vector<NarrowString>, + epilogue, Cult::Containers::Vector<NarrowString>, + hxx_prologue_file, NarrowString, + ixx_prologue_file, NarrowString, + cxx_prologue_file, NarrowString, + fwd_prologue_file, NarrowString, + prologue_file, NarrowString, + hxx_epilogue_file, NarrowString, + ixx_epilogue_file, NarrowString, + cxx_epilogue_file, NarrowString, + fwd_epilogue_file, NarrowString, + epilogue_file, NarrowString, + parts, UnsignedLong, + parts_suffix, NarrowString, + export_symbol, NarrowString, + export_xml_schema, Boolean, + export_maps, Boolean, + import_maps, Boolean, + show_anonymous, Boolean, + show_sloc, Boolean, + proprietary_license, Boolean, + disable_multi_import, Boolean + + > Options; + + struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {}; + } + } +} + +#endif // CXX_TREE_CLI_HXX diff --git a/xsd/xsd/cxx/tree/counter.cxx b/xsd/xsd/cxx/tree/counter.cxx new file mode 100644 index 0000000..9254226 --- /dev/null +++ b/xsd/xsd/cxx/tree/counter.cxx @@ -0,0 +1,267 @@ +// file : xsd/cxx/tree/counter.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/counter.hxx> + +#include <iostream> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct Member: Traversal::Member + { + Member (UnsignedLong& complexity) + : complexity_ (complexity) + { + } + + virtual Void + traverse (Type&) + { + complexity_++; + } + + UnsignedLong& complexity_; + }; + + struct Any: Traversal::Any, Traversal::AnyAttribute + { + Any (UnsignedLong& complexity) + : complexity_ (complexity) + { + } + + virtual Void + traverse (SemanticGraph::Any&) + { + complexity_++; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute&) + { + complexity_++; + } + + UnsignedLong& complexity_; + }; + + struct TypeBase: Traversal::List, + Traversal::Union, + Traversal::Enumeration, + Traversal::Complex, + Context + { + TypeBase (Context& c, UnsignedLong& complexity) + : Context (c), complexity_ (complexity) + { + } + + virtual Void + traverse (SemanticGraph::List&) + { + complexity_++; + } + + virtual Void + traverse (SemanticGraph::Union&) + { + complexity_++; + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + Boolean 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.value<CLI::generate_wildcard> ()) + names >> any; + + Complex::names (c, names); + } + + private: + UnsignedLong& complexity_; + }; + + + // + // + struct GlobalType: Traversal::Type, Context + + { + GlobalType (Context& c, Counts& counts) + : Context (c), counts_ (counts) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + counts_.global_types++; + + UnsignedLong 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++; + + UnsignedLong complexity (0); + + if (doc_root_p (*last_)) + { + if (options.value<CLI::generate_element_type> ()) + { + complexity += 1; // For c-tors and d-tor. + + if (!options.value<CLI::suppress_parsing> ()) + complexity += 1; + + if (options.value<CLI::generate_serialization> ()) + complexity += 1; + } + else + { + if (!options.value<CLI::suppress_parsing> ()) + complexity += 6; // 13 parsing functions. + + if (options.value<CLI::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_; + }; + } + + Counter:: + Counter () + { + } + + Counts Counter:: + count (CLI::Options const& options, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& path) + { + Counts counts; + Context ctx (std::wcerr, tu, path, options, counts, false, 0, 0, 0, 0); + + Traversal::Schema schema; + Traversal::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..726de47 --- /dev/null +++ b/xsd/xsd/cxx/tree/counter.hxx @@ -0,0 +1,29 @@ +// file : xsd/cxx/tree/counter.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_COUNTER_HXX +#define CXX_TREE_COUNTER_HXX + +#include <cxx/tree/elements.hxx> +#include <cxx/tree/cli.hxx> + +namespace CXX +{ + namespace Tree + { + class Counter + { + public: + Counter (); // Dummy ctor, helps with long symbols on HP-UX. + + Counts + count (CLI::Options const&, + SemanticGraph::Schema&, + SemanticGraph::Path const&); + }; + } +} + +#endif // 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..ff964d3 --- /dev/null +++ b/xsd/xsd/cxx/tree/default-value.cxx @@ -0,0 +1,1256 @@ +// file : xsd/cxx/tree/default-value.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/default-value.hxx> + +using std::hex; + +namespace CXX +{ + namespace Tree + { + namespace + { + Void + normalize (String& s) + { + Size n (s.size ()); + + for (Size i (0); i < n; ++i) + { + WideChar& c (s[i]); + + if (c == 0x0D || // carriage return + c == 0x09 || // tab + c == 0x0A) + c = 0x20; + } + } + + Void + collapse (String& s) + { + Size n (s.size ()), j (0); + Boolean subs (false), trim (true); + + for (Size i (0); i < n; ++i) + { + WideChar c (s[i]); + + if (c == 0x20 || c == 0x09 || c == 0x0A) + subs = true; + else + { + if (subs) + { + subs = false; + + if (!trim) + s[j++] = 0x20; + } + + if (trim) + trim = false; + + s[j++] = c; + } + } + + s.resize (j); + } + + Void + strip_zeros (String& s) + { + Size n (s.size ()), i (0); + + if (n > 0 && (s[i] == '-' || s[i] == '+')) + i++; + + Size j (i); + + Boolean strip (true); + + for (; i < n; ++i) + { + WideChar c (s[i]); + + if (c == '0') + { + if (!strip) + s[j++] = c; + } + else + { + s[j++] = c; + + if (strip) + strip = false; + } + } + + if (strip && j < n) + s[j++] = '0'; // There was nothing except zeros so add one back. + + s.resize (j); + } + + 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 (Boolean& 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_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Short&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedShort&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Int&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::UnsignedInt&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + } + + Void LiteralValue:: + traverse (SemanticGraph::Fundamental::Long&) + { + collapse (value_); + strip_zeros (value_); + literal_ = value_; + literal_ += 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 b (0); + + for (Size 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)); + } + + // anySimpleType. + // + Void InitValue:: + traverse (SemanticGraph::AnySimpleType& t) + { + os << fq_name (t) << " (" << strlit (value_) << ")"; + } + + // Strings. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::String&) + { + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NormalizedString&) + { + normalize (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Token&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NameToken&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NameTokens&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("NMTOKEN").first->named ())); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Name&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::NCName&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Language&) + { + collapse (value_); + os << strlit (value_); + } + + // Qualified name. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::QName& t) + { + Size p (value_.rfind ('#')); + + if (p != String::npos) + { + String ns (value_, 0, p); + String qname (value_, p + 1, String::npos); + + collapse (ns); + collapse (qname); + + p = qname.find (':'); + + String name; + if (p != String::npos) + name.assign (qname, p + 1, String::npos); + else + name = qname; + + os << fq_name (t) << " (" << strlit (ns) << ", " << + strlit (name) << ")"; + } + else + { + // Unqualified name. + // + collapse (value_); + os << fq_name (t) << " (" << strlit (value_) << ")"; + } + } + + // ID/IDREF. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Id&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::IdRef&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::IdRefs&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("IDREF").first->named ())); + } + + // URI. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::AnyURI&) + { + collapse (value_); + os << strlit (value_); + } + + // Binary. + // + static unsigned char + base64_decode (unsigned char c) + { + unsigned char r = 0xFF; + + if (c >= 'A' && c <= 'Z') + r = static_cast<unsigned char> (c - 'A'); + else if (c >= 'a' && c <= 'z') + r = static_cast<unsigned char> (c - 'a' + 26); + else if (c >= '0' && c <= '9') + r = static_cast<unsigned char> (c - '0' + 52); + else if (c == '+') + r = 62; + else if (c == '/') + r = 63; + + return r; + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + collapse (value_); + + if (dispatch_count_++ == 0) + { + if (value_) + { + os << "unsigned char " << data_ << "[] = {"; + + // Decode. + // + Size size (value_.size ()); + + // Remove all whitespaces. + // + { + Size j (0); + Boolean subs (false); + + for (Size i (0); i < size; ++i) + { + WideChar c (value_[i]); + + if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09) + subs = true; + else + { + if (subs) + subs = false; + + value_[j++] = c; + } + } + + size = j; + value_.resize (size, '\0'); + } + + // Our length should be a multiple of four. + // + Size quad_count (size / 4); + + // Source and destination indexes. + // + Size si (0), di (0); + + // Process all quads except the last one. + // + unsigned short v; + unsigned char b1, b2, b3, b4; + + WideChar prev_fill (os.fill ('0')); + + for (Size q (0); q < quad_count - 1; ++q) + { + b1 = base64_decode (value_[si++]); + b2 = base64_decode (value_[si++]); + b3 = base64_decode (value_[si++]); + b4 = base64_decode (value_[si++]); + + if (q != 0) + os << ", "; + + if (di % 9 == 0) + os << endl; + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << hex << v; + + v = static_cast<unsigned char> ((b3 << 6) | b4); + os.width (2); + os << ", 0x" << hex << v; + + di += 3; + } + + // Process the last quad. The first two octets are always there. + // + b1 = base64_decode (value_[si++]); + b2 = base64_decode (value_[si++]); + + WideChar e3 (value_[si++]), e4 (value_[si++]); + + if (quad_count != 1) + os << ", "; + + if (di % 9 == 0) + os << endl; + + if (e4 == '=') + { + if (e3 == '=') + { + // Two pads. Last 4 bits in b2 should be zero. + // + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os << "0x" << hex << v; + di++; + } + else + { + // One pad. Last 2 bits in b3 should be zero. + // + b3 = base64_decode (e3); + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << hex << v; + + di += 2; + } + } + else + { + // No pads. + // + b3 = base64_decode (e3); + b4 = base64_decode (e4); + + v = static_cast<unsigned char> ((b1 << 2) | (b2 >> 4)); + os.width (2); + os << "0x" << hex << v; + + v = static_cast<unsigned char> ((b2 << 4) | (b3 >> 2)); + os.width (2); + os << ", 0x" << hex << v; + + v = static_cast<unsigned char> ((b3 << 6) | b4); + os.width (2); + os << ", 0x" << hex << v; + + di += 3; + } + + os.fill (prev_fill); + + os << "};"; + } + } + else + { + os << fq_name (t) << " ("; + + if (value_) + os << data_ << "," << endl + << "sizeof (" << data_ << ")," << endl + << "sizeof (" << data_ << ")," << endl + << "false"; + else + os << "0"; + + + os << ")"; + } + } + + static unsigned char + hex_decode (unsigned char c) + { + unsigned char r = 0xFF; + + if (c >= '0' && c <= '9') + r = static_cast<unsigned char> (c - '0'); + else if (c >= 'A' && c <= 'F') + r = static_cast<unsigned char> (10 + (c - 'A')); + else if (c >= 'a' && c <= 'f') + r = static_cast<unsigned char> (10 + (c - 'a')); + + return r; + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + collapse (value_); + + if (dispatch_count_++ == 0) + { + if (value_) + { + os << "unsigned char " << data_ << "[] = {"; + + // Decode. + // + Size n (value_.size () / 2); + WideChar prev_fill (os.fill ('0')); + + for (Size i (0); i < n; ++i) + { + unsigned char h (hex_decode (value_[2 * i])); + unsigned char l (hex_decode (value_[2 * i + 1])); + + if (h == 0xFF || l == 0xFF) + break; + + if (i != 0) + os << ", "; + + if (i % 9 == 0) + os << endl; + + unsigned short v = static_cast<unsigned char> ((h << 4) | l); + os.width (2); + os << "0x" << hex << v; + } + + os.fill (prev_fill); + + os << "};"; + } + } + else + { + os << fq_name (t) << " ("; + + if (value_) + os << data_ << "," << endl + << "sizeof (" << data_ << ")," << endl + << "sizeof (" << data_ << ")," << endl + << "false"; + else + os << "0"; + + + os << ")"; + } + } + + // Date/time. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Date& t) + { + // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM] + // + collapse (value_); + + Size b (0); + Size e (value_.find ('-', value_[0] == '-' ? 5 : 4)); + String year (value_, 0, e); + + b = e + 1; + String month (value_, b, 2); + + b += 3; + String day (value_, b, 2); + + strip_zeros (year); + strip_zeros (month); + strip_zeros (day); + + os << 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 b (0); + Size e (value_.find ('-', value_[0] == '-' ? 5 : 4)); + String year (value_, 0, e); + b = e + 1; + + String month (value_, b, 2); + b += 3; + + String day (value_, b, 2); + b += 3; + + String hours (value_, b, 2); + b += 3; + + String minutes (value_, b, 2); + b += 3; + + e = b + 2; + for (; e < value_.size (); ++e) + { + WideChar c (value_[e]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String seconds (value_, b, e - b); + + strip_zeros (year); + strip_zeros (month); + strip_zeros (day); + strip_zeros (hours); + strip_zeros (minutes); + strip_zeros (seconds); + make_float (seconds); + + os << fq_name (t) << " (" + << year << ", " << month << ", " << day << ", " + << hours << ", " << minutes << ", " << seconds; + time_zone (e); + os << ")"; + } + + namespace + { + Size + find_delim (String const& s, Size pos) + { + for (; pos < s.size (); ++pos) + { + WideChar c (s[pos]); + + if (c == 'Y' || c == 'D' || c == 'M' || c == 'H' || + c == 'M' || c == 'S' || c == 'T') + break; + } + + return pos; + } + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Duration& t) + { + // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S] + // + collapse (value_); + + Size 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 pos (value_[0] == '-' ? 5 : 4); + for (; pos < value_.size (); ++pos) + { + WideChar c (value_[pos]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String year (value_, 0, pos); + strip_zeros (year); + + os << 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 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 e (8); + for (; e < value_.size (); ++e) + { + WideChar c (value_[e]); + + if (c == 'Z' || c == '+' || c == '-') + break; + } + + String seconds (value_, 6, e - 6); + + strip_zeros (hours); + strip_zeros (minutes); + strip_zeros (seconds); + make_float (seconds); + + os << fq_name (t) << " (" << hours << ", " << minutes << ", " << seconds; + time_zone (e); + os << ")"; + } + + Void InitValue:: + time_zone (Size pos) + { + // time_zone := Z|(+|-)HH:MM + // + if (pos < value_.size ()) + { + String h, m; + + if (value_[pos] == 'Z') + { + h = "0"; + m = "0"; + } + else + { + if (value_[pos] == '-') + { + h = "-"; + m = "-"; + } + + h.append (value_, pos + 1, 2); + m.append (value_, pos + 4, 2); + + strip_zeros (h); + strip_zeros (m); + } + + os << ", " << h << ", " << m; + } + } + + // Entity. + // + Void InitValue:: + traverse (SemanticGraph::Fundamental::Entity&) + { + collapse (value_); + os << strlit (value_); + } + + Void InitValue:: + traverse (SemanticGraph::Fundamental::Entities&) + { + string_sequence_type ( + dynamic_cast<SemanticGraph::Type&> ( + xs_ns ().find ("ENTITY").first->named ())); + } + + Void InitValue:: + string_sequence_type (SemanticGraph::Type& t) + { + collapse (value_); + + if (!value_) + return; + + Size b (0); + + for (Size 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..c80132e --- /dev/null +++ b/xsd/xsd/cxx/tree/default-value.hxx @@ -0,0 +1,353 @@ +// file : xsd/cxx/tree/default-value.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_DEFAULT_VALUE_HXX +#define CXX_TREE_DEFAULT_VALUE_HXX + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + struct IsLiteralValue: IsFundamentalType, Traversal::Complex + { + IsLiteralValue (Boolean& 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::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&); + + // anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnySimpleType&); + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String&); + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString&); + + virtual Void + traverse (SemanticGraph::Fundamental::Token&); + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken&); + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens&); + + virtual Void + traverse (SemanticGraph::Fundamental::Name&); + + virtual Void + traverse (SemanticGraph::Fundamental::NCName&); + + virtual Void + traverse (SemanticGraph::Fundamental::Language&); + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName&); + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id&); + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef&); + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs&); + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI&); + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary&); + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary&); + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date&); + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime&); + + virtual Void + traverse (SemanticGraph::Fundamental::Duration&); + + virtual Void + traverse (SemanticGraph::Fundamental::Day&); + + virtual Void + traverse (SemanticGraph::Fundamental::Month&); + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay&); + + virtual Void + traverse (SemanticGraph::Fundamental::Year&); + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth&); + + virtual Void + traverse (SemanticGraph::Fundamental::Time&); + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity&); + + virtual Void + traverse (SemanticGraph::Fundamental::Entities&); + + private: + Void + string_sequence_type (SemanticGraph::Type& element_type); + + Void + time_zone (Size pos); + + private: + String value_; + String data_; + Size dispatch_count_; + MemberTypeName type_name_; + LiteralValue literal_value_; + }; + } +} + +#endif // 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..cad5a33 --- /dev/null +++ b/xsd/xsd/cxx/tree/elements.cxx @@ -0,0 +1,1355 @@ +// file : xsd/cxx/tree/elements.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + // Context + // + Void Context:: + update_ns_scope () // Keeping this function first helps HP-UX + { // (long symbols). + ns_scope.clear (); + + Boolean 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; + } + } + + Context:: + Context (std::wostream& o, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + CLI::Options const& ops, + Counts const& counts_, + Boolean generate_xml_schema__, + StringLiteralMap const* map, + Regex const* fe, + Regex const* he, + Regex const* ie) + : CXX::Context (o, + root, + path, + map, + ops.value<CLI::char_type> (), + ops.value<CLI::char_encoding> (), + ops.value<CLI::include_with_brackets> (), + ops.value<CLI::include_prefix> (), + ops.value<CLI::export_symbol> (), + ops.value<CLI::namespace_map> (), + ops.value<CLI::namespace_regex> (), + ops.value<CLI::namespace_regex_trace> (), + ops.value<CLI::include_regex> (), + ops.value<CLI::include_regex_trace> (), + ops.value<CLI::generate_inline> (), + ops.value<CLI::reserved_name> ()), + 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.value<CLI::generate_polymorphic> ()), + polymorphic_all (ops.value<CLI::polymorphic_type_all> ()), + detach (ops.value<CLI::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.value<CLI::generate_doxygen> ()), + ns_scope_stack (ns_scope_stack_), + cxx_uq_id_expr_ (L"^[a-zA-Z_]\\w*$"), + cxx_uq_id_expr (cxx_uq_id_expr_) + { + SemanticGraph::Namespace& xs (xs_ns ()); + SemanticGraph::Context& xsc (xs.context ()); + + // Cache some often-used names from the XML Schema namespace + // if names have already been processed. + // + if (xsc.count ("container")) + { + String xs_name (ns_name (xs)); + + any_type = fq_name (xs.find ("anyType").first->named ()); + any_simple_type = fq_name (xs.find ("anySimpleType").first->named ()); + xs_string_type = fq_name (xs.find ("string").first->named ()); + + container = xs_name + L"::" + xsc.get<String> ("container"); + flags_type = xs_name + L"::" + xsc.get<String> ("flags"); + + if (ops.value<CLI::generate_element_type> ()) + element_type = xs_name + L"::" + xsc.get<String> ("element-type"); + + properties_type = xs_name + L"::" + xsc.get<String> ("properties"); + + if (!ops.value<CLI::suppress_parsing> () || + ops.value<CLI::generate_serialization> ()) + { + error_handler_type = xs_name + L"::" + + xsc.get<String> ("error-handler"); + } + + dom_auto_ptr_ = xs_name + L"::dom::auto_ptr"; + dom_node_key_ = xs_name + L"::dom::" + + xsc.get<String> ("tree-node-key"); + + if (ops.value<CLI::generate_serialization> ()) + { + as_double_type_ = xs_name + L"::" + + xsc.get<String> ("as-double"); + + as_decimal_type_ = xs_name + L"::" + + xsc.get<String> ("as-decimal"); + + list_stream_type = xs_name + L"::" + + xsc.get<String> ("list-stream"); + + namespace_infomap_type = xs_name + L"::" + + xsc.get<String> ("namespace-infomap"); + } + + // istream and ostream are templates and for now use the same + // names regardless of the naming convention. + // + if (!ops.value<CLI::generate_extraction> ().empty ()) + istream_type = xs_name + L"::istream"; + + if (!ops.value<CLI::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.value<CLI::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. + // + typedef Containers::Vector<NarrowString> Vector; + + // Direct custom type mapping. + // + { + Vector const& v (ops.value<CLI::custom_type> ()); + + for (Vector::ConstIterator 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 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. + // + { + Vector const& v (ops.value<CLI::custom_type_regex> ()); + + for (Vector::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i) + { + String s (*i); + + if (s.empty ()) + throw InvalidCustomTypeMapping (s, "mapping string is empty"); + + WideChar delimiter (s[0]); + + // First get pattern. + // + Size 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 (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), + 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), + 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) + { + } + + Boolean Context:: + custom_type (SemanticGraph::Type const& t, String& r) const + { + String const& name (t.name ()); + + // First search the direct mapping. + // + { + DirectCustomTypeMap::ConstIterator 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::ConstIterator + 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.merge (i->type_sub, name); + 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; + } + + Boolean Context:: + renamed_type (SemanticGraph::Type const& t, String& r) const + { + String const& name (t.name ()); + + // First search the direct mapping. + // + { + DirectCustomTypeMap::ConstIterator 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::ConstIterator + 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.merge (i->base_sub, name); + } + else + r.clear (); + + return true; + } + } + + return false; + } + + Void Context:: + write_annotation (SemanticGraph::Annotation& a) + { + String const& doc (a.documentation ()); + WideChar const* s (doc.c_str ()); + Size size (doc.size ()); + + // Remove leading and trailing whitespaces. + // + while (*s == WideChar (0x20) || *s == WideChar (0x0A) || + *s == WideChar (0x0D) || *s == WideChar (0x09)) + { + s++; + size--; + } + + if (size != 0) + { + WideChar const* e (s + size - 1); + + while (e > s && + (*e == WideChar (0x20) || *e == WideChar (0x0A) || + *e == WideChar (0x0D) || *e == WideChar (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. + // + WideChar const* last_space (0); + WideChar const* b (s); + WideChar const* e (s); + Boolean after_newline (false); + Boolean rogue (false); + + for (; e < s + size; ++e) + { + UnsignedLong 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 (WideChar const* s, Size size, Boolean rogue) + { + if (!rogue) + os.write (s, size); + else + { + for (WideChar const* p (s); p < s + size; ++p) + { + UnsignedLong 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<WideChar> (u)); + } + } + } + + Boolean Context:: + polymorphic_p (SemanticGraph::Type& t) + { + if (polymorphic_all) + { + Boolean fund (false); + IsFundamentalType test (fund); + test.dispatch (t); + return !fund; + } + else + return t.context ().get<Boolean> ("polymorphic"); + } + + // GenerateDefautCtor + // + GenerateDefaultCtor:: + GenerateDefaultCtor (Context& c, Boolean& generate, Boolean 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.value<CLI::generate_wildcard> () && + min (a) == 1 && max (a) == 1) + generate_ = true; + } + + + // GenerateFromBaseCtor + // + GenerateFromBaseCtor:: + GenerateFromBaseCtor (Context& c, Boolean& generate) + : generate_ (generate), + custom_ (false), + traverser_ (c, generate, custom_) + { + inherits_ >> traverser_; + } + + Void GenerateFromBaseCtor:: + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + + if (!generate_ && custom_) + { + // We have a customized type in the hierarchy. In this case we + // want to generate the c-tor unless base and ultimate-base are + // the same (see CtorArgs). + // + SemanticGraph::Type& b (c.inherits ().base ()); + generate_ = b.is_a<SemanticGraph::Complex> () && + !b.is_a<SemanticGraph::Enumeration> (); + } + } + + GenerateFromBaseCtor::Traverser:: + Traverser (Context& c, Boolean& generate, Boolean& custom) + : Context (c), generate_ (generate), custom_ (custom) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + Void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Type& t) + { + if (!custom_) + { + String tmp; + custom_ = custom_type (t, tmp); + } + } + + Void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Complex& c) + { + names (c, names_); + + if (!generate_) + inherits (c, inherits_); + + if (!generate_) + traverse (static_cast<SemanticGraph::Type&> (c)); + } + + Void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + generate_ = true; + } + + Void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Attribute& a) + { + if (min (a) == 1 && !a.fixed_p ()) + generate_ = true; + } + + Void GenerateFromBaseCtor::Traverser:: + traverse (SemanticGraph::Any& a) + { + if (options.value<CLI::generate_wildcard> () && + min (a) == 1 && max (a) == 1) + generate_ = true; + } + + // HasComplexNonOptArgs + // + HasComplexPolyNonOptArgs:: + HasComplexPolyNonOptArgs (Context& c, + Boolean base, + Boolean& complex, + Boolean& poly, + Boolean& 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) + { + Boolean poly (polymorphic && polymorphic_p (e.type ())); + + Boolean 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, ArgType at, Boolean arg) + : Context (c), arg_type_ (at), arg_ (arg) + { + } + + Void FromBaseCtorArg:: + traverse (SemanticGraph::Any& a) + { + if (!options.value<CLI::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; + + Boolean auto_ptr (false); + + switch (arg_type_) + { + case arg_complex_auto_ptr: + { + Boolean simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + auto_ptr = !simple; + break; + } + case arg_poly_auto_ptr: + { + auto_ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case arg_type: + break; + } + + if (auto_ptr) + os << "::std::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, ArgType at) + : Context (c), + arg_type_ (at), + base_arg_ (0), + first_ (true), + member_name_ (c) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + CtorArgs:: + CtorArgs (Context& c, ArgType 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) + { + *base_arg_ = L"_xsd_" + ename (t) + L"_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.value<CLI::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) + { + Boolean auto_ptr (false); + + switch (arg_type_) + { + case arg_complex_auto_ptr: + { + Boolean simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + auto_ptr = !simple; + break; + } + case arg_poly_auto_ptr: + { + auto_ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case arg_type: + break; + } + + if (auto_ptr) + os << comma () << "::std::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 () + { + Boolean tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + + // CtorArgsWithoutBase + // + CtorArgsWithoutBase:: + CtorArgsWithoutBase (Context& c, ArgType at, Boolean arg, Boolean first) + : Context (c), arg_type_ (at), arg_ (arg), first_ (first) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + Void CtorArgsWithoutBase:: + traverse (SemanticGraph::Any& a) + { + if (!options.value<CLI::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) + { + Boolean auto_ptr (false); + + switch (arg_type_) + { + case arg_complex_auto_ptr: + { + Boolean simple (true); + IsSimpleType t (simple); + t.dispatch (e.type ()); + auto_ptr = !simple; + break; + } + case arg_poly_auto_ptr: + { + auto_ptr = polymorphic && polymorphic_p (e.type ()); + break; + } + case arg_type: + break; + } + + if (auto_ptr) + os << comma () << "::std::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 () + { + Boolean tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + // GlobalElementBase + // + Boolean 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.value<CLI::generate_element_type> () && + ctx_.options.value<CLI::suppress_parsing> () && + !ctx_.options.value<CLI::generate_serialization> ()) + return false; + + return true; + } + + Boolean GlobalElementBase:: + doc_root_p (SemanticGraph::Element& e) + { + if (!ctx_.options.value<CLI::root_element_first> () && + !ctx_.options.value<CLI::root_element_last> () && + !ctx_.options.value<CLI::root_element_all> () && + !ctx_.options.value<CLI::root_element_none> () && + ctx_.options.value<CLI::root_element> ().empty ()) + return true; // By default treat them all. + + if (ctx_.options.value<CLI::root_element_none> ()) + return false; + + if (ctx_.options.value<CLI::root_element_all> ()) + return true; + + if (ctx_.options.value<CLI::root_element_first> () && + e.context ().count ("first") != 0) + return true; + + if (ctx_.options.value<CLI::root_element_last> () && + e.context ().count ("last") != 0) + return true; + + typedef Cult::Containers::Vector<NarrowString> Names; + Names const& names (ctx_.options.value<CLI::root_element> ()); + + // Hopefully nobody will specify more than a handful of names ;-). + // + for (Names::ConstIterator i (names.begin ()); i != names.end (); ++i) + { + String name (*i); + + if (e.name () == name) + return true; + } + + return false; + } + + // Namespace + // + Namespace:: + Namespace (Context& c, + UnsignedLong first, + UnsignedLong 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 + { + Boolean opened (false); + + for (Type::NamesIterator i (ns.names_begin ()); + i != ns.names_end (); ++i) + { + SemanticGraph::Nameable& n (i->named ()); + + if (n.is_a<SemanticGraph::Type> () || + (n.is_a<Element> () && generate_p (dynamic_cast<Element&> (n)))) + { + if (count_ >= first_ && count_ <= last_) + { + if (!opened) + { + opened = true; + pre (ns); + } + + edge_traverser ().dispatch (*i); + } + + ++count_; + } + } + + if (opened) + post (ns); + } + } + + Void Namespace:: + enter (Type&, String const& name, Boolean) + { + 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_); + Boolean 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) + return; + + SemanticGraph::Path path ( + s.context ().count ("renamed") + ? s.context ().get<SemanticGraph::Path> ("renamed") + : u.path ()); + + // 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.string (); + } + catch (SemanticGraph::InvalidPath const&) + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + path_str = path.native_file_string (); +#else + path_str = path.string (); +#endif + } + + String inc_path; + + switch (t) + { + case forward: + { + inc_path = ctx_.fwd_expr->merge (path_str); + break; + } + case header: + case source: + { + inc_path = ctx_.hxx_expr->merge (path_str); + break; + } + case inline_: + { + if (weak) + { + inc_path = ctx_.hxx_expr->merge (path_str); + ctx_.os << "#include " << ctx_.process_include_path (inc_path) + << endl; + } + + inc_path = ctx_.ixx_expr->merge (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..afe3951 --- /dev/null +++ b/xsd/xsd/cxx/tree/elements.hxx @@ -0,0 +1,2055 @@ +// file : xsd/cxx/tree/elements.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_ELEMENTS_HXX +#define CXX_TREE_ELEMENTS_HXX + +#include <sstream> + +#include <cult/containers/map.hxx> +#include <cult/containers/deque.hxx> +#include <cult/containers/vector.hxx> + +#include <backend-elements/regex.hxx> + +#include <cxx/elements.hxx> + +#include <cxx/tree/cli.hxx> + + +namespace CXX +{ + namespace Tree + { + struct Counts + { + Counts () + : global_types (0), + global_elements (0), + generated_global_elements (0), + complexity_total (0) + { + } + + UnsignedLong global_types; + UnsignedLong global_elements; + UnsignedLong generated_global_elements; + + // Complexity value for each global type and generated global + // element, in order. + // + Cult::Containers::Vector<UnsignedLong> complexity; + UnsignedLong 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_; + }; + + // + // + class Context: public CXX::Context + { + public: + typedef BackendElements::Regex::Expression<Char> Regex; + typedef BackendElements::Regex::Pattern<WideChar> WideRegexPat; + + 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 + Cult::Containers::Vector<RegexCustomTypeMapInfo> + RegexCustomTypeMap; + + typedef + Cult::Containers::Map<String, DirectCustomTypeMapInfo> + DirectCustomTypeMap; + + public: + Context (std::wostream& o, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + CLI::Options const& ops, + Counts const& counts_, + Boolean 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. + // + Boolean + 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. + // + Boolean + 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: + Boolean + polymorphic_p (SemanticGraph::Type&); + + Boolean + anonymous_p (SemanticGraph::Type const& t) + { + return t.context ().count ("anonymous"); + } + + // Escaped names. + // + public: + // Accessor name. + // + static String const& + eaname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("aname"); + } + + static String const& + eaname (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("aname"); + } + + static String const& + eaname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("aname"); + } + + // Modifier name. + // + static String const& + emname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("mname"); + } + + static String const& + emname (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("mname"); + } + + static String const& + emname (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("mname"); + } + + // Detach name. + // + static String const& + edname (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("dname"); + } + + // + // + static String const& + etype (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("type"); + } + + static String const& + etraits (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("traits"); + } + + static String const& + econtainer (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("container"); + } + + static String const& + econtainer (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("container"); + } + + static String const& + econtainer (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("container"); + } + + static String const& + eiterator (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("iterator"); + } + + static String const& + eiterator (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("iterator"); + } + + static String const& + eiterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("const-iterator"); + } + + static String const& + econst_iterator (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("const-iterator"); + } + + static String const& + emember (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("member"); + } + + static String const& + emember (SemanticGraph::Any const& a) + { + return a.context ().get<String> ("member"); + } + + static String const& + emember (SemanticGraph::AnyAttribute const& a) + { + return a.context ().get<String> ("member"); + } + + static String const& + edefault_value (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("default-value"); + } + + static String const& + edefault_value_member (SemanticGraph::Member const& m) + { + return m.context ().get<String> ("default-value-member"); + } + + // Underlying enum value type. + // + static String const& + evalue (SemanticGraph::Enumeration const& e) + { + return e.context ().get<String> ("value"); + } + + // dom_document + // + static Boolean + edom_document_p (SemanticGraph::Complex const& c) + { + return c.context ().count ("dom-document"); + } + + static String const& + edom_document (SemanticGraph::Complex const& c) + { + return c.context ().get<String> ("dom-document"); + } + + static Boolean + edom_document_member_p (SemanticGraph::Complex const& c) + { + return c.context ().count ("dom-document-member"); + } + + static String const& + edom_document_member (SemanticGraph::Complex const& c) + { + return c.context ().get<String> ("dom-document-member"); + } + + // Parsing and serialization function names. + // + static String const& + eparser (SemanticGraph::Element const& e) + { + return e.context ().get<String> ("parser"); + } + + static String const& + eserializer (SemanticGraph::Element const& e) + { + return e.context ().get<String> ("serializer"); + } + + public: + Void + enter_ns_scope (String const& name) + { + ns_scope_stack.push_back (name); + update_ns_scope (); + } + + Void + leave_ns_scope () + { + ns_scope_stack.pop_back (); + update_ns_scope (); + } + + private: + Void + update_ns_scope (); + + private: + // Write text that may contain characters that we will have + // to escape (indicated by the rogue flag). + // + Void + write_rogue_text (WideChar const* s, Size size, Boolean rogue); + + public: + CLI::Options 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; + + Boolean& generate_xml_schema; + Boolean& doxygen; + Boolean polymorphic; + Boolean polymorphic_all; + Boolean 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_; + + Boolean generate_xml_schema_; + Boolean doxygen_; + + typedef + Cult::Containers::Deque<String> + NamespaceStack; + + typedef + Cult::Containers::Deque<String> + ScopeStack; + + String ns_scope_; + + NamespaceStack& ns_scope_stack; + NamespaceStack ns_scope_stack_; + + RegexCustomTypeMap regex_custom_type_map_; + DirectCustomTypeMap direct_custom_type_map_; + + private: + WideRegexPat const cxx_uq_id_expr_; + WideRegexPat const& cxx_uq_id_expr; + }; + + // Check whether this Schema type maps to a fundamental C++ type. + // + struct IsFundamentalType: Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal + + { + IsFundamentalType (Boolean& 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: + Boolean& 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 (Boolean& 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: + Boolean& r_; + Traversal::Inherits inherits_; + }; + + + // Check whether this is a enumeration-based type. + // + struct IsEnumBasedType: Traversal::Complex + { + IsEnumBasedType (SemanticGraph::Enumeration*& e) + : enum_ (e) + { + *this >> inherits_; + + inherits_ >> *this; + inherits_ >> enum_; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + inherits (c, inherits_); + } + + private: + struct Enumeration: Traversal::Enumeration + { + Enumeration (SemanticGraph::Enumeration*& e) + : e_ (e) + { + } + + virtual Void + traverse (Type& e) + { + if (e_ == 0) + e_ = &e; + } + + private: + SemanticGraph::Enumeration*& e_; + }; + + + private: + Enumeration enum_; + Traversal::Inherits inherits_; + }; + + + // + // + struct MemberTypeName : Context, + Traversal::Type, + Traversal::List, + Traversal::Union, + Traversal::Complex, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + + { + MemberTypeName (Context& c) + : Context (c) + { + } + + MemberTypeName (Context& c, std::wostream& o) + : Context (c, o) + { + } + + virtual Void + traverse (SemanticGraph::Type&) + { + abort (); + } + + virtual Void + traverse (SemanticGraph::List& l) + { + os << fq_name (l); + } + + virtual Void + traverse (SemanticGraph::Union& u) + { + os << fq_name (u); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + os << fq_name (c); + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + os << fq_name (t); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + os << fq_name (t); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + os << fq_name (t); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + os << fq_name (t); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + os << fq_name (t); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + os << fq_name (t); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + if (t.named_p ()) + { + // IDREF<anyType> + // + os << fq_name (t); + } + else + { + SemanticGraph::Nameable& ncname ( + xs_ns ().find ("NCName").first->named ()); + + os << "::xsd::cxx::tree::idref< " << char_type << ", " << + fq_name (ncname) << ", " << + type_name (t.argumented ().type ()) << " >"; + } + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + if (t.named_p ()) + { + // IDREFS<anyType> + // + os << fq_name (t); + } + else + { + SemanticGraph::Nameable& ncname ( + xs_ns ().find ("NCName").first->named ()); + + os << "::xsd::cxx::tree::idrefs< " << char_type << ", " << + any_simple_type << ", ::xsd::cxx::tree::idref< " << + char_type << ", " << fq_name (ncname) << ", " << + type_name (t.argumented ().type ()) << " > >"; + } + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + os << fq_name (t); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + os << fq_name (t); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + os << fq_name (t); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + os << fq_name (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + os << fq_name (t); + } + + private: + // For idref/idrefs + // + String + type_name (SemanticGraph::Type& t) + { + // This type is always named. + // + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + // + // + struct BaseTypeName : MemberTypeName + { + BaseTypeName (Context& c) + : MemberTypeName (c) + { + } + + BaseTypeName (Context& c, std::wostream& o) + : MemberTypeName (c, o) + { + } + + virtual Void + fundamental_base (SemanticGraph::Type& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << " >"; + } + + // Integrals. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + fundamental_base (t); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + fundamental_base (t); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + fundamental_base (t); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << ", " << + "::xsd::cxx::tree::schema_type::double_ >"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + os << "::xsd::cxx::tree::fundamental_base< " << + fq_name (t) << ", " << char_type << ", " << + any_simple_type << ", " << + "::xsd::cxx::tree::schema_type::decimal >"; + } + }; + + // Initial value should be true. + // + struct IsSimpleType: Traversal::Complex, + Traversal::Member, + Traversal::Any, + Traversal::AnyAttribute + { + IsSimpleType (Boolean& v) + : v_ (v) + { + *this >> names_ >> *this; + *this >> inherits_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + 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: + Boolean& 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&, Boolean& generate, Boolean 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: + Boolean& generate_; + Boolean 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, Boolean& generate); + + virtual Void + traverse (SemanticGraph::Complex& c); + + private: + Boolean& generate_; + Boolean 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, Boolean& generate, Boolean& 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: + Boolean& generate_; + Boolean& 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, + Boolean including_base, + Boolean& complex, + Boolean& poly, + Boolean& clash); + + virtual Void + traverse (SemanticGraph::Complex&); + + virtual Void + traverse (SemanticGraph::Element&); + + private: + Boolean& complex_; + Boolean& poly_; + Boolean& clash_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // Immediate non-optional member. Note that AnyAttribute is always + // mapped to a sequence. + // + struct FromBaseCtorArg: Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + enum ArgType + { + arg_type, + arg_complex_auto_ptr, + arg_poly_auto_ptr + }; + + FromBaseCtorArg (Context& c, ArgType, Boolean arg); + + virtual Void + traverse (SemanticGraph::Any&); + + virtual Void + traverse (SemanticGraph::Attribute&); + + virtual Void + traverse (SemanticGraph::Element&); + + private: + ArgType arg_type_; + Boolean 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 + { + enum ArgType + { + arg_type, + arg_complex_auto_ptr, + arg_poly_auto_ptr + }; + + // The second version outputs the argument name and stores + // in in the base_arg string. + // + CtorArgs (Context&, ArgType); + CtorArgs (Context&, ArgType, 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: + ArgType arg_type_; + String base_; + String* base_arg_; + Boolean 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 (Boolean& 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: + Boolean& 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 + { + enum ArgType + { + arg_type, + arg_complex_auto_ptr, + arg_poly_auto_ptr + }; + + CtorArgsWithoutBase (Context& c, ArgType, Boolean arg, Boolean first); + + virtual Void + traverse (SemanticGraph::Any&); + + virtual Void + traverse (SemanticGraph::Element&); + + virtual Void + traverse (SemanticGraph::Attribute&); + + private: + String + comma (); + + private: + ArgType arg_type_; + Boolean arg_; + Boolean first_; + + private: + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // + // + struct GlobalElementBase + { + GlobalElementBase (Context& c) + : ctx_ (c) + { + } + + Boolean + generate_p (SemanticGraph::Element&); + + Boolean + doc_root_p (SemanticGraph::Element&); + + private: + Context& ctx_; + }; + + + // + // + struct Namespace: CXX::Namespace, + GlobalElementBase, + CXX::Namespace::ScopeTracker + { + Namespace (Context&, + UnsignedLong first = 1, + UnsignedLong last = 0); + + virtual Void + traverse (Type&); + + protected: + virtual Void + enter (Type&, String const& name, Boolean last); + + virtual Void + leave (); + + protected: + Context& ctx_; + + private: + UnsignedLong first_; + UnsignedLong last_; + UnsignedLong count_; + }; + + // + // + struct DocumentedNamespace: Namespace + { + DocumentedNamespace (Context& c) + : Namespace (c) + { + } + + virtual Void + enter (Type& ns, String const& name, Boolean 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.value<CLI::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_; + Boolean 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: + Boolean + gen_include (SemanticGraph::Type& t, String const& file) + { + String custom; + + // XML Schema built-in type customization is only possible when + // we are generating separate header. + // + if (generate_xml_schema && custom_type (t, custom)) + { + String new_name; + renamed_type (t, new_name); + + if (!new_name) + return false; + } + + os << "#include <xsd/cxx/tree/" << prefix_ << "/" << file << ">" + << endl; + + return true; + } + + private: + String prefix_; + Boolean long_; + Boolean unsigned_long_; + }; + } +} + +#endif // 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..71cfbea --- /dev/null +++ b/xsd/xsd/cxx/tree/fundamental-header.hxx @@ -0,0 +1,1320 @@ +// file : xsd/cxx/tree/fundamental-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_FUNDAMENTAL_HEADER_HXX +#define CXX_TREE_FUNDAMENTAL_HEADER_HXX + +#include <cult/containers/set.hxx> +#include <cult/containers/vector.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + struct FundamentalNamespace : DocumentedNamespace, + + Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities, + Context + { + FundamentalNamespace (Context& c) + : DocumentedNamespace (c), + Context (c), + export_ (c.options.value<CLI::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"", + Boolean 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< ", type_); + + if (doxygen) + os << "/**" << endl + << " * @brief Alias for the anyType type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("container"), + "::xsd::cxx::tree::type"); + + os << endl; + + if (doxygen) + os << endl; + } + + // Integrals. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + os << "// 8-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "signed char"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + built_in_type (t, "unsigned char"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + os << "// 16-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "short"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + built_in_type (t, "unsigned short"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + os << "// 32-bit" << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "int"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + built_in_type (t, "unsigned int"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + os << "// 64-bit" << endl + << "//" <<endl; + + if (doxygen) + os << endl; + + built_in_type (t, "long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + built_in_type (t, "unsigned long long"); + os << endl; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + os << "// Supposed to be arbitrary-length integral types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + built_in_type (t, "long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + built_in_type (t, "unsigned long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + built_in_type (t, "unsigned long long"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + built_in_type (t, "long long"); + os << endl; + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + os << "// Boolean." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "bool"); + + os << endl; + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + os << "// Floating-point types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type (t, "float"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + double_ = built_in_type (t, "double"); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + decimal_ = built_in_type (t, "double"); + os << endl; + } + + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + os << "// String types." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + string_ = built_in_type ( + t, L"::xsd::cxx::tree::string< " + char_type + L", ", simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + norm_string_ = built_in_type ( + t, + L"::xsd::cxx::tree::normalized_string< " + char_type + L", ", + string_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + token_ = built_in_type ( + t, L"::xsd::cxx::tree::token< " + char_type + L", ", norm_string_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + nmtoken_ = built_in_type ( + t, L"::xsd::cxx::tree::nmtoken< " + char_type + L", ", token_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::nmtokens< " + char_type + L", ", + simple_type_, + nmtoken_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + name_ = built_in_type ( + t, L"::xsd::cxx::tree::name< " + char_type + L", ", token_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + ncname_ = built_in_type ( + t, L"::xsd::cxx::tree::ncname< " + char_type + L", ", name_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::language< " + char_type + L", ", token_); + + os << endl; + } + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + os << "// ID/IDREF." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type ( + t, L"::xsd::cxx::tree::id< " + char_type + L", ", ncname_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + idref_ = built_in_type ( + t, L"::xsd::cxx::tree::idref< " + char_type + L", ", ncname_, type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::idrefs< " + char_type + L", ", + simple_type_, + idref_); + + os << endl; + } + + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + os << "// URI." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + uri_ = built_in_type ( + t, L"::xsd::cxx::tree::uri< " + char_type + L", ", simple_type_); + + os << endl; + } + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + os << "// Qualified name." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + built_in_type ( + t, + L"::xsd::cxx::tree::qname< " + char_type + L", ", + simple_type_, + uri_, + ncname_); + + os << endl; + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + os << "// Binary." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Binary buffer type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("buffer"), + L"::xsd::cxx::tree::buffer< " + char_type + L" >"); + + if (doxygen) + os << endl; + + built_in_type ( + t, + L"::xsd::cxx::tree::base64_binary< " + char_type + L", ", + simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::hex_binary< " + char_type + L", ", + simple_type_); + + os << endl; + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + os << "// Date/time." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Time zone type." << endl + << " */" << endl; + + gen_typedef (xs_ns ().context().get<String> ("time-zone"), + "::xsd::cxx::tree::time_zone"); + + if (doxygen) + os << endl; + + built_in_type ( + t, L"::xsd::cxx::tree::date< " + char_type + L", ", simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::date_time< " + char_type + L", ", + simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::duration< " + char_type + L", ", + simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gday< " + char_type + L", ", simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gmonth< " + char_type + L", ", simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::gmonth_day< " + char_type + L", ", + simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::gyear< " + char_type + L", ", simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::gyear_month< " + char_type + L", ", + simple_type_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + built_in_type ( + t, L"::xsd::cxx::tree::time< " + char_type + L", ", simple_type_); + + os << endl; + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + os << "// Entity." << endl + << "//" << endl; + + if (doxygen) + os << endl; + + entity_ = built_in_type ( + t, L"::xsd::cxx::tree::entity< " + char_type + L", ", ncname_); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + built_in_type ( + t, + L"::xsd::cxx::tree::entities< " + char_type + L", ", + simple_type_, + entity_); + + os << endl; + } + + virtual Void + post (SemanticGraph::Namespace& n) + { + SemanticGraph::Context& c (xs_ns ().context()); + + Boolean parsing (!options.value<CLI::suppress_parsing> ()); + Boolean serialization (options.value<CLI::generate_serialization> ()); + Boolean element_map (options.value<CLI::generate_element_map> ()); + + if (options.value<CLI::generate_element_type> ()) + { + if (doxygen) + os << "/**" << endl + << " * @brief Base class for element types." << endl + << " */" << endl; + else + os << "// Base class for element types." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("element-type"), + L"::xsd::cxx::tree::element_type< " + char_type + L", ", + type_); + + os << endl; + } + + if (element_map) + { + if (doxygen) + os << "/**" << endl + << " * @brief Root element map." << endl + << " */" << endl; + else + os << "// Root element map." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("element-map"), + L"::xsd::cxx::tree::element_map< " + char_type + L", ", + type_); + + os << endl; + } + + if (serialization) + { + os << "// Namespace information and list stream. Used in" << endl + << "// serialization functions." << endl + << "//" << endl; + + if (doxygen) + os << "/**" << endl + << " * @brief Namespace serialization information." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("namespace-info"), + L"::xsd::cxx::xml::dom::namespace_info< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Namespace serialization information map." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("namespace-infomap"), + L"::xsd::cxx::xml::dom::namespace_infomap< " + + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief List serialization stream." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("list-stream"), + L"::xsd::cxx::tree::list_stream< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Serialization wrapper for the %double type." << endl + << " */" << endl; + + // Do not export as_double and as_decimal since they are already + // instantiated. + // + gen_typedef (c.get<String> ("as-double"), + L"::xsd::cxx::tree::as_double< ", + double_, + "", + "", + false); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Serialization wrapper for the %decimal type." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("as-decimal"), + L"::xsd::cxx::tree::as_decimal< ", + decimal_, + "", + "", + false); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Simple type facet." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("facet"), "::xsd::cxx::tree::facet"); + + os << endl; + } + + //@@ Can't change names of ostream/istream since they are + // templates. + // + if (!options.value<CLI::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.value<CLI::generate_extraction> ().empty ()) + { + if (doxygen) + os << "/**" << endl + << " * @brief Data representation input stream template." << endl + << " */" << endl; + else + os << "// Data representation input stream template." << endl + << "//" << endl; + + os << "using ::xsd::cxx::tree::istream;" + << endl; + } + + os << "// Flags and properties." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Parsing and serialization flags." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("flags"), "::xsd::cxx::tree::flags"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Parsing properties." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("properties"), + L"::xsd::cxx::tree::properties< " + char_type + L" >"); + os << endl; + + + // + // + if (parsing || serialization) + { + os << "// Parsing/serialization diagnostics." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Error severity." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("severity"), + "::xsd::cxx::tree::severity"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Error condition." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("error"), + L"::xsd::cxx::tree::error< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief List of %error conditions." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("diagnostics"), + L"::xsd::cxx::tree::diagnostics< " + char_type + L" >"); + os << endl; + } + + // + // + os << "// Exceptions." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Root of the C++/Tree %exception hierarchy." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("exception"), + L"::xsd::cxx::tree::exception< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the size argument exceeds" << + endl + << " * the capacity argument." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("bounds"), + L"::xsd::cxx::tree::bounds< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that a duplicate ID value" << + endl + << " * was encountered in the object model." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("duplicate-id"), + L"::xsd::cxx::tree::duplicate_id< " + char_type + L" >"); + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating a parsing failure." << endl + << " */" << endl; + + gen_typedef (c.get<String> ("parsing"), + L"::xsd::cxx::tree::parsing< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an expected element" << + endl + << " * was not encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-element"), + L"::xsd::cxx::tree::expected_element< " + char_type + L" >"); + } + + if (parsing || serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an unexpected " << + "element" << endl + << " * was encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("unexpected-element"), + L"::xsd::cxx::tree::unexpected_element< " + char_type + L" >"); + } + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an expected " << + "attribute" << endl + << " * was not encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-attribute"), + L"::xsd::cxx::tree::expected_attribute< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that an unexpected " << + "enumerator" << endl + << " * was encountered." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("unexpected-enumerator"), + L"::xsd::cxx::tree::unexpected_enumerator< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the text content " << + "was" << endl + << " * expected for an element." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("expected-text-content"), + L"::xsd::cxx::tree::expected_text_content< " + char_type + L" >"); + + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that a prefix-namespace" << + endl + << " * mapping was not provided." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-prefix-mapping"), + L"::xsd::cxx::tree::no_prefix_mapping< " + char_type + L" >"); + } + + if (options.value<CLI::generate_polymorphic> ()) + { + if (parsing || serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the type " << + "information" << endl + << " * is not available for a type." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-type-info"), + L"::xsd::cxx::tree::no_type_info< " + char_type + L" >"); + } + + if (parsing) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that the types are not" << + endl + << " * related by inheritance." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("not-derived"), + L"::xsd::cxx::tree::not_derived< " + char_type + L" >"); + } + } + + if (element_map) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating that parsing or " << + "serialization" << endl + << " * information is not available for an element." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("no-element-info"), + L"::xsd::cxx::tree::no_element_info< " + char_type + L" >"); + } + + if (serialization) + { + if (doxygen) + os << endl + << "/**" << endl + << " * @brief Exception indicating a serialization " << + "failure." << endl + << " */" << endl; + + gen_typedef ( + c.get<String> ("serialization"), + L"::xsd::cxx::tree::serialization< " + char_type + L" >"); + } + + os << endl; + + if (parsing || serialization) + { + if (doxygen) + os << "/**" << endl + << " * @brief Error handler callback interface." << endl + << " */" << endl; + else + os << "// Error handler callback interface." << endl + << "//" << endl; + + gen_typedef ( + c.get<String> ("error-handler"), + L"::xsd::cxx::xml::error_handler< " + char_type + L" >"); + + os << endl; + } + + if (parsing || serialization) + { + if (doxygen) + os << "/**" << endl + << " * @brief DOM interaction." << endl + << " */" << endl; + else + os << "// DOM interaction." << endl + << "//" << endl; + + os << "namespace dom" + << "{"; + + // @@ Disregarding current naming convention by using the + // fixed name (no template typedef). + // + if (doxygen) + os << "/**" << endl + << " * @brief Automatic pointer for DOMDocument." << endl + << " */" << endl; + else + os << "// Automatic pointer for DOMDocument." << endl + << "//" << endl; + + os << "using ::xsd::cxx::xml::dom::auto_ptr;" + << endl; + + if (parsing) + { + if (!generate_xml_schema) + { + String g (L"XSD_CXX_TREE_TREE_NODE_KEY" + ns_name (n)); + + std::transform (g.begin (), g.end(), g.begin (), upcase); + g = escape (g); // Make it a C++ id. + + os << "#ifndef " << g << endl + << "#define " << g << endl; + } + + if (doxygen) + os << "/**" << endl + << " * @brief DOM user data key for back pointers to " << + "tree nodes." << endl + << " */" << endl; + else + os << "// DOM user data key for back pointers to tree nodes." << endl + << "//" << endl; + + os << "const XMLCh* const " << c.get<String> ("tree-node-key") << + " = ::xsd::cxx::tree::user_data_keys::node;"; + + if (!generate_xml_schema) + os << "#endif" << endl; + } + + os << "}"; // namespace dom + } + + if (element_map) + { + if (doxygen) + os << "//@cond" << endl + << endl; + + if (!generate_xml_schema) + { + String g (L"XSD_CXX_TREE_ELEMENT_MAP_INIT" + ns_name (n)); + + std::transform (g.begin (), g.end(), g.begin (), upcase); + g = escape (g); // Make it a C++ id. + + os << "#ifndef " << g << endl + << "#define " << g << endl; + } + + os << "static" << endl + << "const ::xsd::cxx::tree::element_map_init< " << + char_type << ", " << type_ << " >" << endl + << "_xsd_element_map_init;"; + + if (!generate_xml_schema) + os << "#endif" << endl; + + if (doxygen) + os << endl + << "//@endcond" << endl; + } + + Namespace::post (n); + + // Generate exports. + // + if (export_) + { + StringSet ns_set; + + for (StringList::ConstIterator 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::ConstIterator i (ns_set.begin ()); + i != ns_set.end (); ++i) + { + String const& ns (*i); + String prefix (L"::xsd::cxx::" + ns); + + Size n (1); + for (Size 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::ConstIterator 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 Cult::Containers::Set<String> StringSet; + typedef Cult::Containers::Vector<String> StringList; + + Boolean 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 // 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..fe5286a --- /dev/null +++ b/xsd/xsd/cxx/tree/generator.cxx @@ -0,0 +1,1842 @@ +// file : xsd/cxx/tree/generator.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/generator.hxx> + +#include <cxx/tree/elements.hxx> + +#include <cxx/tree/counter.hxx> +#include <cxx/tree/validator.hxx> +#include <cxx/tree/name-processor.hxx> +#include <cxx/tree/polymorphism-processor.hxx> + +#include <cxx/tree/tree-forward.hxx> +#include <cxx/tree/tree-header.hxx> +#include <cxx/tree/tree-inline.hxx> +#include <cxx/tree/tree-source.hxx> + +#include <cxx/tree/parser-header.hxx> +#include <cxx/tree/parser-source.hxx> + +#include <cxx/tree/stream-header.hxx> +#include <cxx/tree/stream-source.hxx> + +#include <cxx/tree/serialization-header.hxx> +#include <cxx/tree/serialization-source.hxx> + +#include <cxx/tree/stream-insertion-header.hxx> +#include <cxx/tree/stream-insertion-source.hxx> +#include <cxx/tree/stream-extraction-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> + +#include <backend-elements/regex.hxx> +#include <backend-elements/indentation/cxx.hxx> +#include <backend-elements/indentation/sloc.hxx> +#include <backend-elements/indentation/clip.hxx> + +#include <cult/containers/set.hxx> +#include <cult/containers/vector.hxx> + +#include <boost/filesystem/fstream.hpp> + +#include <iostream> + +#include <usage.hxx> + +#include "../../../libxsd/xsd/cxx/version.hxx" + +using std::endl; +using std::wcerr; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef +boost::filesystem::wifstream +WideInputFileStream; + +typedef +boost::filesystem::wofstream +WideOutputFileStream; + +namespace CXX +{ + namespace + { + Char const copyright_gpl[] = + "// Copyright (C) 2005-2010 Code Synthesis Tools CC\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) 2005-2010 Code Synthesis Tools CC\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"; + } + + namespace Tree + { + namespace CLI + { + extern Key char_type = "char-type"; + extern Key char_encoding = "char-encoding"; + extern Key output_dir = "output-dir"; + extern Key generate_polymorphic = "generate-polymorphic"; + extern Key polymorphic_type = "polymorphic-type"; + extern Key polymorphic_type_all = "polymorphic-type-all"; + extern Key generate_serialization = "generate-serialization"; + extern Key generate_inline = "generate-inline"; + extern Key generate_ostream = "generate-ostream"; + extern Key generate_doxygen = "generate-doxygen"; + extern Key generate_comparison = "generate-comparison"; + extern Key generate_default_ctor = "generate-default-ctor"; + extern Key generate_from_base_ctor = "generate-from-base-ctor"; + extern Key generate_detach = "generate-detach"; + extern Key generate_wildcard = "generate-wildcard"; + extern Key generate_insertion = "generate-insertion"; + extern Key generate_extraction = "generate-extraction"; + extern Key generate_forward = "generate-forward"; + extern Key generate_xml_schema = "generate-xml-schema"; + extern Key extern_xml_schema = "extern-xml-schema"; + extern Key suppress_parsing = "suppress-parsing"; + extern Key generate_element_type = "generate-element-type"; + extern Key generate_element_map = "generate-element-map"; + extern Key generate_intellisense = "generate-intellisense"; + extern Key omit_default_attributes = "omit-default-attributes"; + extern Key namespace_map = "namespace-map"; + extern Key namespace_regex = "namespace-regex"; + extern Key namespace_regex_trace = "namespace-regex-trace"; + extern Key reserved_name = "reserved-name"; + extern Key type_naming = "type-naming"; + extern Key function_naming = "function-naming"; + extern Key type_regex = "type-regex"; + extern Key accessor_regex = "accessor-regex"; + extern Key one_accessor_regex = "one-accessor-regex"; + extern Key opt_accessor_regex = "opt-accessor-regex"; + extern Key seq_accessor_regex = "seq-accessor-regex"; + extern Key modifier_regex = "modifier-regex"; + extern Key one_modifier_regex = "one-modifier-regex"; + extern Key opt_modifier_regex = "opt-modifier-regex"; + extern Key seq_modifier_regex = "seq-modifier-regex"; + extern Key parser_regex = "parser-regex"; + extern Key serializer_regex = "serializer-regex"; + extern Key enumerator_regex = "enumerator-regex"; + extern Key element_type_regex = "element-type-regex"; + extern Key name_regex_trace = "name-regex-trace"; + extern Key include_with_brackets = "include-with-brackets"; + extern Key include_prefix = "include-prefix"; + extern Key include_regex = "include-regex"; + extern Key include_regex_trace = "include-regex-trace"; + extern Key guard_prefix = "guard-prefix"; + extern Key root_element_first = "root-element-first"; + extern Key root_element_last = "root-element-last"; + extern Key root_element_all = "root-element-all"; + extern Key root_element_none = "root-element-none"; + extern Key root_element = "root-element"; + extern Key custom_type = "custom-type"; + extern Key custom_type_regex = "custom-type-regex"; + extern Key hxx_suffix = "hxx-suffix"; + extern Key ixx_suffix = "ixx-suffix"; + extern Key cxx_suffix = "cxx-suffix"; + extern Key fwd_suffix = "fwd-suffix"; + extern Key hxx_regex = "hxx-regex"; + extern Key ixx_regex = "ixx-regex"; + extern Key cxx_regex = "cxx-regex"; + extern Key fwd_regex = "fwd-regex"; + extern Key hxx_prologue = "hxx-prologue"; + extern Key ixx_prologue = "ixx-prologue"; + extern Key cxx_prologue = "cxx-prologue"; + extern Key fwd_prologue = "fwd-prologue"; + extern Key prologue = "prologue"; + extern Key hxx_epilogue = "hxx-epilogue"; + extern Key ixx_epilogue = "ixx-epilogue"; + extern Key cxx_epilogue = "cxx-epilogue"; + extern Key fwd_epilogue = "fwd-epilogue"; + extern Key epilogue = "epilogue"; + extern Key hxx_prologue_file = "hxx-prologue-file"; + extern Key ixx_prologue_file = "ixx-prologue-file"; + extern Key cxx_prologue_file = "cxx-prologue-file"; + extern Key fwd_prologue_file = "fwd-prologue-file"; + extern Key prologue_file = "prologue-file"; + extern Key hxx_epilogue_file = "hxx-epilogue-file"; + extern Key ixx_epilogue_file = "ixx-epilogue-file"; + extern Key cxx_epilogue_file = "cxx-epilogue-file"; + extern Key fwd_epilogue_file = "fwd-epilogue-file"; + extern Key epilogue_file = "epilogue-file"; + extern Key parts = "parts"; + extern Key parts_suffix = "parts-suffix"; + extern Key export_symbol = "export-symbol"; + extern Key export_xml_schema = "export-xml-schema"; + extern Key export_maps = "export-maps"; + extern Key import_maps = "import-maps"; + extern Key show_anonymous = "show-anonymous"; + extern Key show_sloc = "show-sloc"; + extern Key proprietary_license = "proprietary-license"; + extern Key disable_multi_import = "disable-multi-import"; + } + } + + Void Tree::Generator:: + usage () + { + std::wostream& e (wcerr); + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + e << "--char-type <type>" << endl + << " Use <type> as the base character type. Valid\n" + << " values are 'char' (default) and 'wchar_t'." + << endl; + + e << "--char-encoding <enc>" << endl + << " Specify the character encoding that should be used\n" + << " in the object model. Valid values for the 'char'\n" + << " character type are 'utf8' (default), 'iso8859-1',\n" + << " 'lcp', and 'custom'. For the 'wchar_t' character\n" + << " type the only valid value is 'auto'." + << endl; + + e << "--output-dir <dir>" << endl + << " Write generated files to <dir> instead of current\n" + << " directory." + << endl; + + e << "--generate-polymorphic" << endl + << " Generate polymorphism-aware code. Specify this\n" + << " option if you use substitution groups or xsi:type." + << endl; + + e << "--polymorphic-type <type>" << endl + << " Indicate that <type> is a root of a polymorphic\n" + << " type hierarchy." + << endl; + + e << "--polymorphic-type-all" << endl + << " Indicate that all types should be treated as\n" + << " polymorphic." + << endl; + + e << "--generate-serialization" << endl + << " Generate serialization functions. They convert an\n" + << " in-memory representation back to XML." + << endl; + + e << "--generate-inline" << endl + << " Generate certain functions inline." + << endl; + + e << "--generate-ostream" << endl + << " Generate ostream insertion operators." + << endl; + + e << "--generate-doxygen" << endl + << " Generate documentation comments in the Doxygen\n" + << " format." + << endl; + + e << "--generate-comparison" << endl + << " Generate comparison operators." + << endl; + + e << "--generate-default-ctor" << endl + << " Generate default constructors even for types that\n" + << " have required members." + << endl; + + e << "--generate-from-base-ctor" << endl + << " Generate from-base constructors." + << endl; + + e << "--generate-detach" << endl + << " Generate detach functions for required members." + << endl; + + e << "--generate-wildcard" << endl + << " Generate accessors/modifiers as well as parsing\n" + << " and serialization code for XML Schema wildcards." + << endl; + + e << "--generate-insertion <os>" << endl + << " Generate data representation stream insertion\n" + << " operators for the <os> output stream type." + << endl; + + e << "--generate-extraction <is>" << endl + << " Generate data representation stream extraction\n" + << " constructors for the <is> input stream type." + << endl; + + e << "--generate-forward" << endl + << " Generate forward declaration file." + << endl; + + e << "--generate-xml-schema" << endl + << " Generate a C++ header file as if the schema being\n" + << " compiled defines the XML Schema namespace." + << endl; + + e << "--extern-xml-schema <file>" << endl + << " Generate code as if the XML Schema namespace was\n" + << " defined in <file> and xsd:included in the schema\n" + << " being compiled." + << endl; + + e << "--suppress-parsing" << endl + << " Suppress the generation of parsing functions." + << endl; + + e << "--generate-element-type" << endl + << " Generate types instead of parsing/serialization\n" + << " functions for root elements." + << endl; + + e << "--generate-element-map" << endl + << " Generate a root element map that allows uniform\n" + << " parsing/serialization of multiple root elements.\n" + << endl; + + e << "--generate-intellisense" << endl + << " Generate workarounds for IntelliSense bugs in\n" + << " Visual Studio 2005 (8.0)." + << endl; + + e << "--omit-default-attributes" << endl + << " Omit attributes with default and fixed values\n" + << " from serialized XML documents." + << endl; + + e << "--namespace-map <xns>=<cns>" << endl + << " Map XML Schema namespace <xns> to C++ namespace\n" + << " <cns>. Repeat this option to specify mapping for\n" + << " more than one XML Schema namespace." + << endl; + + e << "--namespace-regex <regex>" << endl + << " Add <regex> to the list of regular expressions\n" + << " used to translate XML Schema namespace names to\n" + << " C++ namespace names." + << endl; + + e << "--namespace-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --namespace-regex option." + << endl; + + e << "--reserved-name <name>" << endl + << " Add <name> to the list of names that should not\n" + << " be used as identifiers. The name can optionally\n" + << " be followed by '=' and the replacement name that\n" + << " should be used instead." + << endl; + + e << "--type-naming <style>" << endl + << " Specify the type naming convention that should be\n" + << " used in the generated code. Valid styles are 'knr'\n" + << " (default), 'ucc', and 'java'." + << endl; + + e << "--function-naming <style>" << endl + << " Specify the function naming convention that should\n" + << " be used in the generated code. Valid styles are\n" + << " 'knr' (default), 'lcc', and 'java'." + << endl; + + e << "--type-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema type names to C++\n" + << " type names." + << endl; + + e << "--accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements and\n" + << " attributes to C++ accessor function names." + << endl; + + e << "--one-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality one to C++\n" + << " accessor function names." + << endl; + + e << "--opt-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality optional to C++\n" + << " accessor function names." + << endl; + + e << "--seq-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality sequence to C++\n" + << " accessor function names." + << endl; + + e << "--modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements and\n" + << " attributes to C++ modifier function names." + << endl; + + e << "--one-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality one to C++\n" + << " modifier function names." + << endl; + + e << "--opt-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality optional to C++\n" + << " modifier function names." + << endl; + + e << "--seq-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality sequence to C++\n" + << " modifier function names." + << endl; + + e << "--parser-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ parsing function names." + << endl; + + e << "--serializer-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ serialization function names." + << endl; + + e << "--enumerator-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema enumeration values\n" + << " to C++ enumerator names." + << endl; + + e << "--element-type-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ element type names." + << endl; + + e << "--name-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the name transformation options." + << endl; + + e << "--include-with-brackets" << endl + << " Use angle brackets (<>) instead of quotes (\"\") in\n" + << " generated #include directives." + << endl; + + e << "--include-prefix <prefix>" << endl + << " Add <prefix> to generated #include directive\n" + << " paths." + << endl; + + e << "--include-regex <regex>" << endl + << " Add <regex> to the list of regular expressions\n" + << " used to transform #include directive paths." + << endl; + + e << "--include-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the --include-regex option." + << endl; + + e << "--guard-prefix <prefix>" << endl + << " Add <prefix> to generated header inclusion guards." + << endl; + + e << "--root-element-first" << endl + << " Treat only the first global element as a document\n" + << " root." + << endl; + + e << "--root-element-last" << endl + << " Treat only the last global element as a document\n" + << " root." + << endl; + + e << "--root-element-all" << endl + << " Treat all global elements as document roots." + << endl; + + e << "--root-element-none" << endl + << " Don't treat any global elements as document roots." + << endl; + + e << "--root-element <element>" << endl + << " Treat only <element> as a document root. Repeat\n" + << " this option to specify more than one root element." + << endl; + + e << "--custom-type <map>" << endl + << " Use a custom C++ type instead of the generated\n" + << " class. The <map> argument is in the form\n" + << " name[=type[/base]], where <name> is a type name as\n" + << " defined in XML Schema, <type> is a C++ type name\n" + << " that should be used instead, and optional <base>\n" + << " is a C++ name that should be given to the C++\n" + << " class generated from the XML Schema definition\n" + << " which is normally used as a base for the custom\n" + << " type." + << endl; + + e << "--custom-type-regex <regex>" << endl + << " Use custom C++ types instead of the generated\n" + << " classes. The <regex> argument is in the form\n" + << " /name/[type/[base/]], where <name> is a regex\n" + << " pattern that will be matched against type names\n" + << " as defined in XML Schema, <type> is a C++ type\n" + << " name that should be used instead, and optional\n" + << " <base> is a C++ name that should be given to\n" + << " the C++ class generated from the XML Schema\n" + << " definition." + << endl; + + e << "--hxx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.hxx' to\n" + << " construct the name of the header file." + << endl; + + e << "--ixx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.ixx' to\n" + << " construct the name of the inline file." + << endl; + + e << "--cxx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.cxx' to\n" + << " construct the name of the source file." + << endl; + + e << "--fwd-suffix <suffix>" << endl + << " Use <suffix> instead of the default '-fwd.hxx'\n" + << " to construct the name of the forward declaration\n" + << " file." + << endl; + + e << "--hxx-regex <regex>" << endl + << " Use <regex> to construct the name of the header\n" + << " file." + << endl; + + e << "--ixx-regex <regex>" << endl + << " Use <regex> to construct the name of the inline\n" + << " file." + << endl; + + e << "--cxx-regex <regex>" << endl + << " Use <regex> to construct the name of the source\n" + << " file." + << endl; + + e << "--fwd-regex <regex>" << endl + << " Use <regex> to construct the name of the forward\n" + << " declaration file." + << endl; + + // Prologues. + // + e << "--hxx-prologue <text>" << endl + << " Insert <text> at the beginning of the header file." + << endl; + + e << "--ixx-prologue <text>" << endl + << " Insert <text> at the beginning of the inline file." + << endl; + + e << "--cxx-prologue <text>" << endl + << " Insert <text> at the beginning of the source file." + << endl; + + e << "--fwd-prologue <text>" << endl + << " Insert <text> at the beginning of the forward\n" + << " declaration file." + << endl; + + e << "--prologue <text>" << endl + << " Insert <text> at the beginning of each generated\n" + << " file for which there is no file-specific prologue." + << endl; + + + // Epilogues. + // + e << "--hxx-epilogue <text>" << endl + << " Insert <text> at the end of the header file." + << endl; + + e << "--ixx-epilogue <text>" << endl + << " Insert <text> at the end of the inline file." + << endl; + + e << "--cxx-epilogue <text>" << endl + << " Insert <text> at the end of the source file." + << endl; + + e << "--fwd-epilogue <text>" << endl + << " Insert <text> at the end of the forward\n" + << " declaration file." + << endl; + + e << "--epilogue <text>" << endl + << " Insert <text> at the end of each generated file\n" + << " for which there is no file-specific epilogue." + << endl; + + + // Prologue files. + // + e << "--hxx-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the header file." + << endl; + + e << "--ixx-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the inline file." + << endl; + + e << "--cxx-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the source file." + << endl; + + e << "--fwd-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the forward declaration file." + << endl; + + e << "--prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of each generated file for which there is no file-\n" + << " specific prologue file." + << endl; + + // Epilogue files. + // + e << "--hxx-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the header file." + << endl; + + e << "--ixx-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the inline file." + << endl; + + e << "--cxx-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the source file." + << endl; + + e << "--fwd-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the forward declaration file." + << endl; + + e << "--epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " each generated file for which there is no file-\n" + << " specific epilogue file." + << endl; + + // Misc. + // + e << "--parts <num>" << endl + << " Split generated source code into <num> parts." + << endl; + + e << "--parts-suffix <suffix>" << endl + << " Use <suffix> instead of the default '-' to\n" + << " separate the file name from the part number." + << endl; + + e << "--custom-literals <file>" << endl + << " Load custom XML string to C++ literal mappings\n" + << " from <file>." + << endl; + + e << "--export-symbol <symbol>" << endl + << " Export symbol for Win32 DLL export/import control." + << endl; + + e << "--export-xml-schema" << endl + << " Export/import types in the XML Schema namespace." + << endl; + + e << "--export-maps" << endl + << " Export polymorphism support maps from Win32 DLL." + << endl; + + e << "--import-maps" << endl + << " Import polymorphism support maps from Win32 DLL." + << endl; + + e << "--show-anonymous" << endl + << " Show elements and attributes that are of anonymous\n" + << " types." + << endl; + + e << "--show-sloc" << endl + << " Show the number of generated physical source lines\n" + << " of code (SLOC)." + << endl; + + e << "--sloc-limit <num>" << endl + << " Check that the number of generated physical source\n" + << " lines of code (SLOC) does not exceed <num>." + << endl; + + e << "--options-file <file>" << endl + << " Read additional options from <file>. Each option\n" + << " should appear on a separate line optionally\n" + << " followed by space and an argument." + << endl; + + e << "--proprietary-license" << endl + << " Indicate that the generated code is licensed under\n" + << " a proprietary license instead of the GPL." + << endl; + } + + Tree::CLI::OptionsSpec Tree::Generator:: + options_spec () + { + CLI::OptionsSpec spec; + + spec.option<CLI::char_type> ().default_value ("char"); + + spec.option<CLI::hxx_suffix> ().default_value (".hxx"); + spec.option<CLI::ixx_suffix> ().default_value (".ixx"); + spec.option<CLI::cxx_suffix> ().default_value (".cxx"); + spec.option<CLI::fwd_suffix> ().default_value ("-fwd.hxx"); + + spec.option<CLI::type_naming> ().default_value ("knr"); + spec.option<CLI::function_naming> ().default_value ("knr"); + + spec.option<CLI::parts> ().default_value (1); + spec.option<CLI::parts_suffix> ().default_value ("-"); + + return spec; + } + + + namespace + { + Void + open (WideInputFileStream& ifs, NarrowString const& path) + { + try + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path fs_path (path, boost::filesystem::native); +#else + Path fs_path (path.c_str()); +#endif + ifs.open (fs_path, 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, + Cult::Containers::Vector<NarrowString> const& primary, + Cult::Containers::Vector<NarrowString> const& def) + { + Cult::Containers::Vector<NarrowString> const& v ( + primary.empty () ? def : primary); + + for (Containers::Vector<NarrowString>::ConstIterator + i (v.begin ()), e (v.end ()); i != e; ++i) + { + os << i->c_str () << endl; + } + } + } + + + UnsignedLong Tree::Generator:: + generate (Tree::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + Boolean fpt, + StringLiteralMap const& string_literal_map, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression<Char> Regex; + + using Cult::Containers::Vector; + + typedef Vector<Path> Paths; + typedef Vector<Evptr<WideOutputFileStream> > WideOutputFileStreams; + + try + { + // Do option validation. + // + if (ops.value<CLI::parts> () < 1) + { + wcerr << "error: invalid value for option --parts: " << + ops.value<CLI::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 (); + } + + // Process names. + // + { + NameProcessor proc; + if (!proc.process (ops, schema, file_path, string_literal_map)) + throw Failed (); + } + + // Process polymorphic types. + // + if (ops.value<CLI::generate_polymorphic> () && + !ops.value<CLI::polymorphic_type_all> ()) + { + PolymorphismProcessor proc; + if (!proc.process (ops, schema, file_path, disabled_warnings)) + throw Failed (); + } + + // Parts. + // + UnsignedLong parts (ops.value<CLI::parts> ()); + UnsignedLong units ( + counts.global_types + counts.generated_global_elements); + + UnsignedLong units_per_part (units / parts); + + if (parts != 1 && units_per_part < 1) + { + wcerr << "error: too many parts specified: " << parts << endl; + throw Failed (); + } + + UnsignedLong complexity_per_part (counts.complexity_total / parts); + + + NarrowString parts_suffix (ops.value<CLI::parts_suffix> ()); + + // + // + Boolean generate_xml_schema (ops.value<CLI::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.value<CLI::extern_xml_schema> ()) + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + if (file_path.native_file_string () != name) +#else + if (file_path.string () != name) +#endif + generate_xml_schema = false; + } + } + + Boolean inline_ (ops.value<CLI::generate_inline> () && + !generate_xml_schema); + + Boolean forward (ops.value<CLI::generate_forward> () && + !generate_xml_schema); + + Boolean source (!generate_xml_schema); + + // Generate code. + // +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + NarrowString name (file_path.leaf ()); +#else + NarrowString name (file_path.filename ().string()); +#endif + + NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ()); + NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ()); + NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ()); + NarrowString fwd_suffix (ops.value <CLI::fwd_suffix> ()); + + Regex hxx_expr (ops.value <CLI::hxx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" + : ops.value <CLI::hxx_regex> ()); + + Regex ixx_expr (ops.value <CLI::ixx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#" + : ops.value <CLI::ixx_regex> ()); + + Regex cxx_expr (ops.value <CLI::cxx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#" + : ops.value <CLI::cxx_regex> ()); + + Regex fwd_expr (ops.value <CLI::fwd_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#" + : ops.value <CLI::fwd_regex> ()); + + if (!hxx_expr.match (name)) + { + wcerr << "error: header expression '" << + hxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (inline_ && !ixx_expr.match (name)) + { + wcerr << "error: inline expression '" << + ixx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (source && parts == 1 && !cxx_expr.match (name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + if (forward && !fwd_expr.match (name)) + { + wcerr << "error: forward expression '" << + fwd_expr.pattern () << "' does not match '" << + name.c_str () << "'" << endl; + throw Failed (); + } + + NarrowString hxx_name (hxx_expr.merge (name)); + NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ()); + NarrowString fwd_name (forward ? fwd_expr.merge (name) : NarrowString ()); + +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path hxx_path (hxx_name, boost::filesystem::native); + Path ixx_path (ixx_name, boost::filesystem::native); + Path fwd_path (fwd_name, boost::filesystem::native); +#else + Path hxx_path (hxx_name.c_str()); + Path ixx_path (ixx_name.c_str()); + Path fwd_path (fwd_name.c_str()); +#endif + Paths cxx_paths; + + if (source) + { + if (parts > 1) + { + for (UnsignedLong i (0); i < parts; ++i) + { + std::ostringstream os; + os << i; + + Regex expr ( + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + parts_suffix + os.str () + "$2#"); + + NarrowString part_name (expr.merge (name)); + + if (!cxx_expr.match (part_name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + part_name.c_str () << "'" << endl; + throw Failed (); + } + + cxx_paths.push_back ( +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path (cxx_expr.merge (part_name), boost::filesystem::native)); +#else + Path (cxx_expr.merge (part_name).c_str())); +#endif + } + } + else + cxx_paths.push_back ( +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path (cxx_expr.merge (name), boost::filesystem::native)); +#else + Path (cxx_expr.merge (name).c_str())); +#endif + } + + Path out_dir; + + if (NarrowString dir = ops.value<CLI::output_dir> ()) + { + try + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + out_dir = Path (dir, boost::filesystem::native); +#else + out_dir = Path (dir.c_str()); +#endif + } + 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.branch_path ()); + + 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; + + for (Paths::Iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + *i = out_dir / *i; + } + + // + // + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream ixx; + WideOutputFileStream fwd; + WideOutputFileStreams cxx; + + + // FWD + // + if (forward) + { + fwd.open (fwd_path, ios_base::out); + + if (!fwd.is_open ()) + { + wcerr << fwd_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (fwd_path); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (fwd_path.native_file_string ()); +#else + file_list.push_back (fwd_path.string ()); +#endif + } + + + // HXX + // + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (hxx_path.native_file_string ()); +#else + file_list.push_back (hxx_path.string ()); +#endif + + + // IXX + // + if (inline_) + { + ixx.open (ixx_path, ios_base::out); + + if (!ixx.is_open ()) + { + wcerr << ixx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (ixx_path); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (ixx_path.native_file_string ()); +#else + file_list.push_back (ixx_path.string ()); +#endif + } + + + // CXX + // + if (source) + { + for (Paths::Iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + { + Evptr<WideOutputFileStream> s ( + new WideOutputFileStream (*i, ios_base::out)); + + if (!s->is_open ()) + { + wcerr << *i << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (*i); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (i->native_file_string ()); +#else + file_list.push_back (i->string ()); +#endif + cxx.push_back (s); + } + } + + + // Print copyright and license. + // + Char const* copyright ( + ops.value<CLI::proprietary_license> () + ? copyright_proprietary + : copyright_gpl); + + if (forward) + fwd << copyright; + + hxx << copyright; + + if (ops.value<CLI::generate_doxygen> ()) + { + // Use native path format. + // + hxx << "/**" << endl + << " * @file" << endl + << " * @brief Generated from " << name.c_str () << "." << endl + << " */" << endl + << endl; + + } + + if (inline_) + ixx << copyright; + + if (source) + { + for (WideOutputFileStreams::Iterator i (cxx.begin ()); + i != cxx.end (); ++i) + **i << copyright; + } + + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name (ops.value<CLI::prologue_file> ()); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name (ops.value<CLI::epilogue_file> ()); + + if (name) + open (epilogue, name); + } + + // SLOC counter. + // + UnsignedLong sloc (0); + Boolean show_sloc (ops.value<CLI::show_sloc> ()); + + // + // + Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words. + NarrowString guard_prefix (ops.value<CLI::guard_prefix> ()); + + if (!guard_prefix) +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + guard_prefix = file_path.branch_path ().native_directory_string (); +#else + guard_prefix = file_path.branch_path ().string (); +#endif + + if (guard_prefix) + guard_prefix += '_'; + + // FWD + // + if (forward) + { + Context ctx (fwd, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> fwd_sloc (fwd); + + // Guard + // + String guard (guard_expr.merge (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; + + // Copy prologue. + // + fwd << "// Begin prologue." << endl + << "//" << endl; + + append (fwd, + ops.value<CLI::fwd_prologue> (), + ops.value<CLI::prologue> ()); + append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue); + + fwd << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + fwd << "#include <xsd/cxx/version.hxx>" << endl + << endl + << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + + << endl; + { + fwd << "#include <xsd/cxx/pre.hxx>" << 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; + } + + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd); + + + // Generate. + // + generate_forward (ctx); + + fwd << "#include <xsd/cxx/post.hxx>" << endl + << endl; + } + + // Copy epilogue. + // + fwd << "// Begin epilogue." << endl + << "//" << endl; + + append (fwd, ops.value<CLI::fwd_epilogue_file> (), epilogue); + append (fwd, + ops.value<CLI::fwd_epilogue> (), + ops.value<CLI::epilogue> ()); + + fwd << "//" << endl + << "// End epilogue." << endl + << endl; + + fwd << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << fwd_path << ": " + << fwd_sloc.buffer ().count () << endl; + + sloc += fwd_sloc.buffer ().count (); + } + } + + // HXX + // + { + Context ctx (hxx, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx); + + // Guard + // + String guard (guard_expr.merge (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; + + // Copy prologue. + // + hxx << "// Begin prologue." << endl + << "//" << endl; + + append ( + hxx, ops.value<CLI::hxx_prologue> (), ops.value<CLI::prologue> ()); + append (hxx, ops.value<CLI::hxx_prologue_file> (), prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + hxx << "#include <xsd/cxx/config.hxx>" << endl + << endl + << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + { + hxx << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Generate character selection defines. + // + if (!forward) + { + 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; + } + } + + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx); + + + // Generate. + // + if (!generate_xml_schema) + { + if (forward) + hxx << "#include " << ctx.process_include_path (fwd_name) + << endl << endl; + else + generate_forward (ctx); + } + + generate_tree_header (ctx); + + if (!generate_xml_schema) + { + + if (ops.value<CLI::generate_ostream> ()) + generate_stream_header (ctx); + + if (!ops.value<CLI::generate_element_type> () && + !ops.value<CLI::suppress_parsing> ()) + generate_parser_header (ctx); + + if (ops.value<CLI::generate_serialization> ()) + generate_serialization_header (ctx); + + if (!ops.value<CLI::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 <xsd/cxx/post.hxx>" << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, ops.value<CLI::hxx_epilogue_file> (), epilogue); + append ( + hxx, ops.value<CLI::hxx_epilogue> (), ops.value<CLI::epilogue> ()); + + hxx << "//" << endl + << "// End epilogue." << endl + << endl; + + hxx << "#endif // " << guard << endl; + + if (show_sloc) + { + wcerr << hxx_path << ": " + << hxx_sloc.buffer ().count () << endl; + + sloc += hxx_sloc.buffer ().count (); + } + } + + + // IXX + // + if (inline_) + { + Context ctx (ixx, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx); + + // Guard + // + String guard (guard_expr.merge (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.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ()); + append (ixx, ops.value<CLI::ixx_prologue_file> (), prologue); + + ixx << "//" << endl + << "// End prologue." << endl + << endl; + + { + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx); + + + // Generate. + // + generate_tree_inline (ctx, 1, 0); + } + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue); + append ( + ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ()); + + ixx << "//" << endl + << "// End epilogue." << endl + << endl; + + ixx << "#endif // " << guard.c_str () << endl; + + if (show_sloc) + { + wcerr << ixx_path << ": " + << ixx_sloc.buffer ().count () << endl; + + sloc += ixx_sloc.buffer ().count (); + } + } + + + // CXX + // + + if (source) + { + UnsignedLong first_unit (0); // First unit in the current part. + + for (UnsignedLong part (0); part < parts; ++part) + { + // Figure out the range of units for this part. + // + UnsignedLong last_unit (first_unit); + + if (units != 0) + { + UnsignedLong 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. + // + UnsignedLong 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; + } + } + + // + // + UnsignedLong first (first_unit); + UnsignedLong 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); + + Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (os); + + // Copy prologue. + // + os << "// Begin prologue." << endl + << "//" << endl; + + append (os, + ops.value<CLI::cxx_prologue> (), + ops.value<CLI::prologue> ()); + append (os, ops.value<CLI::cxx_prologue_file> (), prologue); + + os << "//" << endl + << "// End prologue." << endl + << endl; + + { + os << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (os); + + + // Generate. + // + os << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + if (!inline_) + generate_tree_inline (ctx, first, last); + + generate_tree_source (ctx, first, last); + + if (ops.value<CLI::generate_ostream> ()) + generate_stream_source (ctx, first, last); + + if (!ops.value<CLI::generate_element_type> () && + !ops.value<CLI::suppress_parsing> ()) + generate_parser_source (ctx, first, last); + + if (ops.value<CLI::generate_serialization> ()) + generate_serialization_source (ctx, first, last); + + if (!ops.value<CLI::generate_extraction> ().empty ()) + generate_stream_extraction_source (ctx); + + if (!ops.value<CLI::generate_insertion> ().empty ()) + generate_stream_insertion_source (ctx); + + os << "#include <xsd/cxx/post.hxx>" << endl + << endl; + } + + // Copy epilogue. + // + os << "// Begin epilogue." << endl + << "//" << endl; + + append (os, ops.value<CLI::cxx_epilogue_file> (), epilogue); + append (os, + ops.value<CLI::cxx_epilogue> (), + ops.value<CLI::epilogue> ()); + + os << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_paths[part] << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + } + + return sloc; + } + 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 (BackendElements::Regex::Format<Char> const& e) + { + wcerr << "error: invalid regex: '" << + e.expression ().c_str () << "': " << + e.description ().c_str () << endl; + + throw Failed (); + } + catch (BackendElements::Regex::Format<WideChar> const& e) + { + wcerr << "error: invalid regex: '" << + e.expression () << "': " << e.description () << 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..2e50392 --- /dev/null +++ b/xsd/xsd/cxx/tree/generator.hxx @@ -0,0 +1,52 @@ +// file : xsd/cxx/tree/generator.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_GENERATOR_HXX +#define CXX_TREE_GENERATOR_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph/elements.hxx> // Path +#include <xsd-frontend/semantic-graph/schema.hxx> + +#include <xsd.hxx> + +#include <cxx/literal-map.hxx> +#include <cxx/tree/cli.hxx> + +namespace CXX +{ + namespace Tree + { + using namespace Cult::Types; + + class Generator + { + public: + static Void + usage (); + + static CLI::OptionsSpec + options_spec (); + + struct Failed {}; + + static UnsignedLong + generate (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + Boolean file_per_type, + StringLiteralMap const&, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks); + + private: + Generator (); + }; + } +} + +#endif // 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..4949bed --- /dev/null +++ b/xsd/xsd/cxx/tree/name-processor.cxx @@ -0,0 +1,2140 @@ +// file : xsd/cxx/tree/name-processor.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <sstream> +#include <iostream> + +#include <cult/containers/set.hxx> +#include <cult/containers/map.hxx> +#include <cult/containers/vector.hxx> + +#include <backend-elements/regex.hxx> + +#include <cxx/tree/default-value.hxx> +#include <cxx/tree/name-processor.hxx> + +namespace CXX +{ + namespace Tree + { + NameProcessor:: + NameProcessor () + { + // Dummy ctor, helps with long symbols on HP-UX. + } + + namespace + { + // + // + typedef Cult::Containers::Set<String> NameSet; + + class Context: public Tree::Context + { + public: + struct Failed {}; + + Context (CLI::Options const& options, + Counts const& counts, + Boolean generate_xml_schema, + SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + StringLiteralMap const& map) + : Tree::Context (std::wcerr, + root, + path, + options, + counts, + generate_xml_schema, + &map, + 0, + 0, + 0), + global_type_names (global_type_names_), + global_element_names (global_element_names_), + detach (options.value<CLI::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_), + enumerator_regex (enumerator_regex_), + element_type_regex (element_type_regex_) + { + typedef Containers::Vector<NarrowString> Vector; + + NarrowString tn (options.value<CLI::type_naming> ()); + NarrowString fn (options.value<CLI::function_naming> ()); + + + // Type name regex. + // + { + // Predefined rules. The most frequently used come last: global + // names, two components (<name>,type), three components + // (<name>,const,iterator), and one component (value in enum). + // + if (tn == "knr") + { + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/$1/"); + + /* + type_regex.push_back ("/([^,]+)/$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + type_regex.push_back ("/[^ ]* (.+)/$1/"); + */ + } + else + { + // Upper camel case or Java. + // + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/(?:[^ ]* )?([^,]+)/\\u$1/"); + + /* + type_regex.push_back ("/([^,]+)/\\u$1/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/"); + type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/"); + type_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/"); + type_regex.push_back ("/[^ ]* (.+)/\\u$1/"); + */ + + } + + compile_regex (options.value<CLI::type_regex> (), + type_regex, + "type"); + } + + // Accessor name regex. + // + { + // Predefined rules. The most frequently used come last: one + // component, three components (<name>,default,value) and two + // component (dom,document). + // + if (fn == "knr") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/$1_$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/"); + accessor_regex.push_back ("/([^,]+)/$1/"); + } + else if (fn == "lcc") + { + accessor_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/"); + accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1\\u$2\\u$3/"); + accessor_regex.push_back ("/([^,]+)/\\l$1/"); + } + else + { + // 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.value<CLI::accessor_regex> (), + accessor_regex, + "accessor"); + + compile_regex (options.value<CLI::one_accessor_regex> (), + one_accessor_regex, + "one accessor"); + + compile_regex (options.value<CLI::opt_accessor_regex> (), + opt_accessor_regex, + "optional accessor"); + + compile_regex (options.value<CLI::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.value<CLI::modifier_regex> (), + modifier_regex, + "modifier"); + + compile_regex (options.value<CLI::one_modifier_regex> (), + one_modifier_regex, + "one modifier"); + + compile_regex (options.value<CLI::opt_modifier_regex> (), + opt_modifier_regex, + "optional modifier"); + + compile_regex (options.value<CLI::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.value<CLI::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.value<CLI::serializer_regex> (), + serializer_regex, + "serializer"); + } + + // Enumerator name regex. + // + { + // By default map an empty enumerator to the 'empty' word. + // + enumerator_regex.push_back ("/^$/empty/"); + + compile_regex (options.value<CLI::enumerator_regex> (), + enumerator_regex, + "enumerator"); + } + + // Element type regex. + // + compile_regex (options.value<CLI::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), + enumerator_regex (c.enumerator_regex), + element_type_regex (c.element_type_regex) + { + } + + public: + typedef BackendElements::Regex::Expression<WideChar> Regex; + typedef BackendElements::Regex::Format<WideChar> RegexFormat; + typedef Cult::Containers::Vector<Regex> RegexVector; + + String + process_regex (String const& name, + RegexVector const& rv, + String const& id) + { + Boolean trace (options.value<CLI::name_regex_trace> ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::ConstReverseIterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (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) + { + Boolean trace (options.value<CLI::name_regex_trace> ()); + + if (trace) + os << id << " name: '" << name << "'" << endl; + + for (RegexVector::ConstReverseIterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (name)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::ConstReverseIterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (name)) + { + String r (i->merge (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); + Boolean trace (options.value<CLI::name_regex_trace> ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::ConstReverseIterator i (rv.rbegin ()); + i != rv.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (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); + Boolean trace (options.value<CLI::name_regex_trace> ()); + + if (trace) + os << id << " name: '" << s << "'" << endl; + + for (RegexVector::ConstReverseIterator i (primary.rbegin ()); + i != primary.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + for (RegexVector::ConstReverseIterator i (backup.rbegin ()); + i != backup.rend (); ++i) + { + if (trace) + os << "try: '" << i->pattern () << "' : "; + + if (i->match (s)) + { + String r (i->merge (s)); + + if (trace) + os << "'" << r << "' : +" << endl; + + return r; + } + + if (trace) + os << '-' << endl; + } + + return name; + } + + public: + String + find_name (String const& base_name, + NameSet& set, + Boolean insert = true) + { + String name (base_name); + + for (UnsignedLong 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 (Containers::Vector<NarrowString> const& sv, + RegexVector& rv, + String const& id) + { + typedef Containers::Vector<NarrowString> Vector; + + for (Vector::ConstIterator i (sv.begin ()); i != sv.end (); ++i) + { + try + { + rv.push_back (Regex (*i)); + } + catch (RegexFormat const& e) + { + os << "error: invalid " << id << " name regex: '" << + e.expression () << "': " << e.description () << endl; + + throw Failed (); + } + } + } + + private: + Cult::Containers::Map<String, NameSet> global_type_names_; + Cult::Containers::Map<String, NameSet> global_element_names_; + + RegexVector type_regex_; + RegexVector accessor_regex_; + RegexVector one_accessor_regex_; + RegexVector opt_accessor_regex_; + RegexVector seq_accessor_regex_; + RegexVector modifier_regex_; + RegexVector one_modifier_regex_; + RegexVector opt_modifier_regex_; + RegexVector seq_modifier_regex_; + RegexVector parser_regex_; + RegexVector serializer_regex_; + RegexVector enumerator_regex_; + RegexVector element_type_regex_; + + public: + Cult::Containers::Map<String, NameSet>& global_type_names; + Cult::Containers::Map<String, NameSet>& global_element_names; + + Boolean 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& enumerator_regex; + RegexVector& element_type_regex; + }; + + // + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c, NameSet& set) + : Context (c), set_ (set) + { + } + + virtual Void + traverse (Type& e) + { + // Process the name with enumerator name regex. + // + String name ( + process_regex (e.name (), enumerator_regex, L"enumerator")); + + // Escape and unclash. + // + name = find_name (escape (name), set_); + e.context ().set ("name", name); + } + + private: + NameSet& set_; + }; + + // + // + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + // Use processed name. + // + String name (e.context ().get<String> ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (e, name) && !name) + return; + + NameSet enum_set; + enum_set.insert (name); + + Enumerator enumerator (*this, enum_set); + Traversal::Names names (enumerator); + + Traversal::Enumeration::names (e, names); + + // Assign name to the value type. First process the name + // with type name regex. + // + String value_name ( + escape (process_regex ("value", type_regex, L"type"))); + e.context ().set ("value", find_name (value_name, enum_set)); + } + }; + + // + // + struct PrimaryMember: Traversal::Member, Context + { + PrimaryMember (Context& c, NameSet& name_set, NameSet& stem_set) + : Context (c), name_set_ (name_set), stem_set_ (stem_set) + { + } + + virtual Void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + String stem (find_name (m.name (), stem_set_)); + + m.context ().set ("stem", stem); + m.context ().set ("name", + find_name (escape (stem), name_set_, false)); + } + + private: + NameSet& name_set_; + NameSet& stem_set_; + }; + + // + // + struct DerivedMember: Traversal::Member, Context + { + DerivedMember (Context& c, NameSet& name_set) + : Context (c), name_set_ (name_set) + { + } + + virtual Void + traverse (Type& m) + { + if (Tree::Context::skip (m)) + return; + + UnsignedLong max (Tree::Context::max (m)); + UnsignedLong min (Tree::Context::min (m)); + + String const& s (m.context ().get<String> ("stem")); + String const& b (m.context ().get<String> ("name")); + + Boolean def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + // Accessors/modifiers. Note that we postpone inserting + // the names into the name_set to avoid over-escaping. + // + String an, mn; + + if (max != 1) + { + an = find_name ( + escape (process_regex (s, + seq_accessor_regex, + accessor_regex, + L"sequence accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + seq_modifier_regex, + modifier_regex, + L"sequence modifier")), + name_set_, + false); + } + else if (min == 0 && !def_attr) + { + an = find_name ( + escape (process_regex (s, + opt_accessor_regex, + accessor_regex, + L"optional accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + opt_modifier_regex, + modifier_regex, + L"optional modifier")), + name_set_, + false); + } + else + { + an = find_name ( + escape (process_regex (s, + one_accessor_regex, + accessor_regex, + L"one accessor")), + name_set_, + false); + + mn = find_name ( + escape (process_regex (s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_, + false); + } + + m.context ().set ("aname", an); + m.context ().set ("mname", mn); + + name_set_.insert (b); + + if (an != b) + name_set_.insert (an); + + if (mn != b && mn != an) + name_set_.insert (mn); + + // Detach. + // + if (detach && max == 1 && (min == 1 || def_attr)) + { + String dn (find_name ( + escape (process_regex (L"detach," + s, + one_modifier_regex, + modifier_regex, + L"one modifier")), + name_set_)); + + m.context ().set ("dname", dn); + } + + // Types. + // + m.context ().set ( + "type", + find_name ( + escape (process_regex (s + L",type", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "traits", + find_name ( + escape (process_regex (s + L",traits", type_regex, L"type")), + name_set_)); + + if (max != 1) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",sequence", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "iterator", + find_name ( + escape (process_regex (s + L",iterator", type_regex, L"type")), + name_set_)); + + m.context ().set ( + "const-iterator", + find_name ( + escape ( + process_regex (s + L",const,iterator", type_regex, L"type")), + name_set_)); + } + else if (min == 0 && !def_attr) + { + m.context ().set ( + "container", + find_name ( + escape (process_regex (s + L",optional", type_regex, L"type")), + name_set_)); + } + + // Data member. + // + m.context ().set ("member", find_name (b + L"_", name_set_)); + + // Default value. + // + if (m.default_p ()) + { + Boolean simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + String an ( + escape ( + process_regex ( + s + L",default,value", accessor_regex, L"accessor"))); + + m.context ().set ( "default-value", find_name (an, name_set_)); + + Boolean 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_)); + } + } + } + } + + private: + NameSet& name_set_; + }; + + + // + // + struct Any: Traversal::Any, Traversal::AnyAttribute, Context + { + Any (Context& c, + NameSet& name_set, + NameSet& stem_set, + Boolean& has_wildcard) + : Context (c), + name_set_ (name_set), + stem_set_ (stem_set), + has_wildcard_ (has_wildcard) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + UnsignedLong max (Tree::Context::max (a)); + UnsignedLong 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_)); + + 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_; + Boolean& has_wildcard_; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + SemanticGraph::Context& cc (c.context ()); + + // We leave this set around to allow other mappings to use + // this information. + // + cc.set ("cxx-tree-name-processor-stem-set", NameSet ()); + cc.set ("cxx-tree-name-processor-member-set", NameSet ()); + + // Use processed name. + // + String name (cc.get<String> ("name")); + + // If renamed name is empty then we are not generating + // anything for this type and name processing is not + // required. + // + if (renamed_type (c, name) && !name) + return; + + NameSet& stem_set ( + cc.get<NameSet> ("cxx-tree-name-processor-stem-set")); + + NameSet& member_set ( + cc.get<NameSet> ("cxx-tree-name-processor-member-set")); + + stem_set.insert (c.name ()); + member_set.insert (name); + + // Add our base's stems and members to the initial list. + // + if (c.inherits_p ()) + { + // @@ What if this types name is the same as one of base's + // members? + // + SemanticGraph::Type& base (c.inherits ().base ()); + + if (base.is_a<SemanticGraph::Complex> () && + !base.is_a<SemanticGraph::Enumeration> ()) + { + if (!base.context ().count ( + "cxx-tree-name-processor-member-set")) + { + dispatch (base); + } + + NameSet const& base_stem_set ( + base.context ().get<NameSet> ( + "cxx-tree-name-processor-stem-set")); + + stem_set.insert (base_stem_set.begin (), base_stem_set.end ()); + + NameSet const& base_member_set ( + base.context ().get<NameSet> ( + "cxx-tree-name-processor-member-set")); + + member_set.insert (base_member_set.begin (), + base_member_set.end ()); + } + } + + // First assign the "primary" names. + // + { + PrimaryMember member (*this, member_set, stem_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Derived names for members. + // + { + DerivedMember member (*this, member_set); + Traversal::Names names (member); + + Complex::names (c, names); + } + + // Names for wildcards. + // + if (options.value<CLI::generate_wildcard> ()) + { + Boolean has_wildcard (false); + Any any (*this, member_set, stem_set, has_wildcard); + Traversal::Names names (any); + Complex::names (c, names); + + // Assign names for dom_document. + // + if (has_wildcard) + { + // Check if we already have dom_document down inheritance + // hierarchy. + // + for (SemanticGraph::Complex* p (&c); p->inherits_p ();) + { + if (SemanticGraph::Complex* base = + dynamic_cast<SemanticGraph::Complex*> ( + &p->inherits ().base ())) + { + if (base->context ().count ("dom-document")) + { + c.context ().set ( + "dom-document", + base->context ().get<String> ("dom-document")); + break; + } + + p = base; + } + else + break; + } + + // If not, set up the names. + // + if (!c.context ().count ("dom-document")) + { + String stem (find_name (L"dom,document", stem_set)); + + String an ( + escape ( + process_regex (stem, accessor_regex, L"accessor"))); + + c.context ().set ("dom-document", find_name (an, member_set)); + + c.context ().set ( + "dom-document-member", + find_name (escape (stem + L"_"), member_set)); + } + } + } + } + }; + + + // + // + 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.value<CLI::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.value<CLI::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.value<CLI::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 (UnsignedLong 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"); + + if (options.value<CLI::generate_element_type> ()) + process_name (n, "element,type", "element-type"); + + if (options.value<CLI::generate_element_map> ()) + process_name (n, "element,map", "element-map"); + + if (options.value<CLI::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.value<CLI::generate_insertion> ().empty ()) + { + process_name (n, "ostream", "ostream"); + } + + if (!options.value<CLI::generate_extraction> ().empty ()) + { + process_name (n, "istream", "istream"); + } + + process_name (n, "flags", "flags"); + process_name (n, "properties", "properties"); + + NarrowString fn (options.value<CLI::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.value<CLI::suppress_parsing> () || + options.value<CLI::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); + } + } + }; + + Boolean + process_impl (CLI::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; + Traversal::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; + } + } + + Boolean NameProcessor:: + process (CLI::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..cf187b7 --- /dev/null +++ b/xsd/xsd/cxx/tree/name-processor.hxx @@ -0,0 +1,31 @@ +// file : xsd/cxx/tree/name-processor.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_NAME_PROCESSOR_HXX +#define CXX_TREE_NAME_PROCESSOR_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + using namespace Cult::Types; + + class NameProcessor + { + public: + NameProcessor (); // Dummy ctor, helps with long symbols on HP-UX. + + Boolean + process (CLI::Options const&, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + StringLiteralMap const&); + }; + } +} + +#endif // CXX_TREE_NAME_PROCESSOR_HXX diff --git a/xsd/xsd/cxx/tree/parser-header.cxx b/xsd/xsd/cxx/tree/parser-header.cxx new file mode 100644 index 0000000..c1d1ab9 --- /dev/null +++ b/xsd/xsd/cxx/tree/parser-header.cxx @@ -0,0 +1,474 @@ +// file : xsd/cxx/tree/parser-header.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/parser-header.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eparser (e)); + String const& error_handler (error_handler_type); + + if (doxygen) + { + os << "/**" << endl + << " * @name Parsing functions for the %" << + comment (e.name ()) << " document root." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl + << "//@{" << endl + << endl; + } + + if (!doxygen) + { + os << "// Parse a URI or a local file." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file with an error handler." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a URI or a local file with a Xerces-C++ " << + "DOM error" << endl + << " * handler." << endl + << " *" << endl + << " * @param uri A URI or a local file name." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (const " << string_type << "& uri," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse std::istream." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with an error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a " << + "Xerces-C++ DOM error" << endl + << " * handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource id." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource " << + "id and an" << endl + << " * error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a standard input stream with a resource " << + "id and a" << endl + << " * Xerces-C++ DOM error handler." << endl + << " *" << endl + << " * @param is A standrad input stream." << endl + << " * @param id A resource id." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * The resource id is used to identify the document " << + "being parsed in" << endl + << " * diagnostics as well as to resolve relative paths." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& id," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse xercesc::InputSource." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function uses exceptions to report parsing errors." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source with an " << + "error handler." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param eh An error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << error_handler << "& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ input source with a " << + "Xerces-C++ DOM" << endl + << " * error handler." << endl + << " *" << endl + << " * @param is A Xerces-C++ input source." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function reports parsing errors by calling the " << + "error handler." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (" << xerces_ns << "::InputSource& is," << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (!doxygen) + { + os << "// Parse xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A Xerces-C++ DOM document." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (const " << xerces_ns << "::DOMDocument& d," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Parse a Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A pointer to the Xerces-C++ DOM document." << endl + << " * @param f Parsing flags." << endl + << " * @param p Parsing properties. " << endl + << " * @return A pointer to the root of the object model." << endl + << " *" << endl + << " * This function is normally used together with the " << + "keep_dom and" << endl + << " * own_dom parsing flags to assign ownership of the DOM " << + "document" << endl + << " * to the object model." << endl + << " */" << endl; + } + + os << inst_exp + << "::std::auto_ptr< " << type_name (e) << " >" << endl + << name << " (" << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument >& d," << endl + << flags_type << " f = 0," << endl + << "const " << properties_type << "& p = " << properties_type << " ());" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + + Void + generate_parser_header (Context& ctx) + { + ctx.os << "#include <iosfwd>" << endl + << endl + << "#include <xercesc/sax/InputSource.hpp>" << endl + << "#include <xercesc/dom/DOMDocument.hpp>" << endl + << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl + << endl; + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx); + ElementFunction element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/parser-header.hxx b/xsd/xsd/cxx/tree/parser-header.hxx new file mode 100644 index 0000000..20ca7d4 --- /dev/null +++ b/xsd/xsd/cxx/tree/parser-header.hxx @@ -0,0 +1,21 @@ +// file : xsd/cxx/tree/parser-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_PARSER_HEADER_HXX +#define CXX_TREE_PARSER_HEADER_HXX + +#include <cxx/tree/elements.hxx> + + +namespace CXX +{ + namespace Tree + { + Void + generate_parser_header (Context&); + } +} + +#endif // CXX_TREE_PARSER_HEADER_HXX diff --git a/xsd/xsd/cxx/tree/parser-source.cxx b/xsd/xsd/cxx/tree/parser-source.cxx new file mode 100644 index 0000000..7291cb8 --- /dev/null +++ b/xsd/xsd/cxx/tree/parser-source.cxx @@ -0,0 +1,542 @@ +// file : xsd/cxx/tree/parser-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/parser-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eparser (e)); + SemanticGraph::Type& t (e.type ()); + String type (type_name (e)); + String const& error_handler (error_handler_type); + + // Note that I am using fq-name in function calls because g++ gets + // confused if the name is 'type'. (see tests/schema/anonymous) + // + + // URI. + // + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << + char_type << " > > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (const " << string_type << "& u," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "u, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + + // istream + // + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, f, p);" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::sax::std_input_source isrc (is);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, f, p);" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0," << endl + << "(f & " << flags_type << "::keep_dom) == 0);" + << endl + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (::std::istream& is," << endl + << "const " << string_type << "& sid," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);" + << "return " << fq_name (e, "parser") << " (isrc, h, f, p);" + << "}"; + + + // InputSource. + // + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " << + char_type << " > > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << error_handler << "& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (" << xerces_ns << "::InputSource& i," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl + << "i, h, p, f"; + + if (options.value<CLI::disable_multi_import> ()) + os << " | ::xsd::cxx::xml::dom::no_muliple_imports"; + + os << "));" + << endl + << "if (!d.get ())" << endl + << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "d, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}"; + + + // DOM. + // + + Boolean fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. + // + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + // const DOMDocument& + // + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (const " << xerces_ns << "::DOMDocument& d," << endl + << flags_type << " f," << endl + << "const " << properties_type << "& p)" + << "{" + << "if (f & " << flags_type << "::keep_dom)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > c (" << endl + << "static_cast< " << xerces_ns << + "::DOMDocument* > (d.cloneNode (true)));" + << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << fq_name (e, "parser") << " (" << endl + << "c, f | " << flags_type << "::own_dom, p));" + << endl + << "return r;" + << "}" + << "const " << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl; + + if (poly) + { + // aCC cannot handle an inline call to type_factory_map_instance. + // + os << "::xsd::cxx::tree::type_factory_map< " << char_type << + " >& tfm (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< 0, " << + char_type << " > ());" + << endl + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "tfm.create (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl + << "true, true, e, n, f, 0));" + << endl + << "if (tmp.get () != 0)" + << "{" + << "::std::auto_ptr< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" + << "{"; + + if (fund) + { + os << "::std::auto_ptr< " << type << " > r (" << endl + << "new " << type << " (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " >::create (" << endl + << "e, f, 0)));"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type << " >::create (" << endl + << "e, f, 0));"; + } + } + + os << "return r;" + << "}" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << ");" + << "}"; + + + // dom::auto_ptr<DOMDocument> + // + os << "::std::auto_ptr< " << type << " >" << endl + << name << " (" << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument >& d," << endl + << flags_type << " f," << endl + << "const " << properties_type << "&)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > c (" << endl + << "((f & " << flags_type << "::keep_dom) &&" << endl + << "!(f & " << flags_type << "::own_dom))" << endl + << "? static_cast< " << xerces_ns << "::DOMDocument* > (" << + "d->cloneNode (true))" << endl + << ": 0);" + << endl + << xerces_ns << "::DOMDocument& doc (c.get () ? *c : *d);" + << "const " << xerces_ns << "::DOMElement& e (" << + "*doc.getDocumentElement ());" + << endl + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl + << "if (f & " << flags_type << "::keep_dom)" << endl + << "doc.setUserData (" << dom_node_key << "," << endl + << "(c.get () ? &c : &d)," << endl + << "0);" + << endl; + + if (poly) + { + // aCC cannot handle an inline call to type_factory_map_instance. + // + os << "::xsd::cxx::tree::type_factory_map< " << char_type << + " >& tfm (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< 0, " << + char_type << " > ());" + << endl + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "tfm.create (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl + << "true, true, e, n, f, 0));" + << endl + << "if (tmp.get () != 0)" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (e.namespace_().name ()) << ")" + << "{"; + + if (fund) + { + os << "::std::auto_ptr< " << type << " > r (" << endl + << "new " << type << " (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " >::create (" << endl + << "e, f, 0)));"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (" << endl + << "::xsd::cxx::tree::traits< " << type << ", " << + char_type << " >::create (" << endl + << "e, f, 0));"; + } + } + + if (poly) + { + os << endl + << "::std::auto_ptr< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + + os << "return r;" + << "}" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << ");" + << "}"; + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + Void + generate_parser_source (Context& ctx, + UnsignedLong first, + UnsignedLong last) + { + ctx.os << "#include <istream>" << endl + << "#include <xsd/cxx/xml/sax/std-input-source.hxx>" << endl + << "#include <xsd/cxx/tree/error-handler.hxx>" << endl + << endl; + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + ElementFunction element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/parser-source.hxx b/xsd/xsd/cxx/tree/parser-source.hxx new file mode 100644 index 0000000..2a85571 --- /dev/null +++ b/xsd/xsd/cxx/tree/parser-source.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/parser-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_PARSER_SOURCE_HXX +#define CXX_TREE_PARSER_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_parser_source (Context&, UnsignedLong first, UnsignedLong last); + } +} + +#endif // CXX_TREE_PARSER_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/polymorphism-processor.cxx b/xsd/xsd/cxx/tree/polymorphism-processor.cxx new file mode 100644 index 0000000..0763f0f --- /dev/null +++ b/xsd/xsd/cxx/tree/polymorphism-processor.cxx @@ -0,0 +1,791 @@ +// file : xsde/cxx/tree/polymorphism-processor.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/elements.hxx> +#include <cxx/tree/polymorphism-processor.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/set.hxx> + +#include <iostream> + +using std::wcerr; + +namespace CXX +{ + namespace Tree + { + namespace + { + struct TypeSet + { + template <typename I> + TypeSet (I begin, I end) + { + for (; begin != end; ++begin) + insert (*begin); + } + + Void + insert (String const& name) + { + Size p (name.rfind ('#')); + + if (p == String::npos) + unames_.insert (name); + else + qnames_.insert (name); + } + + Boolean + 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 Cult::Containers::Set<String> StringSet; + + StringSet unames_; + StringSet qnames_; + }; + + + // + // + struct Type: Traversal::Type, + Traversal::Complex + { + Type (TypeSet& poly_types) + : poly_types_ (poly_types) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + SemanticGraph::Context& ctx (t.context ()); + + if (!ctx.count ("polymorphic")) + ctx.set ("polymorphic", poly_types_.find (t)); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + SemanticGraph::Context& ctx (c.context ()); + + if (!ctx.count ("polymorphic")) + { + // First check our base. + // + Boolean pb (false); + if (c.inherits_p ()) + { + SemanticGraph::Type& b (c.inherits ().base ()); + + if (!b.context ().count ("polymorphic")) + dispatch (b); + + pb = b.context ().get<Boolean> ("polymorphic"); + } + + ctx.set ("polymorphic", pb || poly_types_.find (c)); + } + } + + private: + TypeSet& poly_types_; + }; + + struct FundType: Traversal::AnyType, + Traversal::AnySimpleType, + + Traversal::Fundamental::Byte, + Traversal::Fundamental::UnsignedByte, + Traversal::Fundamental::Short, + Traversal::Fundamental::UnsignedShort, + Traversal::Fundamental::Int, + Traversal::Fundamental::UnsignedInt, + Traversal::Fundamental::Long, + Traversal::Fundamental::UnsignedLong, + Traversal::Fundamental::Integer, + Traversal::Fundamental::NonPositiveInteger, + Traversal::Fundamental::NonNegativeInteger, + Traversal::Fundamental::PositiveInteger, + Traversal::Fundamental::NegativeInteger, + + Traversal::Fundamental::Boolean, + + Traversal::Fundamental::Float, + Traversal::Fundamental::Double, + Traversal::Fundamental::Decimal, + + Traversal::Fundamental::String, + Traversal::Fundamental::NormalizedString, + Traversal::Fundamental::Token, + Traversal::Fundamental::Name, + Traversal::Fundamental::NameToken, + Traversal::Fundamental::NameTokens, + Traversal::Fundamental::NCName, + Traversal::Fundamental::Language, + + Traversal::Fundamental::QName, + + Traversal::Fundamental::Id, + Traversal::Fundamental::IdRef, + Traversal::Fundamental::IdRefs, + + Traversal::Fundamental::AnyURI, + + Traversal::Fundamental::Base64Binary, + Traversal::Fundamental::HexBinary, + + Traversal::Fundamental::Date, + Traversal::Fundamental::DateTime, + Traversal::Fundamental::Duration, + Traversal::Fundamental::Day, + Traversal::Fundamental::Month, + Traversal::Fundamental::MonthDay, + Traversal::Fundamental::Year, + Traversal::Fundamental::YearMonth, + Traversal::Fundamental::Time, + + Traversal::Fundamental::Entity, + Traversal::Fundamental::Entities + { + FundType (TypeSet& poly_types, Boolean& valid) + : poly_types_ (poly_types), valid_ (valid) + { + } + + Void + check (SemanticGraph::Type& t, Boolean fund) + { + SemanticGraph::Context& ctx (t.context ()); + + if (poly_types_.find (t)) + { + if (!fund) + ctx.set ("polymorphic", true); + else + { + wcerr << "error: built-in type '" << t.name () << "' cannot " + << "be polymorphic because it is mapped to a fundamental " + << "C++ type" + << endl; + + valid_ = false; + } + } + else + ctx.set ("polymorphic", false); + } + + // anyType & anySimpleType. + // + virtual Void + traverse (SemanticGraph::AnyType& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::AnySimpleType& t) + { + check (t, false); + } + + // Boolean. + // + virtual Void + traverse (SemanticGraph::Fundamental::Boolean& t) + { + check (t, true); + } + + // Integral types. + // + virtual Void + traverse (SemanticGraph::Fundamental::Byte& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedByte& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Short& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedShort& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Int& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedInt& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Long& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::UnsignedLong& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Integer& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonPositiveInteger& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NonNegativeInteger& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::PositiveInteger& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NegativeInteger& t) + { + check (t, true); + } + + // Floats. + // + virtual Void + traverse (SemanticGraph::Fundamental::Float& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Double& t) + { + check (t, true); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Decimal& t) + { + check (t, true); + } + + // Strings. + // + virtual Void + traverse (SemanticGraph::Fundamental::String& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NormalizedString& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Token& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameToken& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NameTokens& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Name& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::NCName& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Language& t) + { + check (t, false); + } + + + // Qualified name. + // + virtual Void + traverse (SemanticGraph::Fundamental::QName& t) + { + check (t, false); + } + + + // ID/IDREF. + // + virtual Void + traverse (SemanticGraph::Fundamental::Id& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRef& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::IdRefs& t) + { + check (t, false); + } + + // URI. + // + virtual Void + traverse (SemanticGraph::Fundamental::AnyURI& t) + { + check (t, false); + } + + // Binary. + // + virtual Void + traverse (SemanticGraph::Fundamental::Base64Binary& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::HexBinary& t) + { + check (t, false); + } + + + // Date/time. + // + virtual Void + traverse (SemanticGraph::Fundamental::Date& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::DateTime& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Duration& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Day& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Month& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::MonthDay& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Year& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::YearMonth& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Time& t) + { + check (t, false); + } + + // Entity. + // + virtual Void + traverse (SemanticGraph::Fundamental::Entity& t) + { + check (t, false); + } + + virtual Void + traverse (SemanticGraph::Fundamental::Entities& t) + { + check (t, false); + } + + private: + TypeSet& poly_types_; + Boolean& valid_; + }; + + struct GlobalElement: Traversal::Element + { + GlobalElement (TypeSet& poly_types, + Boolean& valid, + const WarningSet& disabled_warnings) + : poly_types_ (poly_types), valid_ (valid), warning_ (true) + { + if (disabled_warnings.find ("all") != disabled_warnings.end () || + disabled_warnings.find ("T005") != disabled_warnings.end ()) + warning_ = false; + } + + virtual Void + traverse (Type& e) + { + using SemanticGraph::Schema; + + if (!e.substitutes_p ()) + return; + + // If we are a substitution for some element, then mark + // that element's type as polymorphic. + // + Type& r (e.substitutes ().root ()); + SemanticGraph::Type& rt (r.type ()); + SemanticGraph::Context& ctx (rt.context ()); + + // We may need to override the previous value. + // + if (ctx.count ("polymorphic") && ctx.get<Boolean> ("polymorphic")) + return; + + // Built-in types that are mapped to fundamental types cannot + // be declared polymorphic. + // + Boolean fund (false); + IsFundamentalType test (fund); + test.dispatch (rt); + + if (fund) + { + wcerr << r.file () << ":" << r.line () << ":" << r.column () + << ": error: built-in type '" << rt.name () << "' " + << "is mapped to a fundamental C++ type and is expected " + << "to be polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + valid_ = false; + return; + } + + ctx.set ("polymorphic", true); + + if (!warning_) + return; + + Schema& es (dynamic_cast<Schema&> (e.scope ().scope ())); + Schema& rts (dynamic_cast<Schema&> (rt.scope ().scope ())); + + // If the root type and this element are in different schemas + // and the root type is not explicitly marked as polymorphic, + // then issue a warning. + // + if (&es != &rts && !sources_p (es, rts) && !poly_types_.find (rt)) + { + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": warning T005: assuming type '" << rt.name () << "' " + << "is polymorphic" << endl; + + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": info: because type '" << rt.name () << "' is " + << "used in a substitution group declared here" << endl; + + wcerr << rt.file () << ":" << rt.line () << ":" << rt.column () + << ": info: use --polymorphic-type to indicate this type " + << "is polymorphic when compiling schemas that " + << "reference it" << endl; + } + } + + private: + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a<Sources> ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + TypeSet& poly_types_; + Boolean& valid_; + Boolean warning_; + }; + + // Go into sourced/included/imported schemas while making sure + // we don't process the same stuff more than once. + // + struct Uses: Traversal::Sources, + Traversal::Includes, + Traversal::Imports + { + Uses (Char const* seen_key) + : seen_key_ (seen_key) + { + } + + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Sources::traverse (sr); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (!s.context ().count (seen_key_)) + { + s.context ().set (seen_key_, true); + Traversal::Imports::traverse (i); + } + } + + private: + Char const* seen_key_; + }; + + Char const* pass_one_key = "cxx-tree-polymorphism-processor-seen-one"; + Char const* pass_two_key = "cxx-tree-polymorphism-processor-seen-two"; + + Boolean + process_impl (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const&, + const WarningSet& disabled_warnings) + { + Boolean valid (true); + + // Prepare a set of polymorphic types. + // + + TypeSet poly_types (ops.value<CLI::polymorphic_type> ().begin (), + ops.value<CLI::polymorphic_type> ().end ()); + + // Root schema in the file-per-type mode is just a bunch + // of includes without a namespace. + // + SemanticGraph::Schema::NamesIterator i (tu.names_begin ()); + + if (i != tu.names_end () && + i->named ().name () == L"http://www.w3.org/2001/XMLSchema") + { + // XML Schema namespace. + // + Traversal::Schema schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + schema >> schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + else + { + // First handle fundamental types. + // + { + Traversal::Schema schema; + Traversal::Implies implies; + Traversal::Schema xs_schema; + + schema >> implies >> xs_schema; + + Traversal::Names xs_schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundType fund_type (poly_types, valid); + + xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type; + + schema.dispatch (tu); + } + + // Note that we check first if this schema has already been + // processed which may happen in the file-per-type compilation + // mode. + // + if (!tu.context ().count (pass_two_key)) + { + // Pass one - check substitution groups. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_one_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + GlobalElement element (poly_types, valid, disabled_warnings); + + schema >> schema_names >> ns >> ns_names >> element; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_one_key, true); + + schema.dispatch (tu); + } + + // Pass two - process types. + // + if (valid) + { + Traversal::Schema schema; + Uses uses (pass_two_key); + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (poly_types); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set (pass_two_key, true); + + schema.dispatch (tu); + } + } + } + + return valid; + } + } + + Boolean PolymorphismProcessor:: + process (CLI::Options const& ops, + SemanticGraph::Schema& tu, + SemanticGraph::Path const& file, + const WarningSet& disabled_warnings) + { + return process_impl (ops, tu, file, disabled_warnings); + } + } +} diff --git a/xsd/xsd/cxx/tree/polymorphism-processor.hxx b/xsd/xsd/cxx/tree/polymorphism-processor.hxx new file mode 100644 index 0000000..3fbeca8 --- /dev/null +++ b/xsd/xsd/cxx/tree/polymorphism-processor.hxx @@ -0,0 +1,35 @@ +// file : xsde/cxx/tree/polymorphism-processor.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_POLYMORPHISM_PROCESSOR_HXX +#define CXX_TREE_POLYMORPHISM_PROCESSOR_HXX + +#include <cult/types.hxx> + +#include <xsd-frontend/semantic-graph.hxx> + +#include <cxx/tree/cli.hxx> + +#include <xsd.hxx> + +namespace CXX +{ + namespace Tree + { + using namespace Cult::Types; + + class PolymorphismProcessor + { + public: + Boolean + process (CLI::Options const& options, + XSDFrontend::SemanticGraph::Schema&, + XSDFrontend::SemanticGraph::Path const& file, + const WarningSet& disabled_warnings); + }; + } +} + +#endif // CXX_TREE_POLYMORPHISM_PROCESSOR_HXX diff --git a/xsd/xsd/cxx/tree/serialization-header.cxx b/xsd/xsd/cxx/tree/serialization-header.cxx new file mode 100644 index 0000000..d024a38 --- /dev/null +++ b/xsd/xsd/cxx/tree/serialization-header.cxx @@ -0,0 +1,581 @@ +// file : xsd/cxx/tree/serialization-header.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/serialization-header.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << name << "&);" + << endl; + + Boolean simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + // operator<< (xercesc::DOMAttr) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&, " << + "const " << name << "&);" + << endl; + + // operator<< (list_stream) + // + os << inst_exp + << "void" << endl + << "operator<< (" << list_stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + struct ElementType: Traversal::Element, + GlobalElementBase, + Context + { + ElementType (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (doc_root_p (e)) + { + // operator<< (xercesc::DOMElement) + // + os << inst_exp + << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement&, " << + "const " << ename (e) << "&);" + << endl; + } + } + }; + + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eserializer (e)); + String const& error_handler (error_handler_type); + String const& namespace_infomap (namespace_infomap_type); + + if (doxygen) + { + os << "/**" << endl + << " * @name Serialization functions for the %" << + comment (e.name ()) << " document root." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl + << "//@{" << endl + << endl; + } + + if (!doxygen) + { + os << "// Serialize to std::ostream." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function uses exceptions to report " << + "serialization errors." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream with an " << + "error handler." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh An error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << error_handler << "& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a standard output stream with a " << + "Xerces-C++ DOM" << endl + << " * error handler." << endl + << " *" << endl + << " * @param os A standrad output stream." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (::std::ostream& os," << endl + << "const " << type_name (e) << "& x, " << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to xercesc::XMLFormatTarget." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function uses exceptions to report " << + "serialization errors." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target " << + "with an error" << endl + << " * handler." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh An error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << error_handler << "& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a Xerces-C++ XML format target " << + "with a" << endl + << " * Xerces-C++ DOM error handler." << endl + << " *" << endl + << " * @param ft A Xerces-C++ XML format target." << endl + << " * @param x An object model to serialize." << endl + << " * @param eh A Xerces-C++ DOM error handler." << endl + << " * @param m A namespace information map." << endl + << " * @param e A character encoding to produce XML in." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * This function reports serialization errors by " << + "calling the error" << endl + << " * handler." << endl + << " */" << endl; + } + + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl + << "const " << type_name (e) << "& x, " << endl + << xerces_ns << "::DOMErrorHandler& eh," << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to an existing xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to an existing Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param d A Xerces-C++ DOM document." << endl + << " * @param x An object model to serialize." << endl + << " * @param f Serialization flags." << endl + << " *" << endl + << " * Note that it is your responsibility to create the " << + "DOM document" << endl + << " * with the correct root element as well as set the " << + "necessary" << endl + << " * namespace mapping attributes." << endl + << " */" << endl; + } + os << inst_exp + << "void" << endl + << name << " (" << xerces_ns << "::DOMDocument& d," << endl + << "const " << type_name (e) << "& x," << endl + << flags_type << " f = 0);" + << endl; + + if (!doxygen) + { + os << "// Serialize to a new xercesc::DOMDocument." << endl + << "//" << endl + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Serialize to a new Xerces-C++ DOM document." << endl + << " *" << endl + << " * @param x An object model to serialize." << endl + << " * @param m A namespace information map." << endl + << " * @param f Serialization flags." << endl + << " * @return A pointer to the new Xerces-C++ DOM document." << endl + << " */" << endl; + } + + os << inst_exp + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument >" << endl + << name << " (const " << type_name (e) << "& x, " << endl + << "const " << namespace_infomap << "& m = " << + namespace_infomap << " ()," << endl + << flags_type << " f = 0);" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + + } + + Void + generate_serialization_header (Context& ctx) + { + Boolean elemen_type (ctx.options.value<CLI::generate_element_type> ()); + + if (!elemen_type) + ctx.os << "#include <iosfwd>" << endl + << endl + << "#include <xercesc/dom/DOMDocument.hpp>" << endl + << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl + << "#include <xercesc/framework/XMLFormatter.hpp>" << endl + << endl + << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + ElementType element_type (ctx); + ElementFunction element_function (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (elemen_type) + names >> element_type; + else + names >> element_function; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/serialization-header.hxx b/xsd/xsd/cxx/tree/serialization-header.hxx new file mode 100644 index 0000000..86c6b6a --- /dev/null +++ b/xsd/xsd/cxx/tree/serialization-header.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/serialization-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_SERIALIZATION_HEADER_HXX +#define CXX_TREE_SERIALIZATION_HEADER_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_serialization_header (Context&); + } +} + +#endif // CXX_TREE_SERIALIZATION_HEADER_HXX diff --git a/xsd/xsd/cxx/tree/serialization-source.cxx b/xsd/xsd/cxx/tree/serialization-source.cxx new file mode 100644 index 0000000..40ae031 --- /dev/null +++ b/xsd/xsd/cxx/tree/serialization-source.cxx @@ -0,0 +1,1336 @@ +// file : xsd/cxx/tree/serialization-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/serialization-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + enum schema_type + { + st_other, + st_double, + st_decimal + }; + + enum schema_type + schema_type (SemanticGraph::Type& t) + { + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + return st_double; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + return st_decimal; + else + return st_other; + } + + + // + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const " << base << "& > (i);" + << "}"; + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr& a, " << + "const " << name << "& i)" + << "{" + << "a << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "& l," << endl + << "const " << name << "& i)" + << "{" + << "l << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + String ns (e.qualified_p () ? e.namespace_ ().name () : ""); + String type (scope + L"::" + etype (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + os << "// " << comment (e.name ()) << endl + << "//" << endl; + + // aCC cannot handle an inline call to type_serializer_map_instance. + // + if (poly) + { + os << "{" + << "::xsd::cxx::tree::type_serializer_map< " << char_type + << " >& tsm (" << endl + << "::xsd::cxx::tree::type_serializer_map_instance< 0, " << + char_type << " > ());" + << endl; + } + + if (max (e) != 1) + { + // sequence + // + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{"; + + if (poly) + { + os << "if (typeid (" << type << ") == typeid (*b))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << *b;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, *b);"; + } + else + { + os << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << *b;"; + break; + } + case st_double: + { + os << "s << " << as_double_type << " (*b);"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << " (*b);"; + break; + } + } + } + + os << "}"; + } + else if (min (e) == 0) + { + // optional + // + os << "if (i." << aname << " ())" + << "{"; + + if (poly) + { + os << "const " << type << "& x (*i." << aname << " ());" + << "if (typeid (" << type << ") == typeid (x))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << x;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, x);"; + } + else + { + os << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << *i." << aname << " ();"; + break; + } + case st_double: + { + os << "s << " << as_double_type << "(*i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << "(*i." << aname << " ());"; + break; + } + } + } + + os << "}"; + } + else + { + // one + // + if (poly) + { + os << "const " << type << "& x (i." << aname << " ());" + << "if (typeid (" << type << ") == typeid (x))" + << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl + << "s << x;" + << "}" + << "else" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", e, x);"; + } + else + { + os << "{" + << xerces_ns << "::DOMElement& s (" << endl + << "::xsd::cxx::xml::dom::create_element (" << endl + << strlit (e.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (t)) + { + case st_other: + { + os << "s << i." << aname << " ();"; + break; + } + case st_double: + { + os << "s << " << as_double_type << "(i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "s << " << as_decimal_type << "(i." << aname << " ());"; + break; + } + } + + os << "}"; + } + } + + if (poly) + os << "}"; + } + + private: + String scope; + }; + + struct Any: Traversal::Any, Context + { + Any (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + + os << "// " << ename (a) << endl + << "//" << endl; + + if (max (a) != 1) + { + // sequence + // + os << "for (" << scope << "::" << econst_iterator (a) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{" + << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << + "::DOMElement* > (&(*b)), true));" + << "}"; + } + else if (min (a) == 0) + { + // optional + // + os << "if (i." << aname << " ())" + << "{" + << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." << + aname << " ())), true));" + << "}"; + } + else + { + // one + // + os << "e.appendChild (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." << + aname << " ())), true));" + << endl; + } + } + + private: + String scope; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + String ns (a.qualified_p () ? a.namespace_ ().name () : ""); + + os << "// " << comment (a.name ()) << endl + << "//" << endl; + + if (a.optional_p () && !a.default_p ()) + { + os << "if (i." << aname << " ())" + << "{" + << xerces_ns << "::DOMAttr& a (" << endl + << "::xsd::cxx::xml::dom::create_attribute (" << endl + << strlit (a.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (a.type ())) + { + case st_other: + { + os << "a << *i." << aname << " ();"; + break; + } + case st_double: + { + os << "a << " << as_double_type << "(*i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "a << " << as_decimal_type << "(*i." << aname << " ());"; + break; + } + } + + os << "}"; + } + else + { + // Make sure we serialize required fixed attributes. + // + if (a.optional_p () && + options.value<CLI::omit_default_attributes> ()) + { + os << "if (i." << aname << " () != " << scope << + "::" << edefault_value (a) << " ())"; + } + + os << "{" + << xerces_ns << "::DOMAttr& a (" << endl + << "::xsd::cxx::xml::dom::create_attribute (" << endl + << strlit (a.name ()) << "," << endl + << (ns ? strlit (ns) + L",\n" : L"") + << "e));" + << endl; + + switch (schema_type (a.type ())) + { + case st_other: + { + os << "a << i." << aname << " ();"; + break; + } + case st_double: + { + os << "a << " << as_double_type << "(i." << aname << " ());"; + break; + } + case st_decimal: + { + os << "a << " << as_decimal_type << "(i." << aname << " ());"; + break; + } + } + + os << "}"; + } + } + + private: + String scope; + }; + + struct AnyAttribute: Traversal::AnyAttribute, Context + { + AnyAttribute (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + + os << "// " << ename (a) << endl + << "//" << endl; + + os << "for (" << scope << "::" << econst_iterator (a) << endl + << "b (i." << aname << " ().begin ()), " << + "n (i." << aname << " ().end ());" << endl + << "b != n; ++b)" + << "{" + << xerces_ns << "::DOMAttr* a (" << endl + << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl + << "e.getOwnerDocument ()->importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));" + << endl + << "if (a->getLocalName () == 0)" << endl + << "e.setAttributeNode (a);" + << "else" << endl + << "e.setAttributeNodeNS (a);" + << "}"; + } + + private: + String scope; + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{"; + + if (c.inherits_p ()) + { + os << "e << static_cast< const "; + inherits (c, inherits_); + os << "& > (i);" + << endl; + } + else + os << "e << static_cast< const " << any_type << "& > (i);" + << endl; + + // Serialize anyAttribute content first so that is gets + // overriden by schema-defined attributes. + // + if (options.value<CLI::generate_wildcard> ()) + { + AnyAttribute any_attribute (*this, name); + Traversal::Names names (any_attribute); + + Complex::names (c, names); + } + + { + Traversal::Names names; + Any any (*this, name); + Element element (*this, name); + Attribute attribute (*this, name); + + names >> element; + names >> attribute; + + if (options.value<CLI::generate_wildcard> ()) + names >> any; + + Complex::names (c, names); + } + + os << "}"; + + + Boolean simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + Boolean hb (c.inherits_p ()); + + // operator<< (xercesc::DOMAttr) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMAttr&" << + (hb ? " a" : "") << ", " << + "const " << name << "&" << (hb ? " i" : "") << ")" + << "{"; + + if (hb) + { + os << "a << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);"; + } + + os << "}"; + + + // operator<< (list_stream) + // + os << "void" << endl + << "operator<< (" << list_stream_type << "&" << + (hb ? " l" : "") << "," << endl + << "const " << name << "&" << (hb ? " i" : "") << ")" + << "{"; + + if (hb) + { + os << "l << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);"; + } + + os << "}"; + } + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_serializer_init (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + + + // Generate substitution group map entry. + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c), type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual Void + traverse (Type& e) + { + if (polymorphic && e.substitutes_p ()) + { + Type& r (e.substitutes ().root ()); + + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::element_serializer_initializer< 0, " << + char_type << ", "; + + belongs (e, belongs_); + + os << " >" << endl + << "_xsd_" << name << "_element_serializer_init (" << endl + << strlit (r.name ()) << "," << endl + << strlit (r.namespace_ ().name ()) << "," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_ ().name ()) << ");" + << endl + << endl; + } + } + + private: + Traversal::Belongs belongs_; + MemberTypeName type_name_; + + }; + + struct ElementType: Traversal::Element, + GlobalElementBase, + Context + { + ElementType (Context& c) + : GlobalElementBase (c), + Context (c), + element_map_ (c.options.value<CLI::generate_element_map> ()) + { + } + + virtual Void + traverse (Type& e) + { + if (doc_root_p (e)) + { + String const& name (ename (e)); + + // operator<< (xercesc::DOMElement) + // + os << "void" << endl + << "operator<< (" << xerces_ns << "::DOMElement& e, " << + "const " << name << "& i)" + << "{" + << "e << i." << eaname (e) << " ();" + << "}"; + + // Element map registration. + // + if (element_map_) + { + SemanticGraph::Context& ec (e.context ()); + String const& aname (ec.get<String> ("element-name")); + String const& ans (ec.get<String> ("element-ns")); + + os << "static " << endl + << "const ::xsd::cxx::tree::serializer_init< " << + name << ", " << char_type << ", " << any_type << " >" << endl + << "_xsd_" << name << "_serializer_init (" << + name << "::" << aname << " (), " << + name << "::" << ans << " ());" + << endl; + } + } + } + + private: + Boolean element_map_; + }; + + struct ElementFunction: Traversal::Element, + GlobalElementBase, + Context + { + ElementFunction (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + String const& name (eserializer (e)); + String ns (e.namespace_ ().name ()); + String const& error_handler (error_handler_type); + String const& namespace_infomap (namespace_infomap_type); + + SemanticGraph::Type& type (e.type ()); + + // Note that I am using fq-name in function calls because g++ gets + // confused if the name is 'type'. (see tests/schema/anonymous) + // + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. + // + Boolean poly (polymorphic && + polymorphic_p (type) && + !anonymous_p (type)); + + // To std::ostream. + // + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << + char_type << " > > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << error_handler << "& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << "::xsd::cxx::xml::auto_initializer i (" << endl + << "(f & " << flags_type << "::dont_initialize) == 0);" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (::std::ostream& o," << endl + << "const " << type_name (e) << "& s," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "::xsd::cxx::xml::dom::ostream_format_target t (o);" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + // To XMLFormatTarget. + // + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << endl + << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" + << endl + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << + char_type << " > > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << error_handler << "& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + os << "void" << endl + << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl + << "const " << type_name (e) << "& s," << endl + << xerces_ns << "::DOMErrorHandler& h," << endl + << "const " << namespace_infomap << "& m," << endl + << "const " << string_type << "& e," << endl + << flags_type << " f)" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << fq_name (e, "serializer") << " (s, m, f));" + << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" + << "{" + << "throw ::xsd::cxx::tree::serialization< " << + char_type << " > ();" + << "}" + << "}"; + + // To an existing DOM instance. + // + os << "void" << endl + << name << " (" << xerces_ns << "::DOMDocument& d," << endl + << "const " << type_name (e) << "& s," << endl + << flags_type << ")" + << "{" + << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl; + + if (poly) + { + os << "if (typeid (" << type_name (e) << ") == typeid (s))" + << "{"; + } + + os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl + << "n.namespace_ () == " << strlit (ns) << ")" + << "{"; + + switch (schema_type (type)) + { + case st_other: + { + os << "e << s;"; + break; + } + case st_double: + { + os << "e << " << as_double_type << "(s);"; + break; + } + case st_decimal: + { + os << "e << " << as_decimal_type << "(s);"; + break; + } + } + + os << "}" + << "else" + << "{" + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name ()," << endl + << "n.namespace_ ()," << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << ");" + << "}"; + + if (poly) + { + // aCC cannot handle an inline call to + // type_serializer_map_instance. + // + os << "}" + << "else" + << "{" + << "::xsd::cxx::tree::type_serializer_map< " << char_type + << " >& tsm (" << endl + << "::xsd::cxx::tree::type_serializer_map_instance< 0, " << + char_type << " > ());" + << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "e, n, s);" + << "}"; + } + + os << "}"; + + + // To a new DOM instance. + // + os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl + << name << " (const " << type_name (e) << "& s," << endl + << "const " << namespace_infomap << "& m," << endl + << flags_type << " f)" + << "{"; + + if (poly) + { + // aCC cannot handle an inline call to + // type_serializer_map_instance as well as the direct + // auto_ptr assignment. + // + os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;" + << endl + << "if (typeid (" << type_name (e) << ") == typeid (s))" + << "{" + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > r (" << endl + << "::xsd::cxx::xml::dom::serialize< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << "m, f));" + << "d = r;" + << "}" + << "else" + << "{" + << "::xsd::cxx::tree::type_serializer_map< " << char_type + << " >& tsm (" << endl + << "::xsd::cxx::tree::type_serializer_map_instance< 0, " << + char_type << " > ());" + << endl + << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > r (" << endl + << "tsm.serialize (" << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_().name ()) << "," << endl + << "m, s, f));" + << "d = r;" + << "}"; + } + else + { + os << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > d (" << endl + << "::xsd::cxx::xml::dom::serialize< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << strlit (ns) << "," << endl + << "m, f));" + << endl; + } + + os << fq_name (e, "serializer") << " (*d, s, f);" + << "return d;" + << "}"; + + } + + private: + String + type_name (Type& e) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (e.type ()); + + return o.str (); + } + }; + } + + Void + generate_serialization_source (Context& ctx, + UnsignedLong first, + UnsignedLong last) + { + Boolean elemen_type (ctx.options.value<CLI::generate_element_type> ()); + + if (!elemen_type) + ctx.os << "#include <ostream>" << endl + << "#include <xsd/cxx/tree/error-handler.hxx>" << endl; + + ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl + << endl; + + if (ctx.polymorphic) + { + ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl + << endl; + + Boolean import_maps (ctx.options.value<CLI::import_maps> ()); + Boolean export_maps (ctx.options.value<CLI::export_maps> ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "type_serializer_plate< 0, " << ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "type_serializer_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "type_serializer_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "type_serializer_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{" + << "static" << endl + << "const ::xsd::cxx::tree::type_serializer_plate< 0, " << + ctx.char_type << " >" << endl + << "type_serializer_plate_init;" + << "}"; + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + ElementType element_type (ctx); + ElementFunction element_function (ctx); + + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + names >> element; + + if (elemen_type) + names >> element_type; + else + names >> element_function; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/serialization-source.hxx b/xsd/xsd/cxx/tree/serialization-source.hxx new file mode 100644 index 0000000..322949a --- /dev/null +++ b/xsd/xsd/cxx/tree/serialization-source.hxx @@ -0,0 +1,22 @@ +// file : xsd/cxx/tree/serialization-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_SERIALIZATION_SOURCE_HXX +#define CXX_TREE_SERIALIZATION_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_serialization_source (Context&, + UnsignedLong first, + UnsignedLong last); + } +} + +#endif // CXX_TREE_SERIALIZATION_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/xsd/cxx/tree/stream-extraction-source.cxx new file mode 100644 index 0000000..1378bc6 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-extraction-source.cxx @@ -0,0 +1,763 @@ +// file : xsd/cxx/tree/stream-extraction-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/stream-extraction-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + typedef Containers::Vector<NarrowString> Streams; + + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (s, f, c)," << endl + << " " << base << " (s, f, this)" + << "{" + << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, f, c)" + << "{" + << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": "; + + inherits (e, inherits_base_); + + os << " (s, f, c)" + << "{"; + + if (string_based) + os << "_xsd_" << name << "_convert ();"; + + os << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct CtorMember: Traversal::Member, Context + { + CtorMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + os << "," << endl + << " " << emember (m) << " (f, this)"; + } + }; + + struct CtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CtorAny (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& stream_) + : Context (c), stream (stream_) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + SemanticGraph::Type& t (e.type ()); + String type (etype (e)); + + Boolean fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (t); + } + + // Figure out if we need to generate polymorphic code. If this + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. + // + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (max (e) != 1) + { + // sequence + // + String container (econtainer (e)); + + os << "{" + << "::std::size_t n;" + << "::xsd::cxx::tree::istream_common::as_size< " << + "::std::size_t > as (n);" + << "s >> as;" + << "if (n > 0)" + << "{" + << container << "& c (this->" << member << ");" + << "c.reserve (n);" + << "while (n--)" + << "{"; + + if (poly) + { + os << "bool d;" + << "::std::auto_ptr< " << type << " > r;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{" + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " << + stream << ", " << char_type << " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (new " << type << + " (s, f, this));"; + } + + os << "c.push_back (r);" + << "}" // while + << "}" // if + << "}"; + } + else if (min (e) == 0) + { + // optional + // + os << "{" + << "bool p;" + << "s >> p;" + << "if (p)" + << "{"; + + if (poly) + { + os << "bool d;" + << "::std::auto_ptr< " << type << " > r;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{" + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " << + stream << ", " << char_type << " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (new " << type << + " (s, f, this));"; + } + + os << "this->" << member << ".set (r);" + << "}" // if (p) + << "}"; + } + else + { + // one + // + os << "{"; + + if (poly) + { + os << "bool d;" + << "::std::auto_ptr< " << type << " > r;" + << "s >> d;" + << endl + << "if (!d)" << endl + << "r.reset (new " << type << " (s, f, this));" + << "else" + << "{" + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " << + stream << ", " << char_type << " > ().extract (" << endl + << "s, f, this));" + << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));" + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << "}"; + } + else if (fund) + { + os << type << " r;" + << "s >> r;"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (new " << type << + " (s, f, this));"; + } + + os << "this->" << member << ".set (r);" + << "}"; + } + } + + private: + String stream; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& member (emember (a)); + String type (etype (a)); + + Boolean fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (a.type ()); + } + + if (a.optional_p () && !a.default_p ()) + { + os << "{" + << "bool p;" + << "s >> p;" + << "if (p)" + << "{"; + + if (fund) + { + os << type << " r;" + << "s >> r;" + << "this->" << member << ".set (r);"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (new " << type << + " (s, f, this));" + << "this->" << member << ".set (r);"; + } + + os << "}" // if (p) + << "}"; + } + else + { + os << "{"; + + if (fund) + { + os << type << " r;" + << "s >> r;" + << "this->" << member << ".set (r);"; + } + else + { + os << "::std::auto_ptr< " << type << " > r (new " << type << + " (s, f, this));" + << "this->" << member << ".set (r);"; + } + + os << "}"; + } + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c), ctor_any_ (c), ctor_member_ (c) + { + inherits_ >> base_; + names_ctor_member_ >> ctor_member_; + + if (options.value<CLI::generate_wildcard> ()) + names_ctor_member_ >> ctor_any_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + Boolean has_members (has<Traversal::Member> (c)); + + Boolean facets (false); + if (c.inherits_p ()) + { + // See if we have any facets that we need to handle. + // + using SemanticGraph::Restricts; + using SemanticGraph::Fundamental::Decimal; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty () && + (r->facet_find ("fractionDigits") != r->facet_end () || + r->facet_find ("totalDigits") != r->facet_end ()) && + ultimate_base (c).is_a<Decimal> ()) + facets = true; + } + } + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + + os << name << "::" << endl + << name << " (" << istream_type << "< " << + i->c_str () << " >& s," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": "; + + if (c.inherits_p ()) + inherits (c, inherits_); + else + os << any_type; + + os << " (s, f, c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, names_ctor_member_); + + os << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);" + << endl; + + if (has_members) + os << "this->" << unclash (name, "parse") << " (s, f);"; + + os << "}"; + + // Parse + // + if (has_members) + { + os << "void " << name << "::" << endl + << unclash (name, "parse") << " (" << + istream_type << "< " << i->c_str () << " >& s," << endl + << flags_type << " f)" + << "{"; + { + Element element (*this, *i); + Attribute attribute (*this); + Traversal::Names names_; + + names_ >> element; + names_ >> attribute; + + names (c, names_); + } + + os << "}"; + } + + + // Register with type map. + // + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_extraction_init_" << + n++ << " (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + + CtorAny ctor_any_; + CtorMember ctor_member_; + + Traversal::Names names_ctor_member_; + }; + } + + Void + generate_stream_extraction_source (Context& ctx) + { + if (ctx.polymorphic) + { + Streams const& st (ctx.options.value<CLI::generate_extraction> ()); + + ctx.os << "#include <xsd/cxx/tree/stream-extraction-map.hxx>" << endl + << endl; + + Boolean import_maps (ctx.options.value<CLI::import_maps> ()); + Boolean export_maps (ctx.options.value<CLI::export_maps> ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{"; + + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream (*i); + + ctx.os << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "stream_extraction_plate< 0, " << stream << ", " << + ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "stream_extraction_plate< 0, " << stream << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "stream_extraction_plate< 0, " << stream << ", " << + ctx.char_type << " >;" + << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "stream_extraction_plate< 0, " << stream << ", " << + ctx.char_type << " >;" + << "#endif" << endl; + } + + ctx.os << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + + } + + ctx.os << "namespace _xsd" + << "{"; + + UnsignedLong n (0); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream (*i); + + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::stream_extraction_plate< 0, " << + stream << ", " << ctx.char_type << " >" << endl + << "stream_extraction_plate_init_" << n++ << ";"; + } + + ctx.os << "}"; + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/stream-extraction-source.hxx b/xsd/xsd/cxx/tree/stream-extraction-source.hxx new file mode 100644 index 0000000..23ab17c --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-extraction-source.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/stream-extraction-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_EXTRACTION_SOURCE_HXX +#define CXX_TREE_EXTRACTION_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_stream_extraction_source (Context&); + } +} + +#endif // CXX_TREE_EXTRACTION_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/stream-header.cxx b/xsd/xsd/cxx/tree/stream-header.cxx new file mode 100644 index 0000000..02e2651 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-header.cxx @@ -0,0 +1,183 @@ +// file : xsd/cxx/tree/stream-header.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/stream-header.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + Boolean enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + // If we are based on an enum then the value type is just an + // alias and we don't need to generate this operator again. + // + if (string_based && !enum_based) + { + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, " << + name << "::" << evalue (e) << ");" + << endl; + } + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + os << inst_exp + << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "&, const " << + name << "&);" + << endl; + } + }; + } + + Void + generate_stream_header (Context& ctx) + { + String c (ctx.char_type); + + ctx.os << "#include <iosfwd>" << endl + << endl; + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/stream-header.hxx b/xsd/xsd/cxx/tree/stream-header.hxx new file mode 100644 index 0000000..246a06e --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-header.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/stream-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_STREAM_HEADER_HXX +#define CXX_TREE_STREAM_HEADER_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_stream_header (Context&); + } +} + +#endif // CXX_TREE_STREAM_HEADER_HXX diff --git a/xsd/xsd/cxx/tree/stream-insertion-header.cxx b/xsd/xsd/cxx/tree/stream-insertion-header.cxx new file mode 100644 index 0000000..1669fdd --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-insertion-header.cxx @@ -0,0 +1,178 @@ +// file : xsd/cxx/tree/stream-insertion-header.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/stream-insertion-header.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + typedef Containers::Vector<NarrowString> Streams; + + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type (ostream_type + L"< " + String (*i) + L" >"); + + os << inst_exp + << stream_type << "&" << endl + << "operator<< (" << stream_type << "&," << endl + << "const " << name << "&);" + << endl; + } + } + }; + } + + Void + generate_stream_insertion_header (Context& ctx) + { + String c (ctx.char_type); + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/stream-insertion-header.hxx b/xsd/xsd/cxx/tree/stream-insertion-header.hxx new file mode 100644 index 0000000..ca93713 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-insertion-header.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/stream-insertion-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_STREAM_INSERTION_HEADER_HXX +#define CXX_TREE_STREAM_INSERTION_HEADER_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_stream_insertion_header (Context&); + } +} + +#endif // CXX_TREE_STREAM_INSERTION_HEADER_HXX diff --git a/xsd/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/xsd/cxx/tree/stream-insertion-source.cxx new file mode 100644 index 0000000..09faf71 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-insertion-source.cxx @@ -0,0 +1,534 @@ +// file : xsd/cxx/tree/stream-insertion-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/stream-insertion-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + typedef Containers::Vector<NarrowString> Streams; + + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{" + << "return s << static_cast< const " << base << "& > (x);" + << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + } + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{" + << "return s << static_cast< const " << base << "& > (x);" + << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + } + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "& x)" + << "{" + << "return s << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (x);" + << "}"; + + // Register with type map. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_, String const& stream_) + : Context (c), scope (scope_), stream (stream_) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) return; + + String const& aname (eaname (e)); + SemanticGraph::Type& t (e.type ()); + String type (scope + L"::" + etype (e)); + + // Figure out if we need to generate polymorphic code. If this + // elemen's type is anonymous then we don't need to do anything. + // Note that if the type is anonymous then it can't be derived + // from which makes it impossible to substitute or dynamically- + // type with xsi:type. + // + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (max (e) != 1) + { + // sequence + // + os << "{" + << "const " << scope << "::" << econtainer (e) << "& c (" << + "x." << aname << " ());" + << "s << ::xsd::cxx::tree::ostream_common::as_size< " << + "::std::size_t > (c.size ());"; + + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "i (c.begin ()), e (c.end ());" << endl + << "i != e; ++i)" + << "{"; + + if (poly) + { + os << "bool d (typeid (" << type << ") != typeid (*i));" + << "s << d;" + << "if (!d)" << endl + << "s << *i;" + << "else" << endl + << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " << + stream << ", " << char_type << " > ().insert (s, *i);"; + } + else + os << "s << *i;"; + + os << "}" // for + << "}"; + } + else if (min (e) == 0) + { + // optional + // + os << "{" + << "bool p (x." << aname << " ());" + << "s << p;" + << "if (p)"; + + if (poly) + { + os << "{" + << "const " << type << "& i (*x." << aname << " ());" + << "bool d (typeid (" << type << ") != typeid (i));" + << "s << d;" + << "if (!d)" << endl + << "s << i;" + << "else" << endl + << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " << + stream << ", " << char_type << " > ().insert (s, i);" + << "}"; + } + else + os << endl + << "s << *x." << aname << " ();"; + + os << "}"; + } + else + { + // one + // + if (poly) + { + os << "{" + << "const " << type << "& i (x." << aname << " ());" + << "bool d (typeid (" << type << ") != typeid (i));" + << "s << d;" + << "if (!d)" << endl + << "s << i;" + << "else" << endl + << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " << + stream << ", " << char_type << " > ().insert (s, i);" + << "}"; + } + else + os << "s << x." << aname << " ();"; + } + } + + private: + String scope; + String stream; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + + if (a.optional_p () && !a.default_p ()) + { + os << "{" + << "bool p (x." << aname << " ());" + << "s << p;" + << "if (p)" << endl + << "s << *x." << aname << " ();" + << "}"; + } + else + { + os << "s << x." << aname << " ();"; + } + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + Boolean has_body (has<Traversal::Member> (c) || c.inherits_p ()); + + UnsignedLong n (0); + Streams const& st (options.value<CLI::generate_insertion> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >"); + + os << stream_type << "&" << endl + << "operator<< (" << stream_type << "& s," << endl + << "const " << name << "&" << (has_body ? " x" : "") << ")" + << "{"; + + if (c.inherits_p ()) + { + os << "s << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (x);"; + } + + { + Traversal::Names names_member; + Element element (*this, name, *i); + Attribute attribute (*this); + + names_member >> element; + names_member >> attribute; + + names (c, names_member); + } + + os << "return s;" + << "}"; + + + // Register with type map. + // + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_initializer< " << + "0, " << i->c_str () << ", " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_stream_insertion_init_" << + n++ << " (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + } + + Void + generate_stream_insertion_source (Context& ctx) + { + if (ctx.polymorphic) + { + Streams const& st (ctx.options.value<CLI::generate_insertion> ()); + + ctx.os << "#include <xsd/cxx/tree/stream-insertion-map.hxx>" << endl + << endl; + + Boolean import_maps (ctx.options.value<CLI::import_maps> ()); + Boolean export_maps (ctx.options.value<CLI::export_maps> ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{"; + + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream (*i); + + ctx.os << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "stream_insertion_plate< 0, " << stream << ", " << + ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "stream_insertion_plate< 0, " << stream << ", " << + ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "stream_insertion_plate< 0, " << stream << ", " << + ctx.char_type << " >;" + << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "stream_insertion_plate< 0, " << stream << ", " << + ctx.char_type << " >;" + << "#endif" << endl; + } + + ctx.os << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{"; + + UnsignedLong n (0); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream (*i); + + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::stream_insertion_plate< 0, " << + stream << ", " << ctx.char_type << " >" << endl + << "stream_insertion_plate_init_" << n++ << ";"; + } + + ctx.os << "}"; + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/stream-insertion-source.hxx b/xsd/xsd/cxx/tree/stream-insertion-source.hxx new file mode 100644 index 0000000..b270912 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-insertion-source.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/stream-insertion-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_INSERTION_SOURCE_HXX +#define CXX_TREE_INSERTION_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_stream_insertion_source (Context&); + } +} + +#endif // CXX_TREE_INSERTION_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/stream-source.cxx b/xsd/xsd/cxx/tree/stream-source.cxx new file mode 100644 index 0000000..e8a7fc4 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-source.cxx @@ -0,0 +1,489 @@ +// file : xsd/cxx/tree/stream-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/stream-source.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const " << base << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const " << xs_string_type << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), base_ (c) + { + inherits_base_ >> base_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + Boolean enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + // If we are based on an enum then the value type is just an + // alias and we don't need to generate this operator again. + // + if (string_based && !enum_based) + { + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + name << "::" << evalue (e) << " i)" + << "{" + << "return o << " << name << "::_xsd_" << name << + "_literals_[i];" + << "}"; + } + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "& i)" + << "{" + << "return o << static_cast< const "; + + inherits (e, inherits_base_); + + os << "& > (i);" + << "}"; + + // Register with ostream map. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element: Traversal::Element, Context + { + Element (Context& c, String const& scope_) + : Context (c), scope (scope_) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + // aCC cannot handle an inline call to std_ostream_map_instance. + // + if (poly) + { + os << "{" + << "::xsd::cxx::tree::std_ostream_map< " << char_type + << " >& om (" << endl + << "::xsd::cxx::tree::std_ostream_map_instance< 0, " << + char_type << " > ());" + << endl; + } + + if (max (e) != 1) + { + // sequence + // + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "b (i." << aname << " ().begin ()), " << + "e (i." << aname << " ().end ());" << endl + << "b != e; ++b)" + << "{" + << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << *b;"; + else + os << ";" + << "om.insert (o, *b);"; + + os << "}"; + } + else if (min (e) == 0) + { + // optional + // + + os << "if (i." << aname << " ())" + << "{" + << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << *i." << aname << " ();"; + else + os << ";" + << "om.insert (o, *i." << aname << " ());"; + + os << "}"; + } + else + { + // one + // + os << "o << ::std::endl << " << strlit (e.name () + L": "); + + if (!poly) + os << " << i." << aname << " ();"; + else + os << ";" + << "om.insert (o, i." << aname << " ());"; + } + + if (poly) + os << "}"; + } + + private: + String scope; + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + + if (a.optional_p () && !a.default_p ()) + { + os << "if (i." << aname << " ())" + << "{" + << "o << ::std::endl << " << strlit (a.name () + L": ") << + " << *i." << aname << " ();" + << "}"; + } + else + { + os << "o << ::std::endl << " << strlit (a.name () + L": ") << + " << i." << aname << " ();"; + } + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), base_ (c) + { + inherits_ >> base_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + // + // + Boolean has_body (has<Traversal::Member> (c) || c.inherits_p ()); + + os << std_ostream_type << "&" << endl + << "operator<< (" << std_ostream_type << "& o, " << + "const " << name << "&" << (has_body ? " i" : "") << ")" + << "{"; + + if (c.inherits_p ()) + { + os << "o << static_cast< const "; + + inherits (c, inherits_); + + os << "& > (i);" + << endl; + } + + { + Traversal::Names names_member; + Element element (*this, name); + Attribute attribute (*this); + + names_member >> element; + names_member >> attribute; + + names (c, names_member); + } + + os << "return o;" + << "}"; + + // Register with ostream map. + // + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + os << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_std_ostream_init;" + << endl; + } + } + + private: + Traversal::Inherits inherits_; + BaseTypeName base_; + }; + } + + Void + generate_stream_source (Context& ctx, + UnsignedLong first, + UnsignedLong last) + { + String c (ctx.char_type); + + ctx.os << "#include <ostream>" << endl + << endl; + + if (ctx.polymorphic) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-map.hxx>" << endl + << endl; + + Boolean import_maps (ctx.options.value<CLI::import_maps> ()); + Boolean export_maps (ctx.options.value<CLI::export_maps> ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "std_ostream_plate< 0, " << ctx.char_type << " >;"; + + if (import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "std_ostream_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl + << "template struct __attribute__ ((visibility(\"default\"))) " << + "std_ostream_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl + << "template struct XSD_MAP_VISIBILITY " << + "std_ostream_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{" + << "static" << endl + << "const ::xsd::cxx::tree::std_ostream_plate< 0, " << + ctx.char_type << " >" << endl + << "std_ostream_plate_init;" + << "}"; + } + + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/stream-source.hxx b/xsd/xsd/cxx/tree/stream-source.hxx new file mode 100644 index 0000000..13e8f37 --- /dev/null +++ b/xsd/xsd/cxx/tree/stream-source.hxx @@ -0,0 +1,22 @@ +// file : xsd/cxx/tree/stream-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_STREAM_SOURCE_HXX +#define CXX_TREE_STREAM_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_stream_source (Context&, + UnsignedLong first, + UnsignedLong last); + } +} + +#endif // CXX_TREE_STREAM_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/tree-forward.cxx b/xsd/xsd/cxx/tree/tree-forward.cxx new file mode 100644 index 0000000..214cc75 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-forward.cxx @@ -0,0 +1,327 @@ +// file : xsd/cxx/tree/tree-forward.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/tree-forward.hxx> +#include <cxx/tree/fundamental-header.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String const& name (ename (l)); + + if (String custom = custom_type (l)) + { + String new_name; + renamed_type (l, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String const& name (ename (u)); + + if (String custom = custom_type (u)) + { + String new_name; + renamed_type (u, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + String const& name (ename (e)); + + if (String custom = custom_type (e)) + { + String new_name; + renamed_type (e, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + String const& name (ename (c)); + + if (String custom = custom_type (c)) + { + String new_name; + renamed_type (c, new_name); + + if (new_name) + os << "class " << new_name << ";"; + + if (custom == name) + os << "class " << name << ";"; + else + os << "typedef " << custom << " " << name << ";"; + } + else + os << "class " << name << ";"; + } + }; + } + + Void + generate_forward (Context& ctx) + { + NarrowString xml_schema (ctx.options.value<CLI::extern_xml_schema> ()); + + // Inlcude or Emit fundamental types. + // + if (xml_schema) + { + String name (ctx.hxx_expr->merge (xml_schema)); + + ctx.os << "#include " << ctx.process_include_path (name) << endl + << endl; + } + else + { + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/types.hxx>" << endl + << endl; + + if (!ctx.options.value<CLI::suppress_parsing> () || + ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl + << endl; + } + + if (!ctx.options.value<CLI::suppress_parsing> () || + ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + } + + Boolean element_map (ctx.options.value<CLI::generate_element_map> ()); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl + << endl; + + // I need to include all the "optional" headers here (instead of + // later in the individual generators for each feature because + // those headers provide implementation for the fundamental types. + // + if (!ctx.options.value<CLI::suppress_parsing> ()) + { + ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "parsing"); + + schema >> implies >> xsd >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl + << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "serialization"); + + schema >> implies >> xsd >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.value<CLI::generate_ostream> ()) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl + << endl; + } + + typedef Containers::Vector<NarrowString> Streams; + + Streams const& ist (ctx.options.value<CLI::generate_insertion> ()); + if (!ist.empty ()) + { + for (Streams::ConstIterator i (ist.begin ()); i != ist.end (); ++i) + { + if (*i == "ACE_OutputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl + << endl; + } + + Streams const& est (ctx.options.value<CLI::generate_extraction> ()); + if (!est.empty ()) + { + for (Streams::ConstIterator i (est.begin ()); i != est.end (); ++i) + { + if (*i == "ACE_InputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl + << endl; + } + + + Traversal::Schema schema, xsd; + Traversal::Implies implies; + Traversal::Names names; + FundamentalNamespace ns (ctx); + + schema >> implies >> xsd >> names >> ns; + + schema.dispatch (ctx.schema_root); + } + + // First emit header includes. + // + if (ctx.options.value<CLI::generate_forward> ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::forward); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + ctx.os << "// Forward declarations." << endl + << "//" << endl; + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + schema.dispatch (ctx.schema_root); + + ctx.os << endl; + } + } +} diff --git a/xsd/xsd/cxx/tree/tree-forward.hxx b/xsd/xsd/cxx/tree/tree-forward.hxx new file mode 100644 index 0000000..efe0e02 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-forward.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/tree-forward.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_TREE_FORWARD_HXX +#define CXX_TREE_TREE_FORWARD_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_forward (Context&); + } +} + +#endif // CXX_TREE_TREE_FORWARD_HXX diff --git a/xsd/xsd/cxx/tree/tree-header.cxx b/xsd/xsd/cxx/tree/tree-header.cxx new file mode 100644 index 0000000..9b5acc6 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-header.cxx @@ -0,0 +1,3867 @@ +// file : xsd/cxx/tree/tree-header.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/tree-header.hxx> +#include <cxx/tree/default-value.hxx> +#include <cxx/tree/fundamental-header.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + typedef Containers::Vector<NarrowString> Streams; + + // List mapping. + // + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + if (doxygen) + { + os << "/**" << endl + << " * @brief List class corresponding to the %" << + comment (l.name ()) << endl + << " * schema type." << endl + << " *" << endl + << " * This class has an interface of a standard C++ " << + "sequence (e.g.," << endl + << " * std::vector)." << endl; + + if (l.annotated_p ()) + { + os << " *" << endl; + write_annotation (l.annotation ()); + } + + os << " */" << endl; + } + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String item_name (item_type_name (item_type)); + String base_type (L"::xsd::cxx::tree::list< " + item_name + L", " + + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base_type += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + + base_type += L" >"; + + os << "class " << type_exp << name << + ": public " << any_simple_type << "," << endl + << " public " << base_type + << "{" + << "public:" << endl; + + // c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Creates an empty list." << endl + << " */" << endl; + } + os << name << " ();" + << endl; + + // c-tor (size_type, const X& x) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create a list with copies of the specified " << + "element." << endl + << " *" << endl + << " * @param n A number of elements to copy." << endl + << " * @param x An element to copy." << endl + << " *" << endl + << " * This constructor creates a list with @a n copies " << + "of @a x." << endl + << " */" << endl; + } + + String size_type (name != L"size_type" + ? String (L"size_type") + : base_type + L"::size_type"); + + os << name << " (" << size_type << " n, const " << item_name << + "& x);" + << endl; + + // c-tor (const I& begin, const I& end) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create a list from an iterator range." << endl + << " *" << endl + << " * @param begin An iterator pointing to the first " << + "element." << endl + << " * @param end An iterator pointing to the one past " << + "the last element." << endl + << " *" << endl + << " * This constructor creates a list consisting of " << + "copies of the" << endl + << " * elements in the range [begin,end)." << endl + << " */" << endl; + } + + String iter_type (unclash (name, "I")); + + os << "template < typename " << iter_type << " >" << endl + << name << " (const " << iter_type << "& begin, const " << + iter_type << "& end)" << endl + << ": " << base_type << " (begin, end, this)" + << "{" + << "}"; + + // c-tor (istream&) + // + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();"; + + os << "};"; + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + // Union mapping. + // + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Union class corresponding to the %" << + comment (u.name ()) << endl + << " * schema type." << endl + << " *" << endl + << " * The mapping represents unions as strings." << endl; + + if (u.annotated_p ()) + { + os << " *" << endl; + write_annotation (u.annotation ()); + } + + os << " */" << endl; + } + + os << "class " << type_exp << name << + ": public " << xs_string_type + << "{" + << "public:" << endl + << endl; + + if (options.value<CLI::generate_default_ctor> ()) + { + // c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor may leave the " << + "instance in an" << endl + << " * invalid state." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (const char*) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + os << name << " (const " << char_type << "* v);" + << endl; + + // c-tor (string const&) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + os << name << " (const " << string_type << "& v);" + << endl; + + // c-tor (istream&) + // + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor () + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + os << "};"; + } + }; + + // Enum mapping. + // + struct Enumerator: Traversal::Enumerator, Context + { + Enumerator (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (doxygen && e.annotated_p ()) + { + os << "/**" << endl; + write_annotation (e.annotation ()); + os << " */" << endl; + } + + os << ename (e); + } + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), + base_ (c), + member_ (c), + enumerator_ (c) + { + inherits_base_ >> base_; + inherits_member_ >> member_; + + names_ >> enumerator_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + Boolean enum_based (false); + SemanticGraph::Enumeration* base_enum (0); + + if (string_based) + { + IsEnumBasedType t (base_enum); + t.dispatch (e); + + if (base_enum != 0) + enum_based = true; + } + + String value; + if (string_based) + value = evalue (e); + + // Get to the ultimate base and see if is a fundamental type. + // + Boolean fund_based (false); + SemanticGraph::Type& ult_base (ultimate_base (e)); + { + IsFundamentalType t (fund_based); + t.dispatch (ult_base); + } + + // Count enumerators. + // + UnsignedLong enum_count (0); + + for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); + i != end; ++i) + ++enum_count; + + // + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Enumeration class corresponding to the %" << + comment (e.name ()) << endl + << " * schema type." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " */" << endl; + } + + os << "class " << type_exp << name << ": public "; + + // Enumeration always has a base. + // + inherits (e, inherits_base_); + + os << "{" + << "public:" << endl; + + if (string_based) + { + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Underlying enum type." << endl + << " */" << endl; + } + + if (enum_based) + { + os << "typedef "; + + inherits (e, inherits_base_); + + os << "::" << evalue (*base_enum) << " " << value << ";" + << endl; + } + else + { + os << "enum " << value + << "{"; + + names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma); + + os << "};"; + } + } + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor may leave the " << + "instance in an" << endl + << " * invalid state." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (value) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "underlying enum value." << endl + << " *" << endl + << " * @param v A enum value." << endl + << " */" << endl; + } + + os << name << " (" << value << " v);" + << endl; + } + + // c-tor (const char*) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + + os << name << " (const " << char_type << "* v);" + << endl; + } + + // c-tor (const std::string&) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string." << endl + << " *" << endl + << " * @param v A string value." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& v);" + << endl; + } + + // c-tor (fundamental) + // + if (fund_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a fundamental " << + "type value." << endl + << " *" << endl + << " * @param v A fundamental type value." << endl + << " */" << endl; + } + + os << name << " ("; + + member_.dispatch (ult_base); + + os << " v);" + << endl; + } + + // c-tor (base) + // + // If the ultimate is also our immediate base and it is a + // fundamental type then this c-tor clashes with c-tor + // (fundamental) above. + // + if (!fund_based || &ult_base != &e.inherits ().base ()) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "base value." << endl + << " *" << endl + << " * @param v A base value." << endl + << " */" << endl; + } + + os << name << " (const "; + + inherits (e, inherits_member_); + + os << "& v);" + << endl; + } + + + // c-tor (istream&) + // + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + // operator= (value) + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Assign the underlying enum value." << endl + << " *" << endl + << " * @param v A enum value." << endl + << " * @return A refernce to the instance." << endl + << " */" << endl; + } + + os << name << "&" << endl + << "operator= (" << value << " v);" + << endl; + } + + // operator value () + // + // Name lookup differences in various compilers make generation + // of this operator outside of the class a really hard task. So + // we are going to make it "always inline". + // + if (string_based) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Implicit conversion operator to the " << + "underlying" << endl + << " * enum value." << endl + << " *" << endl + << " * @return A enum value." << endl + << " */" << endl; + } + + os << "virtual" << endl + << "operator " << value << " () const" + << "{" + << "return _xsd_" << name << "_convert ();" + << "}"; + } + + // + // + if (string_based) + { + if (doxygen) + os << "//@cond" << endl + << endl; + + os << "protected:" << endl + << value << endl + << "_xsd_" << name << "_convert () const;" + << endl; + + os << "public:" << endl; + + if (enum_based) + { + // We are going to reuse our base's literals. + // + os << "static const " << char_type << "* const* " << + "_xsd_" << name << "_literals_;"; + } + else + { + os << "static const " << char_type << "* const " << + "_xsd_" << name << "_literals_[" << enum_count << "];"; + } + + os << "static const " << value << + " _xsd_" << name << "_indexes_[" << enum_count << "];"; + + if (doxygen) + os << endl + << "//@endcond" << endl + << endl; + } + + os << "};"; + } + + virtual Void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + + Traversal::Inherits inherits_member_; + MemberTypeName member_; + + Traversal::Names names_; + Enumerator enumerator_; + }; + + + // + // + struct MemberFunction: Traversal::Member, Context + { + MemberFunction (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& aname (eaname (m)); + String const& mname (emname (m)); + String kind (m.is_a<SemanticGraph::Element> () + ? "element" : "attribute"); + + Boolean fund (false); + { + IsFundamentalType t (fund); + t.dispatch (m.type ()); + } + + Boolean def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + String container (econtainer (m)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the element" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "element sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy elements from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "makes a copy and adds it " << endl + << " * to the sequence. Note that this operation " << + "completely changes the " << endl + << " * sequence and all old elements will be lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + String const& type (etype (m)); + String container (econtainer (m)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the " << kind << endl + << " * container." << endl + << " *" << endl + << " * @return A constant reference to the optional " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + kind << " container." << endl + << " *" << endl + << " * @return A reference to the optional container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the " << kind << "." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x An optional container with the new value " << + "to set." << endl + << " *" << endl + << " * If the value is present in @a x then this function " << + "makes a copy " << endl + << " * of this value and sets it as the new value of the " << + kind << "." << endl + << " * Otherwise the " << kind << " container is set " << + "the 'not present' state." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly instead" << endl + << " * of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (::std::auto_ptr< " << type << " > p);" + << endl; + } + } + else + { + // one + // + String const& type (etype (m)); + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the " << kind << "." << endl + << " *" << endl + << " * @return A constant reference to the " << kind << + "." << endl + << " */" << endl; + } + + os << "const " << type << "&" << endl + << aname << " () const;" + << endl; + + // Do not generate modifiers for fixed attributes. + // + if (!(def_attr && m.fixed_p ())) + { + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + kind << "." << endl + << " *" << endl + << " * @return A reference to the " << kind << "." << endl + << " */" << endl; + } + + os << type << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the " << kind << "." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the " << kind << " value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (::std::auto_ptr< " << type << " > p);" + << endl; + + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Detach the " << kind << " value from " << + "the object model." << endl + << " *" << endl + << " * @return A pointer to the " << kind << " value." << endl + << " *" << endl + << " * Note that this function leaves the required " << + kind << " in " << endl + << " * the original object model uninitialized." << endl + << " */" << endl; + } + + os << "::std::auto_ptr< " << type << " >" << endl + << edname (m) << " ();" + << endl; + } + } + } + + // default_value + // + if (m.default_p ()) + { + Boolean simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + Boolean lit (false); + { + IsLiteralValue test (lit); + test.dispatch (m.type ()); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the default value for the " << + kind << "." << endl + << " *" << endl; + + if (lit) + os << " * @return The " << kind << "'s default value." << endl; + else + os << " * @return A read-only (constant) reference to the " + << kind << "'s" << endl + << " * default value." << endl; + + os << " */" << endl; + } + + if (lit) + os << "static " << etype (m) << endl; + else + os << "static const " << etype (m) << "&" << endl; + + os << edefault_value (m) << " ();" + << endl; + } + } + } + }; + + struct AnyFunction: Traversal::Any, Context + { + AnyFunction (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + SemanticGraph::Complex& c ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ())); + + if (max (a) != 1) + { + // sequence + // + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element sequence." << endl + << " *" << endl + << " * @return A constant reference to the sequence " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element" << endl + << " * sequence." << endl + << " *" << endl + << " * @return A reference to the sequence container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy elements from a given sequence." << endl + << " *" << endl + << " * @param s A sequence to copy elements from." << endl + << " *" << endl + << " * For each element in @a s this function " << + "makes a copy and adds" << endl + << " * it to the wildcard element sequence. Note that " << + "this operation" << endl + << " * completely changes the sequence and all old " << + "elements will be" << endl + << " * lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + else if (min (a) == 0) + { + // optional + // + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element container." << endl + << " *" << endl + << " * @return A constant reference to the optional " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element" << endl + << " * container." << endl + << " *" << endl + << " * @return A reference to the optional container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param e A new element to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new wildcard content." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e);" + << endl; + + // void + // name (type*); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content without copying." << endl + << " *" << endl + << " * @param p A new element to use." << endl + << " *" << endl + << " * This function will use the passed element " << + "directly instead" << endl + << " * of making a copy. For this to work the element " << + "should belong" << endl + << " * to the DOM document associated with this instance." << endl + << " *" << endl + << " * @see " << edom_document (c) << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << xerces_ns << "::DOMElement* p);" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param x An optional container with the new " << + "element to set." << endl + << " *" << endl + << " * If the element is present in @a x then this function " << + "makes a " << endl + << " * copy of this element and sets it as the new wildcard " << + "content." << endl + << " * Otherwise the element container is set the 'not " << + "present' state." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& x);" + << endl; + } + else + { + // one + // + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the wildcard" << endl + << " * element." << endl + << " *" << endl + << " * @return A constant reference to the DOM element." << endl + << " */" << endl; + } + + os << "const " << xerces_ns << "::DOMElement&" << endl + << aname << " () const;" + << endl; + + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "wildcard element." << endl + << " *" << endl + << " * @return A reference to the DOM element." << endl + << " */" << endl; + } + + os << xerces_ns << "::DOMElement&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content." << endl + << " *" << endl + << " * @param e A new element to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new wildcard content." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e);" + << endl; + + // void + // name (const*); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the wildcard content without copying." << endl + << " *" << endl + << " * @param p A new element to use." << endl + << " *" << endl + << " * This function will use the passed element " << + "directly instead" << endl + << " * of making a copy. For this to work the element " << + "should belong" << endl + << " * to the DOM document associated with this instance." << endl + << " *" << endl + << " * @see " << edom_document (c) << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (" << xerces_ns << "::DOMElement* p);" + << endl; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String container (econtainer (a)); + + // container const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the" << endl + << " * attribute set." << endl + << " *" << endl + << " * @return A constant reference to the set " << + "container." << endl + << " */" << endl; + } + + os << "const " << container << "&" << endl + << aname << " () const;" + << endl; + + // container& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "attribute set." << endl + << " *" << endl + << " * @return A reference to the set container." << endl + << " */" << endl; + } + + os << container << "&" << endl + << aname << " ();" + << endl; + + // void + // name (container const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy attributes from a given set." << endl + << " *" << endl + << " * @param s A set to copy elements from." << endl + << " *" << endl + << " * For each attribute in @a s this function " << + "makes a copy and adds" << endl + << " * it to the set. Note that this operation " << + "completely changes the " << endl + << " * set and all old attributes will be lost." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << container << "& s);" + << endl; + } + }; + + // + // + struct Member: Traversal::Member, Context + { + Member (Context& c) + : Context (c), + type_name_ (c), + member_function_ (c) + { + belongs_ >> type_name_; + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& type (etype (m)); + Boolean el (m.is_a<SemanticGraph::Element> ()); + + Boolean def_attr (m.default_p () && !el); + + if (doxygen) + { + os << "/**" << endl + << " * @name " << comment (m.name ()) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the %" << + comment (m.name ()) << endl + << " * "; + + if (max (m) != 1) + { + os << "sequence element." << endl; + } + else if (min (m) == 0) + { + if (def_attr) + os << "optional attribute with a default value." << endl; + else + os << "optional " << (el ? "element." : "attribute.") << endl; + } + else + { + os << "required " << (el ? "element." : "attribute.") << endl; + } + + if (m.annotated_p ()) + { + os << " *" << endl; + write_annotation (m.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << comment (m.name ()) << endl + << "// " << endl; + } + + // Typedefs. + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " type." << endl + << " */" << endl; + } + + os << "typedef "; + + belongs (m, belongs_); + + os << " " << type << ";"; + + if (max (m) != 1) + { + String const& container (econtainer (m)); + Boolean isense (options.value<CLI::generate_intellisense> ()); + + // sequence + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element sequence container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::sequence< " << type << " > " << + container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element iterator type." << endl + << " */" << endl; + } + + // IntelliSense does not not like aliases and fully-qualified + // names here. + // + if (!isense) + os << "typedef " << container << "::iterator " << + eiterator (m) << ";"; + else + os << "typedef xsd::cxx::tree::sequence< " << type << + " >::iterator " << eiterator (m) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element constant iterator type." << endl + << " */" << endl; + } + + if (!isense) + os << "typedef " << container << "::const_iterator " << + econst_iterator (m) << ";"; + else + os << "typedef xsd::cxx::tree::sequence< " << type << + " >::const_iterator " << econst_iterator (m) << ";"; + + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " optional container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::optional< " << type << " > " << + econtainer (m) << ";"; + } + else + { + // one + // + } + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief " << (el ? "Element" : "Attribute") << + " traits type." << endl + << " */" << endl; + } + os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + SemanticGraph::Type& t (m.type ()); + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " > " << etraits (m) << ";" + << endl; + + member_function_.traverse (m); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + MemberTypeName type_name_; + Traversal::Belongs belongs_; + + MemberFunction member_function_; + }; + + + struct Any: Traversal::Any, + Traversal::AnyAttribute, + Context + { + Any (Context& c) + : Context (c), any_function_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (doxygen) + { + os << "/**" << endl + << " * @name " << ename (a) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "any wildcard." << endl; + + if (a.annotated_p ()) + { + os << " *" << endl; + write_annotation (a.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << ename (a) << endl + << "// " << endl; + } + + // Typedefs. + // + if (max (a) != 1) + { + String const& container (econtainer (a)); + + // sequence + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element sequence container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::element_sequence " << + container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::iterator " << + eiterator (a) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element constant iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::const_iterator " << + econst_iterator (a) << ";" + << endl; + + } + else if (min (a) == 0) + { + // optional + // + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM element optional container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::element_optional " << + econtainer (a) << ";" + << endl; + } + else + { + // one + // + if (doxygen) + os << endl; + } + + any_function_.traverse (a); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& container (econtainer (a)); + + if (doxygen) + { + os << "/**" << endl + << " * @name " << ename (a) << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "anyAttribute" << endl + << " * wildcard." << endl; + + if (a.annotated_p ()) + { + os << " *" << endl; + write_annotation (a.annotation ()); + } + + os << " */" << endl + << "//@{" << endl; + } + else + { + os << "// " << ename (a) << endl + << "// " << endl; + } + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute set container type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::attribute_set< " << char_type << + " > " << container << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::iterator " << + eiterator (a) << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief DOM attribute constant iterator type." << endl + << " */" << endl; + } + + os << "typedef " << container << "::const_iterator " << + econst_iterator (a) << ";" + << endl; + + any_function_.traverse (a); + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + } + + private: + AnyFunction any_function_; + }; + + struct DataMember: Traversal::Member, Context + { + DataMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) return; + + String const& member (emember (m)); + + Boolean def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + os << econtainer (m) << " " << member << ";"; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + os << econtainer (m) << " " << member << ";"; + } + else + { + // one + // + os << "::xsd::cxx::tree::one< " << etype (m) << " > " << + member << ";"; + } + + // default_value + // + if (m.default_p ()) + { + Boolean simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + Boolean lit (false); + { + IsLiteralValue test (lit); + test.dispatch (m.type ()); + } + + if (!lit) + { + os << "static const " << etype (m) << " " << + edefault_value_member (m) << ";"; + } + } + } + } + }; + + struct DataAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + DataAny (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + + if (max (a) != 1) + { + // sequence + // + os << econtainer (a) << " " << member << ";"; + } + else if (min (a) == 0) + { + // optional + // + os << econtainer (a) << " " << member << ";"; + } + else + { + // one + // + os << "::xsd::cxx::tree::element_one " << member << ";"; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + os << econtainer (a) << " " << emember (a) << ";"; + } + }; + + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + base_name_ (c), + member_name_ (c), + any_ (c), + member_ (c), + data_any_ (c), + data_member_ (c) + { + inherits_base_ >> base_name_; + inherits_member_ >> member_name_; + + names_ >> member_; + if (options.value<CLI::generate_wildcard> ()) + names_ >> any_; + + names_data_ >> data_member_; + if (options.value<CLI::generate_wildcard> ()) + names_data_ >> data_any_; + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + Boolean has_members (has<Traversal::Member> (c)); + + Boolean hae (has<Traversal::Any> (c)); + Boolean haa (has<Traversal::AnyAttribute> (c)); + + Boolean gen_wildcard (options.value<CLI::generate_wildcard> ()); + + Boolean simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (c); + } + + SemanticGraph::Enumeration* enum_base (0); + { + IsEnumBasedType t (enum_base); + t.dispatch (c); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Class corresponding to the %" << + comment (c.name ()) << " schema type." << endl; + + if (c.annotated_p ()) + { + os << " *" << endl; + write_annotation (c.annotation ()); + } + + os << " *" << endl + << " * @nosubgrouping" << endl + << " */" << endl; + } + + os << "class " << type_exp << name << ": public "; + + if (c.inherits_p ()) + inherits (c, inherits_base_); + else + os << any_type; + + os << "{" + << "public:" << endl; + + // Members. + // + names (c, names_); + + // dom_document accessors. + // + if (edom_document_member_p (c)) + { + + if (!doxygen) + { + os << "// DOMDocument for wildcard content." << endl + << "//" << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the DOM" << endl + << " * document associated with this instance." << endl + << " *" << endl + << " * @return A constant reference to the DOM document." << endl + << " *" << endl + << " * The DOM document returned by this function is " << + "used to store" << endl + << " * the raw XML content corresponding to wildcards." << endl + << " */" << endl; + } + + os << "const " << xerces_ns << "::DOMDocument&" << endl + << edom_document (c) << " () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the DOM " << + "document" << endl + << " * associated with this instance." << endl + << " *" << endl + << " * @return A reference to the DOM document." << endl + << " *" << endl + << " * The DOM document returned by this function is " << + "used to store" << endl + << " * the raw XML content corresponding to wildcards." << endl + << " */" << endl; + } + os << xerces_ns << "::DOMDocument&" << endl + << edom_document (c) << " ();" + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @name Constructors" << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Constructors." << endl + << "//" << endl; + } + + Boolean generate_no_base_ctor (false); + { + GenerateWithoutBaseCtor t (generate_no_base_ctor); + t.traverse (c); + } + + Boolean has_complex_non_op_args (false); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + // c-tor (ultimate-base, all-non-optional-members) will become + // default c-tor if our inheritance hierarchy has no required + // members and no simple base. We can also collide with + // c-tor (all-non-optional-members) if we have no required + // members. + // + Boolean generate (false); + { + GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); + t.traverse (c); + } + + if (generate) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor leaves required " << + "elements and" << endl + << " * attributes uninitialized." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + } + + // c-tor (base, all-non-optional-members) + // + if (options.value<CLI::generate_from_base_ctor> ()) + { + // c-tor (base, all-non-optional-members) will be equivalent to + // c-tor (ultimate-base, all-non-optional-members) unless our + // immediate base's hierarchy has some non-optional members. + // We also need to generate this c-tor when one of the types + // in our inheritance hierarchy was customized since the + // customized version may not necessarily be convertible to + // the base without loss of information. + // + Boolean generate (false); + { + GenerateFromBaseCtor t (*this, generate); + t.traverse (c); + } + + if (generate) + { + Boolean has_complex_non_op_args (false); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args (*this, FromBaseCtorArg::arg_type, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes" << endl + << " * (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args ( + *this, FromBaseCtorArg::arg_complex_auto_ptr, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the immediate " + "base and" << endl + << " * initializers for required elements and " + << "attributes" << endl + << " * (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " (const "; + inherits (c, inherits_member_); + os << "&"; + { + FromBaseCtorArg args ( + *this, FromBaseCtorArg::arg_poly_auto_ptr, false); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ");" + << endl; + } + } + } + + // c-tor (all-non-optional-members) + // + if (generate_no_base_ctor) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. One case where + // this c-tor will be generated is restriction of anyType. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_complex_auto_ptr, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from initializers " << + "for required " << endl + << " * elements and attributes (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_poly_auto_ptr, false, true); + ctor_args.dispatch (c); + } + os << ");" + << endl; + } + } + + if (string_based) + { + // We might not have the value type if this enum is customized. + // + if (enum_base != 0 && enum_base->context ().count ("value")) + { + // c-tor (enum-value, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the " << + "underlying enum value" << endl + << " * and initializers for required elements and " << + "attributes." << endl + << " */" << endl; + } + + os << name << " (" << fq_name (*enum_base) << "::" << + evalue (*enum_base); + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (const char*, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a C string and " << + "initializers" << endl + << " * for required elements and attributes." << endl + << " */" << endl; + } + + os << name << " (const " << char_type << "*"; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + + // c-tor (const std::string&, all-non-optional-members) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string and" << + "initializers" << endl + << " * for required elements and attributes." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "&"; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, false, false); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (ultimate-base, all-non-optional-members) + // + + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgs::arg_type); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes" << endl + << " * (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgs::arg_complex_auto_ptr); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && has_poly_non_op_args && !complex_poly_args_clash) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from the ultimate " + "base and" << endl + << " * initializers for required elements and " << + "attributes" << endl + << " * (auto_ptr version)." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "values directly" << endl + << " * instead of making copies." << endl + << " */" << endl; + } + + os << name << " ("; + + { + CtorArgs ctor_args (*this, CtorArgs::arg_poly_auto_ptr); + ctor_args.dispatch (c); + } + + os << ");" + << endl; + } + + // c-tor (istream&) + // + Streams const& st (options.value<CLI::generate_extraction> ()); + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a data " << + "representation" << endl + << " * stream." << endl + << " *" << endl + << " * @param s A stream to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (" << istream_type << "< " << i->c_str () << + " >& s," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + + if (simple) + { + // c-tor (xercesc::DOMAttr) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM attribute." << endl + << " *" << endl + << " * @param a A DOM attribute to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // c-tor (std::basic_string const&, xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a string fragment." << endl + << " *" << endl + << " * @param s A string fragment to extract the data from." << endl + << " * @param e A pointer to DOM element containing the " << + "string fragment." << endl + << " * @param f Flags to create the new instance with." << endl + << " * @param c A pointer to the object that will " << + "contain the new" << endl + << " * instance." << endl + << " */" << endl; + } + + os << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + } + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x," << endl + << flags_type << " f = 0," << endl + << container << "* c = 0);" + << endl; + + // clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @param c A pointer to the object that will contain " << + "the copy." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0," << endl + << container << "* c = 0) const;" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();" + << endl; + + // Data members and implementation functions. + // + if (has_members || hae || (haa && gen_wildcard)) + { + os << "// Implementation." << endl + << "//" << endl; + + if (doxygen) + os << endl + << "//@cond" << endl + << endl; + + if (!options.value<CLI::suppress_parsing> ()) + { + // parse (xercesc::DOMElement) + // + os << "protected:" << endl + << "void" << endl + << unclash (name, "parse") << " (" << + parser_type << "&," << endl + << flags_type << ");" + << endl; + } + + os << "protected:" + << endl; + + // parse (istream) + // + if (has_members) + { + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + os << "void" << endl + << unclash (name, "parse") << " (" << + istream_type << "< " << i->c_str () << " >&," << endl + << flags_type << ");" + << endl; + } + } + + // + // + if (edom_document_member_p (c)) + { + os << dom_auto_ptr << "< " << xerces_ns << + "::DOMDocument > " << edom_document_member (c) << ";" + << endl; + } + + // + // + names (c, names_data_); + + if (doxygen) + os << endl + << "//@endcond" << endl; + } + + os << "};"; + + // Comparison operators. + // + if (options.value<CLI::generate_comparison> () && + (has_members || !c.inherits_p () || + ((hae || haa) && gen_wildcard))) + { + os << inst_exp + << "bool" << endl + << "operator== (const " << name << "&, const " << name << "&);" + << endl; + + os << inst_exp + << "bool" << endl + << "operator!= (const " << name << "&, const " << name << "&);" + << endl + << endl; + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_name_; + + Traversal::Inherits inherits_member_; + MemberTypeName member_name_; + + Traversal::Names names_; + Any any_; + Member member_; + + Traversal::Names names_data_; + DataAny data_any_; + DataMember data_member_; + }; + + + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c), type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + SemanticGraph::Type& t (e.type ()); + + Boolean fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + Boolean simple (true); + if (!fund) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Class corresponding to the %" << + comment (e.name ()) << " root element." << endl; + + if (e.annotated_p ()) + { + os << " *" << endl; + write_annotation (e.annotation ()); + } + + os << " *" << endl + << " * @nosubgrouping" << endl + << " */" << endl; + } + + String const& name (ename (e)); + + os << "class " << type_exp << name << ": public " << element_type + << "{" + << "public:" << endl + << endl; + + String const& type (etype (e)); + + if (doxygen) + { + os << "/**" << endl + << " * @name Element value" << endl + << " *" << endl + << " * @brief Accessor and modifier functions for the " << + "element value." << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Element value." << endl + << "//" << endl; + } + + // Typedefs. + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Element value type." << endl + << " */" << endl; + } + + os << "typedef "; + + belongs (e, belongs_); + + os << " " << type << ";"; + + if (doxygen) + { + os << endl + << "/**" << endl + << " * @brief Element value traits type." << endl + << " */" << endl; + } + + os << "typedef ::xsd::cxx::tree::traits< " << type << ", " << + char_type; + + if (t.is_a<SemanticGraph::Fundamental::Double> ()) + os << ", ::xsd::cxx::tree::schema_type::double_"; + else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) + os << ", ::xsd::cxx::tree::schema_type::decimal"; + + os << " > " << etraits (e) << ";" + << endl; + + // Accessors/modifiers. + // + String const& aname (eaname (e)); + String const& mname (emname (e)); + + // type const& + // name () const; + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) reference " << + "to the element" << endl + << " * value." << endl + << " *" << endl + << " * @return A constant reference to the element value." << + endl + << " */" << endl; + } + + os << "const " << type << "&" << endl + << aname << " () const;" + << endl; + + // type& + // name (); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-write reference to the " << + "element value." << endl + << " *" << endl + << " * @return A reference to the element value." << endl + << " */" << endl; + } + + os << type << "&" << endl + << aname << " ();" + << endl; + + // void + // name (type const&); + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the element value." << endl + << " *" << endl + << " * @param x A new value to set." << endl + << " *" << endl + << " * This function makes a copy of its argument " << + "and sets it as" << endl + << " * the new value of the element." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (const " << type << "& x);" + << endl; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Set the element value without " << + "copying." << endl + << " *" << endl + << " * @param p A new value to use." << endl + << " *" << endl + << " * This function will try to use the passed value " << + "directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << "void" << endl + << mname << " (::std::auto_ptr< " << type << " > p);" + << endl; + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Detach the element value from " << + "the object." << endl + << " *" << endl + << " * @return A pointer to the element value." << endl + << " *" << endl + << " * Note that this function leaves the element " << + "object uninitialized." << endl + << " */" << endl; + } + + os << "::std::auto_ptr< " << type << " >" << endl + << edname (e) << " ();" + << endl; + } + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a read-only (constant) pointer " << + "to the element" << endl + << " * value." << endl + << " *" << endl + << " * @return A constant pointer to the element value " << + "or 0 if this" << endl + << " * element is of a fundamental type." << endl + << " */" << endl; + } + + os << "virtual const " << any_type << "*" << endl + << "_value () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return a pointer to the element value." << endl + << " *" << endl + << " * @return A pointer to the element value or 0 if this " << + "element is" << endl + << " * of a fundamental type." << endl + << " */" << endl; + } + os << "virtual " << any_type << "*" << endl + << "_value ();" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // Constructor. + // + + if (doxygen) + { + os << "/**" << endl + << " * @name Constructors" << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Constructors." << endl + << "//" << endl; + } + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Default constructor." << endl + << " *" << endl + << " * Note that this constructor leaves the element " << + "value" << endl + << " * uninitialized." << endl + << " */" << endl; + } + + os << name << " ();" + << endl; + } + + // c-tor (value) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from an initializer " << + "for the element" << endl + << " * value." << endl + << " *" << endl + << " * @param x Element value." << endl + << " */" << endl; + } + + os << name << " (const " << type << "& x);" + << endl; + + + // If the element value is a complex type (has elements, + // attributes, or wildcards) then also generate the auto_ptr + // version. If we are generating polymorphic code then we + // also need to provide auto_ptr version for simple types. + // + if (!simple || (polymorphic && polymorphic_p (t))) + { + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from an initializer " << + "for" << endl + << " * the element value (auto_ptr version)." << endl + << " *" << endl + << " * @param p Element value to use." << endl + << " *" << endl + << " * This constructor will try to use the passed " << + "value directly" << endl + << " * instead of making a copy." << endl + << " */" << endl; + } + + os << name << " (::std::auto_ptr< " << type << " > p);" + << endl; + } + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Create an instance from a DOM element." << endl + << " *" << endl + << " * @param e A DOM element to extract the data from." << endl + << " * @param f Flags to create the new instance with." << endl + << " */" << endl; + } + + os << name << " (const " << xerces_ns << "::DOMElement& e, " << + flags_type << " f = 0);" + << endl; + } + + // copy c-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy constructor." << endl + << " *" << endl + << " * @param x An instance to make a copy of." << endl + << " * @param f Flags to create the copy with." << endl + << " *" << endl + << " * For polymorphic object models use the @c _clone " << + "function instead." << endl + << " */" << endl; + } + + os << name << " (const " << name << "& x, " << + flags_type << " f = 0);" + << endl; + + // _clone + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Copy the instance polymorphically." << endl + << " *" << endl + << " * @param f Flags to create the copy with." << endl + << " * @return A pointer to the dynamically allocated copy." << endl + << " *" << endl + << " * This function ensures that the dynamic type of the " << + "instance is" << endl + << " * used for copying and should be used for polymorphic " << + "object" << endl + << " * models instead of the copy constructor." << endl + << " */" << endl; + } + + os << "virtual " << name << "*" << endl + << "_clone (" << flags_type << " f = 0) const;" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // Element name and namespace accessors. + // + if (doxygen) + { + os << "/**" << endl + << " * @name Element name and namespace" << endl + << " *" << endl + << " * @brief Accessor functions for the element name " << + "and namespace." << endl + << " */" << endl + << "//@{" << endl + << endl; + } + else + { + os << "// Element name and namespace." << endl + << "//" << endl; + } + + SemanticGraph::Context& ec (e.context ()); + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element name (static function)." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * name." << endl + << " */" << endl; + } + os << "static const " << string_type << "&" << endl + << ec.get<String> ("element-name") << " ();" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element namespace (static " << + "function)." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * namespace." << endl + << " */" << endl; + } + os << "static const " << string_type << "&" << endl + << ec.get<String> ("element-ns") << " ();" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element name." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * name." << endl + << " */" << endl; + } + os << "virtual const " << string_type << "&" << endl + << "_name () const;" + << endl; + + if (doxygen) + { + os << "/**" << endl + << " * @brief Return the element namespace." << endl + << " *" << endl + << " * @return A read-only string reference containing " << + "the element" << endl + << " * namespace." << endl + << " */" << endl; + } + os << "virtual const " << string_type << "&" << endl + << "_namespace () const;" + << endl; + + if (doxygen) + { + os << "//@}" << endl + << endl; + } + + // d-tor + // + if (doxygen) + { + os << "/**" << endl + << " * @brief Destructor." << endl + << " */" << endl; + } + + os << "virtual " << endl + << "~" << name << " ();" + << endl; + + // Data member. + // + + if (doxygen) + os << "//@cond" << endl + << endl; + + os << "protected:" << endl + << "::xsd::cxx::tree::one< " << type << " > " << + emember (e) << ";" + << "static const " << string_type << " " << + ec.get<String> ("element-name-member") << ";" + << "static const " << string_type << " " << + ec.get<String> ("element-ns-member") << ";"; + + if (doxygen) + os << endl + << "//@endcond" << endl; + + os << "};"; + } + + private: + Traversal::Belongs belongs_; + MemberTypeName type_name_; + }; + } + + Void + generate_tree_header (Context& ctx) + { + if (ctx.generate_xml_schema) + { + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/types.hxx>" << endl + << endl; + + if (!ctx.options.value<CLI::suppress_parsing> () || + ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl + << endl; + } + + if (!ctx.options.value<CLI::suppress_parsing> () || + ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl + << endl; + } + + Boolean element_map (ctx.options.value<CLI::generate_element_map> ()); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl + << endl; + + // I need to include all the "optional" headers here (instead of + // later in the individual generators for each feature because + // those headers provide implementation for the fundamental types. + // + if (!ctx.options.value<CLI::suppress_parsing> ()) + { + ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl; + + Traversal::Schema schema; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "parsing"); + + schema >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.value<CLI::generate_serialization> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl + << "#include <xsd/cxx/tree/serialization.hxx>" << endl; + + Traversal::Schema schema; + Traversal::Names names; + Traversal::Namespace ns; + Traversal::Names ns_names; + FundIncludes type (ctx, "serialization"); + + schema >> names >> ns >> ns_names >> type; + + schema.dispatch (ctx.schema_root); + + if (element_map) + ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" << + endl; + + ctx.os << endl; + } + + if (ctx.options.value<CLI::generate_ostream> ()) + { + ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl + << endl; + } + + Streams const& ist (ctx.options.value<CLI::generate_insertion> ()); + if (!ist.empty ()) + { + for (Streams::ConstIterator i (ist.begin ()); i != ist.end (); ++i) + { + if (*i == "ACE_OutputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl + << endl; + } + + Streams const& est (ctx.options.value<CLI::generate_extraction> ()); + if (!est.empty ()) + { + for (Streams::ConstIterator i (est.begin ()); i != est.end (); ++i) + { + if (*i == "ACE_InputCDR") + ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>" + << endl; + else if (*i == "XDR") + ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>" + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl + << endl; + } + + // Emit fundamental types. + // + { + Traversal::Schema schema; + Traversal::Names names; + FundamentalNamespace ns (ctx); + + schema >> names >> ns; + + schema.dispatch (ctx.schema_root); + } + } + else + { + Boolean inline_ (ctx.options.value<CLI::generate_inline> ()); + + ctx.os << "#include <memory> // std::auto_ptr" << endl + << "#include <limits> // std::numeric_limits" << endl + << "#include <algorithm> // std::binary_search" << endl + << endl; + + if (ctx.char_type == L"char" && ctx.char_encoding != L"custom") + { + ctx.os << "#include <xsd/cxx/xml/char-" << ctx.char_encoding << + ".hxx>" << endl + << endl; + } + + ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl + << "#include <xsd/cxx/tree/elements.hxx>" << endl + << "#include <xsd/cxx/tree/containers.hxx>" << endl + << "#include <xsd/cxx/tree/list.hxx>" << endl + << endl; + + if (!ctx.options.value<CLI::suppress_parsing> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/parsing-header.hxx>" << endl + << endl; + } + + if (ctx.options.value<CLI::generate_wildcard> ()) + { + if (ctx.options.value<CLI::suppress_parsing> () || + !ctx.options.value<CLI::generate_serialization> ()) + ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl; + + ctx.os << "#include <xsd/cxx/tree/containers-wildcard.hxx>" << endl + << endl; + } + + if (!ctx.options.value<CLI::generate_extraction> ().empty ()) + ctx.os << "#include <xsd/cxx/tree/istream-fwd.hxx>" << endl + << endl; + + // Emit header includes. + // + { + if (inline_) + { + ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << "#define XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + + Traversal::Schema schema; + Includes includes (ctx, Includes::header); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + + if (inline_) + { + ctx.os << "#undef XSD_DONT_INCLUDE_INLINE" << endl + << "#else" << endl + << endl; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + + + { + Traversal::Schema schema; + + Traversal::Sources sources; + Traversal::Names names_ns, names; + + DocumentedNamespace ns (ctx); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.options.value<CLI::generate_element_type> ()) + names >> element; + + schema.dispatch (ctx.schema_root); + } + + // Emit inline includes. + // + if (inline_) + { + ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << endl; + + Traversal::Schema schema; + Includes ixx_includes (ctx, Includes::inline_); + schema >> ixx_includes; + + schema.dispatch (ctx.schema_root); + + ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + } + } + } +} diff --git a/xsd/xsd/cxx/tree/tree-header.hxx b/xsd/xsd/cxx/tree/tree-header.hxx new file mode 100644 index 0000000..bb3b417 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-header.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/tree-header.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_TREE_HEADER_HXX +#define CXX_TREE_TREE_HEADER_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_tree_header (Context&); + } +} + +#endif // CXX_TREE_TREE_HEADER_HXX diff --git a/xsd/xsd/cxx/tree/tree-inline.cxx b/xsd/xsd/cxx/tree/tree-inline.cxx new file mode 100644 index 0000000..5bf309b --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-inline.cxx @@ -0,0 +1,1062 @@ +// file : xsd/cxx/tree/tree-inline.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/tree-inline.hxx> +#include <cxx/tree/default-value.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + SemanticGraph::Type& item_type (l.argumented ().type ()); + String item_name (item_type_name (item_type)); + String base_type (L"::xsd::cxx::tree::list< " + item_name + + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base_type += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base_type += L", ::xsd::cxx::tree::schema_type::decimal"; + + base_type += L" >"; + + os << "// " << name << endl + << "//" << endl + << endl; + + // c-tor () + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base_type << " ( " << flags_type << " (0), this)" + << "{" + << "}"; + + // c-tor (size_type, const X& x) + // + String size_type (name != L"size_type" + ? String (L"size_type") + : base_type + L"::size_type"); + + os << inl + << name << "::" << endl + << name << " (" << size_type << " n, const " << item_name << + "& x)" << endl + << ": " << base_type << " (n, x, this)" + << "{" + << "}"; + + // copy c-tor () + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& o," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (o, f, c)," << endl + << " " << base_type << " (o, f, this)" + << "{" + << "}"; + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (options.value<CLI::generate_default_ctor> ()) + { + // c-tor () + // + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()" + << "{" + << "}"; + } + + // c-tor (const char*) + // + os << inl + << name << "::" << endl + << name << " (const " << char_type << "* s)" << endl + << ": " << base << " (s)" + << "{" + << "}"; + + // c-tor (string const&) + // + os << inl + << name << "::" << endl + << name << " (const " << string_type << "& s)" << endl + << ": " << base << " (s)" + << "{" + << "}"; + + // copy c-tor () + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& o," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (o, f, c)" + << "{" + << "}"; + } + }; + + // Enumeration + // + + // Generate a sequence of explicit c-tor calls until we reach + // one of the fundamental string types that can be constructed + // from char literals. + // + struct CtorCallSequence: Traversal::Complex, + Traversal::Fundamental::Type, + Context + { + CtorCallSequence (Context& c, String const& arg) + : Context (c), arg_ (arg), base_type_name_ (c) + { + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + // This type should be ultimately string based. + // + assert (c.inherits_p ()); + + os << ename (c) << " (" << endl; + + dispatch (c.inherits ().base ()); + + os << ")"; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Type& t) + { + base_type_name_.dispatch (t); + + os << " (" << arg_ << ")"; + } + + private: + String arg_; + BaseTypeName base_type_name_; + }; + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), member_ (c) + { + inherits_member_ >> member_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + Boolean enum_based (false); + if (string_based) + { + SemanticGraph::Enumeration* be (0); + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + String value; + if (string_based) + value = evalue (e); + + // Get to the ultimate base and see if is a fundamental type. + // + Boolean fund_based (false); + SemanticGraph::Type& ult_base (ultimate_base (e)); + { + IsFundamentalType t (fund_based); + t.dispatch (ult_base); + } + + // + // + String base; // base type name + { + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + inherits (e, inherits_type); + base = o.str (); + } + + os << "// " << name << endl + << "// " << endl + << endl; + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + os << inl + << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()" + << "{" + << "}"; + } + + // c-tor (value) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (" << value << " v)" << endl + << ": "; + + // If we are enum-based then we can just use the corresponding + // base c-tor directly. Otherwise we will use the from-string + // c-tor. + // + if (enum_based) + os << base << " (v)"; + else + { + CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); + t.dispatch (e.inherits ().base ()); + } + + os << "{" + << "}"; + } + + // c-tor (const char*) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (const " << char_type << "* v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (const std::string&) + // + if (string_based) + { + os << inl + << name << "::" << endl + << name << " (const " << string_type << "& v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (fundamental) + // + if (fund_based) + { + os << inl + << name << "::" << endl + << name << " ("; + + member_.dispatch (ult_base); + + os << " v)" + << ": " << base << " (v)" + << "{" + << "}"; + } + + // c-tor (base) + // + // If the ultimate is also our immediate base and it is a + // fundamental type then this c-tor clashes with c-tor + // (fundamental) above. + // + if (!fund_based || &ult_base != &e.inherits ().base ()) + { + os << inl + << name << "::" << endl + << name << " (const "; + + inherits (e, inherits_member_); + + os << "& v)" << endl + << ": " << base << " (v)" + << "{" + << "}"; + } + + // copy c-tor + // + os << inl + << name << "::" << endl + << name << " (const " << name << "& v," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (v, f, c)" + << "{" + << "}"; + + // operato= (value) + // + if (string_based) + { + os << inl + << name << "& " << name << "::" << endl + << "operator= (" << value << " v)" + << "{" + << "static_cast< " << base << "& > (*this) = "; + + // If we are enum-based then we can just use the corresponding + // base assignment directly. Otherwise we will use the from- + // base assignment and a from-string base c-tor. + // + if (enum_based) + os << "v"; + else + { + os << endl; + + CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]"); + t.dispatch (e.inherits ().base ()); + } + + os << ";" + << endl + << "return *this;" + << "}"; + } + + os << endl; + } + + private: + Traversal::Inherits inherits_member_; + MemberTypeName member_; + }; + + struct Member: Traversal::Member, Context + { + Member (Context& c, String const& scope) + : Context (c), scope_ (scope), lit_value_ (c) + { + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& aname (eaname (m)); + String const& mname (emname (m)); + String const& member (emember (m)); + + Boolean fund (false); + { + IsFundamentalType t (fund); + t.dispatch (m.type ()); + } + + Boolean def_attr (m.default_p () && + m.is_a<SemanticGraph::Attribute> ()); + + if (max (m) != 1) + { + // sequence + // + String container (econtainer (m)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + else if (min (m) == 0 && !def_attr) + { + // optional + // + String type (etype (m)); + String container (econtainer (m)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& x)" + << "{" + << "this->" << member << " = x;" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + os << inl + << "void " << scope_ << "::" << endl + << mname << " (::std::auto_ptr< " << type << " > x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + } + else + { + // one + // + String type (etype (m)); + String q_type (scope_ + L"::" + type); + + // type const& + // name () const; + // + os << inl + << "const " << q_type << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // Do not generate modifiers for fixed attributes. + // + if (!(def_attr && m.fixed_p ())) + { + // type& + // name (); + // + os << inl + << q_type << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + os << inl + << "void " << scope_ << "::" << endl + << mname << " (::std::auto_ptr< " << type << " > x)" + << "{" + << "this->" << member << ".set (x);" + << "}"; + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + os << inl + << "::std::auto_ptr< " << q_type << " > " << + scope_ << "::" << endl + << edname (m) << " ()" + << "{" + << "return this->" << member << ".detach ();" + << "}"; + } + } + + + // default_value + // + if (m.default_p ()) + { + Boolean simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (m.type ()); + } + + if (simple) + { + String lit (lit_value_.dispatch (m.type (), m.value ())); + + os << inl; + + if (lit) + os << scope_ << "::" << etype (m) << " "; + else + os << "const " << scope_ << "::" << etype (m) << "& "; + + os << scope_ << "::" << endl + << edefault_value (m) << " ()" + << "{"; + + if (lit) + os << "return " << etype (m) << " (" << lit << ");"; + else + os << "return " << edefault_value_member (m) << ";"; + + os << "}"; + } + } + } + + private: + String scope_; + LiteralValue lit_value_; + }; + + struct Any: Traversal::Any, + Traversal::AnyAttribute, + Context + { + Any (Context& c, String const& scope) + : Context (c), scope_ (scope) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String const& member (emember (a)); + + if (max (a) != 1) + { + // sequence + // + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + else if (min (a) == 0) + { + // optional + // + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (type*); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << xerces_ns << "::DOMElement* e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& x)" + << "{" + << "this->" << member << " = x;" + << "}"; + } + else + { + // one + // + + // type const& + // name () const; + // + os << inl + << "const " << xerces_ns << "::DOMElement& " << + scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // type& + // name (); + // + os << inl + << xerces_ns << "::DOMElement& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << xerces_ns << "::DOMElement& e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + + // void + // name (type*); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (" << xerces_ns << "::DOMElement* e)" + << "{" + << "this->" << member << ".set (e);" + << "}"; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + String const& mname (emname (a)); + + String const& member (emember (a)); + String container (econtainer (a)); + String q_container (scope_ + L"::" + container); + + // container const& + // name () const; + // + os << inl + << "const " << q_container << "& " << scope_ << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ";" + << "}"; + + // container& + // name (); + // + os << inl + << q_container << "& " << scope_ << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ";" + << "}"; + + // void + // name (container const&); + // + os << inl + << "void " << scope_ << "::" << endl + << mname << " (const " << container << "& s)" + << "{" + << "this->" << member << " = s;" + << "}"; + } + + private: + String scope_; + }; + + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + os << "// " << name << endl + << "// " << endl + << endl; + + // Generate accessors and modifiers. + // + Any any (*this, name); + Member member (*this, name); + Traversal::Names names; + + if (options.value<CLI::generate_wildcard> ()) + names >> any; + + names >> member; + + Complex::names (c, names); + + // dom_document accessors. + // + if (edom_document_member_p (c)) + { + os << inl + << "const " << xerces_ns << "::DOMDocument& " << + name << "::" << endl + << edom_document (c) << " () const" + << "{" + << "return *" << edom_document_member (c) << ";" + << "}"; + + os << inl + << xerces_ns << "::DOMDocument& " << name << "::" << endl + << edom_document (c) << " ()" + << "{" + << "return *" << edom_document_member (c) << ";" + << "}"; + } + + os << endl; + } + }; + + + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (!doc_root_p (e)) + return; + + Boolean fund (false); + { + IsFundamentalType test (fund); + test.dispatch (e.type ()); + } + + String const& name (ename (e)); + + os << "// " << name << endl + << "// " << endl + << endl; + + // Accessors/modifiers. + // + String const& type (etype (e)); + String const& aname (eaname (e)); + String const& mname (emname (e)); + String const& member (emember (e)); + + // type const& + // name () const; + // + os << inl + << "const " << name << "::" << type << "& " << name << "::" << endl + << aname << " () const" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // type& + // name (); + // + os << inl + << name << "::" << type << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return this->" << member << ".get ();" + << "}"; + + // void + // name (type const&); + // + os << inl + << "void " << name << "::" << endl + << mname << " (const " << type << "& x)" + << "{" + << "return this->" << member << ".set (x);" + << "}"; + + // void + // name (auto_ptr<type>); + // + if (!fund) + { + os << inl + << "void " << name << "::" << endl + << mname << " (::std::auto_ptr< " << type << " > p)" + << "{" + << "return this->" << member << ".set (p);" + << "}"; + } + + // auto_ptr<type> + // detach_name (); + // + if (detach && !fund) + os << inl + << "::std::auto_ptr< " << name << "::" << type << " > " << + name << "::" << endl + << edname (e) << " ()" + << "{" + << "return this->" << member << ".detach ();" + << "}"; + } + }; + } + + Void + generate_tree_inline (Context& ctx, UnsignedLong first, UnsignedLong last) + { + // Generate includes. + // + if (ctx.options.value<CLI::generate_inline> ()) + { + Traversal::Schema schema; + Includes includes (ctx, Includes::inline_); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + else + { + // Emit "weak" header includes that are used in the file-per-type + // compilation model. + // + Traversal::Schema schema; + Includes includes (ctx, Includes::source); + + schema >> includes; + + schema.dispatch (ctx.schema_root); + } + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + + if (ctx.options.value<CLI::generate_element_type> ()) + names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/tree-inline.hxx b/xsd/xsd/cxx/tree/tree-inline.hxx new file mode 100644 index 0000000..ffe4341 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-inline.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/tree-inline.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_TREE_INLINE_HXX +#define CXX_TREE_TREE_INLINE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_tree_inline (Context&, UnsignedLong first, UnsignedLong last); + } +} + +#endif // CXX_TREE_TREE_INLINE_HXX diff --git a/xsd/xsd/cxx/tree/tree-source.cxx b/xsd/xsd/cxx/tree/tree-source.cxx new file mode 100644 index 0000000..4a17b00 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-source.cxx @@ -0,0 +1,3468 @@ +// file : xsd/cxx/tree/tree-source.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cult/containers/list.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/tree-source.hxx> +#include <cxx/tree/default-value.hxx> + +namespace CXX +{ + namespace Tree + { + namespace + { + struct List: Traversal::List, Context + { + List (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& l) + { + String name (ename (l)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (l, name) && !name) + return; + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.value<CLI::suppress_parsing> ()) + { + SemanticGraph::Type& item_type (l.argumented ().type ()); + String base (L"::xsd::cxx::tree::list< " + + item_type_name (item_type) + L", " + char_type); + + if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (e, f, c)," << endl + << " " << base << " (e, f, this)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (a, f, c)," << endl + << " " << base << " (a, f, this)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << any_simple_type << " (s, e, f, c)," << endl + << " " << base << " (s, e, f, this)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) + { + // Note that we are using the original type name. + // + String const& name (ename (l)); + + if (!options.value<CLI::suppress_parsing> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (l.name ()) << "," << endl + << strlit (xml_ns_name (l)) << ");" + << endl; + + if (options.value<CLI::generate_comparison> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + + private: + String + item_type_name (SemanticGraph::Type& t) + { + std::wostringstream o; + + MemberTypeName type (*this, o); + type.dispatch (t); + + return o.str (); + } + }; + + + struct Union: Traversal::Union, Context + { + Union (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& u) + { + String name (ename (u)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (u, name) && !name) + return; + + String const& base (xs_string_type); + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{" + << "}"; + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{" + << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{" + << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) + { + // Note that we are using the original type name. + // + String const& name (ename (u)); + + if (!options.value<CLI::suppress_parsing> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (u.name ()) << "," << endl + << strlit (xml_ns_name (u)) << ");" + << endl; + + if (options.value<CLI::generate_comparison> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + }; + + + // Enumeration mapping. + // + + struct EnumeratorLiteral: Traversal::Enumerator, Context + { + EnumeratorLiteral (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + os << strlit (e.name ()); + } + }; + + + // + // + struct LiteralInfo + { + LiteralInfo (String const& value, String const& name) + : value_ (value), name_ (name) + { + } + + String value_; + String name_; + }; + + Boolean + operator< (LiteralInfo const& x, LiteralInfo const& y) + { + return x.value_ < y.value_; + } + + typedef Cult::Containers::List<LiteralInfo> LiteralInfoList; + + + // Populate LiteralInfoList + // + struct EnumeratorLiteralInfo: Traversal::Enumerator, Context + + { + EnumeratorLiteralInfo (Context& c, LiteralInfoList& list) + : Context (c), list_ (list) + { + } + + virtual Void + traverse (Type& e) + { + list_.push_back (LiteralInfo (e.name (), ename (e))); + } + + private: + LiteralInfoList& list_; + }; + + + struct Enumeration: Traversal::Enumeration, Context + { + Enumeration (Context& c) + : Context (c), enumerator_literal_ (c) + { + names_enumerator_literal_ >> enumerator_literal_; + } + + virtual Void + traverse (Type& e) + { + String name (ename (e)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (e, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (e); + } + + SemanticGraph::Enumeration* be (0); + Boolean enum_based (false); + if (string_based) + { + IsEnumBasedType t (be); + t.dispatch (e); + + enum_based = (be != 0); + } + + String value; + if (string_based) + value = evalue (e); + + UnsignedLong enum_count (0); + + for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ()); + i != end; ++i) + ++enum_count; + + String base; // base type name + { + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + inherits (e, inherits_type); + base = o.str (); + } + + os << "// " << name << endl + << "//" << endl + << endl; + + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f, c)" + << "{"; + + if (string_based) + os << "_xsd_" << name << "_convert ();"; + + os << "}"; + + + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (string_based) + { + os << "_xsd_" << name << "_convert ();"; + } + + os << "}"; + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // convert + // + // @@ TODO: expected list + // + if (string_based) + { + String i_name (L"_xsd_" + name + L"_indexes_"); + + os << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_convert () const" + << "{" + << "::xsd::cxx::tree::enum_comparator< " << char_type << + " > c (_xsd_" << name << "_literals_);" + << "const " << value << "* i (::std::lower_bound (" << endl + << i_name << "," << endl + << i_name << " + " << enum_count << "," << endl + << "*this," << endl + << "c));" + << endl + << "if (i == " << i_name << " + " << enum_count << " || " << + "_xsd_" << name << "_literals_[*i] != *this)" + << "{" + << "throw ::xsd::cxx::tree::unexpected_enumerator < " << + char_type << " > (*this);" + << "}" + << "return *i;" + << "}"; + } + + // literals and indexes + // + if (string_based) + { + if (enum_based) + { + os << "const " << char_type << "* const* " << name << "::" << endl + << "_xsd_" << name << "_literals_ = " << + fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;" + << endl; + } + else + { + os << "const " << char_type << "* const " << name << "::" << endl + << "_xsd_" << name << "_literals_[" << enum_count << "] =" + << "{"; + + names<Enumeration> ( + e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma); + + os << "};"; + } + + + LiteralInfoList l; + { + EnumeratorLiteralInfo enumerator (*this, l); + Traversal::Names names_enumerator (enumerator); + names (e, names_enumerator); + } + + l.sort (); + + os << "const " << name << "::" << value << " " << + name << "::" << endl + << "_xsd_" << name << "_indexes_[" << enum_count << "] =" + << "{"; + + String fq_name (ns_scope + L"::" + name); + + for (LiteralInfoList::Iterator + b (l.begin ()), i (b), end (l.end ()); i != end; ++i) + { + if (i != b) + os << "," << endl; + + os << fq_name << "::" << i->name_; + } + + os << "};"; + } + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) + { + // Note that we are using the original type name. + // + String const& name (ename (e)); + + if (!options.value<CLI::suppress_parsing> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (e.name ()) << "," << endl + << strlit (xml_ns_name (e)) << ");" + << endl; + + if (options.value<CLI::generate_comparison> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + } + + virtual Void + comma (Type&) + { + os << "," << endl; + } + + private: + Traversal::Names names_enumerator_literal_; + EnumeratorLiteral enumerator_literal_; + + }; + + // + // + struct Member: Traversal::Member, Context + { + Member (Context& c, String const& scope) + : Context (c), scope_ (scope), init_value_ (c) + { + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) + return; + + // default_value + // + if (m.default_p ()) + { + SemanticGraph::Type& t (m.type ()); + Boolean simple (true); + + if (m.is_a<SemanticGraph::Element> ()) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + if (simple) + { + Boolean lit (false); + { + IsLiteralValue test (lit); + test.dispatch (t); + } + + if (!lit) + { + InitKind::Kind kind (InitKind::simple); + { + InitKind test (kind); + test.dispatch (t); + } + + String const& member (edefault_value_member (m)); + + String init_name; + + switch (kind) + { + case InitKind::data: + { + init_name = escape (L"_xsd_" + scope_ + member + L"data"); + init_value_.data (init_name); + init_value_.dispatch (t, m.value ()); + break; + } + case InitKind::function: + { + init_name = escape (L"_xsd_" + scope_ + member + L"init"); + + os << "static " << scope_ << "::" << etype (m) << endl + << init_name << " ()" + << "{" + << scope_ << "::" << etype (m) << " r;" + << endl; + + init_value_.dispatch (t, m.value ()); + + os << "return r;" + << "};"; + break; + } + case InitKind::simple: + break; + } + + os << "const " << scope_ << "::" << etype (m) << " " << + scope_ << "::" << member << " (" << endl; + + switch (kind) + { + case InitKind::data: + { + // Second dispatch. + // + init_value_.dispatch (t, m.value ()); + break; + } + case InitKind::function: + { + os << init_name << " ()"; + break; + } + case InitKind::simple: + { + init_value_.dispatch (t, m.value ()); + break; + } + } + + os << ");" + << endl; + } + } + } + } + + private: + String scope_; + InitValue init_value_; + }; + + + struct Element: Traversal::Element, Context + { + Element (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + String tr (etraits (e)); // traits type name + String type (etype (e)); + + SemanticGraph::Type& t (e.type ()); + + Boolean fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (t); + } + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + os << "// " << comment (e.name ()) << endl + << "//" << endl; + + if (poly) + { + // aCC cannot handle an inline call to type_factory_map_instance. + // + os << "{" + << "::xsd::cxx::tree::type_factory_map< " << char_type << + " >& tfm (" << endl + << "::xsd::cxx::tree::type_factory_map_instance< 0, " << + char_type << " > ());" + << endl + << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl + << "tfm.create (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << "," << endl + << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl + << (e.global_p () ? "true" : "false") << ", " << + (e.qualified_p () ? "true" : "false") << ", " << + "i, n, f, this));" + << endl + << "if (tmp.get () != 0)" + << "{"; + } + else + { + if (e.qualified_p () && e.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ () == " << strlit (e.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (e.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + if (!fund) + { + os << "::std::auto_ptr< " << type << " > r (" << endl + << tr << "::create (i, f, this));" + << endl; + } + } + + + // Checks. Disabled at the moment since they make it impossible to + // parse valid instances where the same element is used in both + // base and derived types. See the cxx/tree/name-clash/inheritance + // test for details. + // + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + + if (poly || !fund) + { + if (poly) + { + // Cast to static type. + // + os << "::std::auto_ptr< " << type << " > r (" << endl + << "dynamic_cast< " << type << "* > (tmp.get ()));" + << endl + << "if (r.get ())" << endl + << "tmp.release ();" + << "else" << endl + << "throw ::xsd::cxx::tree::not_derived< " << char_type << + " > ();" + << endl; + } + + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (r);"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (r);"; + } + else + { + // one + // + os << "this->" << member << ".set (r);"; + } + } + else + { + if (max (e) != 1) + { + // sequence + // + os << "this->" << member << ".push_back (" << tr << + "::create (i, f, this));"; + } + else if (min (e) == 0) + { + // optional + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + else + { + // one + // + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + } + + os << "continue;"; + + // End of check block. + // + if (max (e) != 1) + { + // sequence + // + } + else if (min (e) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + + if (poly) + os << "}"; + } + }; + + struct ElementTest: Traversal::Element, Context + { + ElementTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& e) + { + if (skip (e)) + return; + + if (max (e) == 1 && min (e) == 1) + { + // one + // + os << "if (!" << emember (e) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << strlit (e.name ()) << "," << endl + << (e.qualified_p () + ? strlit (e.namespace_ ().name ()) + : L + String ("\"\"")) << ");" + << "}"; + } + } + }; + + struct Any: Traversal::Any, Context + { + Any (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "true"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () && " << + "n.namespace_ () != " << strlit (ns) << ")"; + } + else + os << "!n.namespace_ ().empty ()"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{"; + + + // Checks. + // + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "if (!this->" << member << ")" + << "{"; + } + else + { + // one + // + os << "if (!" << member << ".present ())" + << "{"; + } + + os << xerces_ns << "::DOMElement* r (" << endl + << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));"; + + if (max (a) != 1) + { + // sequence + // + os << "this->" << member << " .push_back (r);"; + } + else if (min (a) == 0) + { + // optional + // + os << "this->" << member << ".set (r);"; + } + else + { + // one + // + os << "this->" << member << ".set (r);"; + } + + os << "continue;"; + + // End of check block. + // + if (max (a) != 1) + { + // sequence + // + } + else if (min (a) == 0) + { + // optional + // + os << "}"; + } + else + { + // one + // + os << "}"; + } + + os << "}"; // if block + } + }; + + struct AnyTest: Traversal::Any, Context + { + AnyTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + if (max (a) == 1 && min (a) == 1) + { + // one + // + os << "if (!" << emember (a) << ".present ())" + << "{" + << "throw ::xsd::cxx::tree::expected_element< " << + char_type << " > (" << endl + << L << "\"*\"," << endl + << strlit (*a.namespace_begin ()) << ");" + << "}"; + } + } + }; + + struct Attribute: Traversal::Attribute, Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& tr (etraits (a)); // traits type name + + if (a.qualified_p () && a.namespace_ ().name ()) + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ () == " << strlit (a.namespace_ ().name ()) << ")" + << "{"; + } + else + { + os << "if (n.name () == " << strlit (a.name ()) << " && " << + "n.namespace_ ().empty ())" + << "{"; + } + + Boolean fund (false); + { + IsFundamentalType traverser (fund); + traverser.dispatch (a.type ()); + } + + if (fund) + { + os << "this->" << member << ".set (" << tr << + "::create (i, f, this));"; + } + else + { + String type (etype (a)); + + os << "::std::auto_ptr< " << type << " > r (" << endl + << tr << "::create (i, f, this));" + << endl + << "this->" << member << ".set (r);"; + } + + os << "continue;" + << "}"; + + } + }; + + struct AnyAttribute: Traversal::AnyAttribute, Context + { + AnyAttribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& member (emember (a)); + + String const& ns (a.definition_namespace ().name ()); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "// " << ename (a) << endl + << "//" << endl + << "if ("; + + // Note that we need to filter out namespaces for xmlns and + // xsi. + // + for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()), + e (a.namespace_end ()); i != e;) + { + if (*i == L"##any") + { + os << "(n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##other") + { + if (ns) + { + // Note that here I assume that ##other does not include + // unqualified names in a schema with target namespace. + // This is not what the spec says but that seems to be + // the consensus. + // + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << strlit (ns) << " &&" <<endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else + os << "(!n.namespace_ ().empty () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type << + " > () &&" << endl + << "n.namespace_ () != " << + "::xsd::cxx::xml::bits::xsi_namespace< " << char_type << + " > ())"; + } + else if (*i == L"##local") + { + os << "n.namespace_ ().empty ()"; + } + else if (*i == L"##targetNamespace") + { + os << "n.namespace_ () == " << strlit (ns); + } + else + { + os << "n.namespace_ () == " << strlit (*i); + } + + if (++i != e) + os << " ||" << endl; + } + + os << ")" + << "{" + << xerces_ns << "::DOMAttr* r (" << endl + << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl + << "this->" << dom_doc << " ().importNode (" << endl + << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));" + << "this->" << member << " .insert (r);" + << "continue;" + << "}"; + } + }; + + + struct AttributeTest: Traversal::Attribute, Context + { + AttributeTest (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& member (emember (a)); + + if (!a.optional_p () || a.default_p ()) + { + os << "if (!" << member << ".present ())" + << "{"; + + if (a.default_p ()) + { + os << "this->" << member << ".set (" << + edefault_value (a) << " ());"; + } + else + os << "throw ::xsd::cxx::tree::expected_attribute< " << + char_type << " > (" << endl + << strlit (a.name ()) << "," << endl + << (a.qualified_p () + ? strlit (a.namespace_ ().name ()) + : L + String ("\"\"")) << ");"; + + os << "}"; + } + } + }; + + + // + // + struct CtorBase: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Context + { + // If base_arg is empty then no base argument is + // generated. + // + CtorBase (Context& c, String const& base_arg) + : Context (c), base_arg_ (base_arg) + { + } + + virtual Void + traverse (SemanticGraph::Type&) + { + if (base_arg_) + os << base_arg_; + } + + virtual Void + traverse (SemanticGraph::Enumeration&) + { + if (base_arg_) + os << base_arg_; + } + + Void + traverse (SemanticGraph::Complex& c) + { + Args args (*this, base_arg_); + args.traverse (c); + } + + private: + // No need to traverse AnyAttribute since it is always mapped + // to a sequence. + // + struct Args: Traversal::Complex, + Traversal::Enumeration, + Traversal::Type, + Traversal::Any, + Traversal::Element, + Traversal::Attribute, + Context + { + Args (Context& c, String const& base_arg) + : Context (c), base_arg_ (base_arg), first_ (true) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Type&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual Void + traverse (SemanticGraph::Enumeration&) + { + if (base_arg_) + os << comma () << base_arg_; + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + if (!options.value<CLI::generate_wildcard> ()) + return; + + if (min (a) == 1 && max (a) == 1) + { + // one + // + os << comma () << ename (a); + } + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (!skip (e) && min (e) == 1 && max (e) == 1) + { + // one + // + os << comma () << ename (e); + } + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + // Note that we are not including attributes with default + // or required fixed values here. + // + if (min (a) == 1 && !a.fixed_p ()) + { + // one + // + os << comma () << ename (a); + } + } + + using Complex::traverse; + + private: + String + comma () + { + Boolean tmp (first_); + first_ = false; + return tmp ? "" : ",\n"; + } + + private: + String base_arg_; + Boolean first_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + String base_arg_; + }; + + + struct CtorMember: Traversal::Element, + Traversal::Attribute, + Context + { + CtorMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + if (max (e) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (" << flags_type << " (), this)"; + } + else if (min (e) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (" << flags_type << " (), this)"; + } + else + { + // one + // + os << "," << endl + << " " << member << " (" << ename (e) << ", " << + flags_type << " (), this)"; + } + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + Boolean def (a.default_p ()); + + if (min (a) == 0 && !def) + { + // optional + // + os << "," << endl + << " " << member << " (" << flags_type << " (), this)"; + } + else + { + // one + // + + if (def) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), " << flags_type << " (), this)"; + } + else + { + os << "," << endl + << " " << member << " (" << ename (a) << ", " << + flags_type << " (), this)"; + } + } + } + }; + + struct CtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CtorAny (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + if (max (a) != 1) + { + // sequence + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else if (min (a) == 0) + { + // optional + // + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + else + { + // one + // + os << "," << endl + << " " << member << " (" << ename (a) << ", this->" << + dom_doc << " ())"; + } + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << emember (a) << " (this->" << dom_doc << " ())"; + } + }; + + + struct CopyMember: Traversal::Member, Context + { + CopyMember (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual Void + traverse (SemanticGraph::Member& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", f, this)"; + } + + private: + String arg_name; + }; + + struct CopyAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + CopyAny (Context& c, String const& arg_name_) + : Context (c), arg_name (arg_name_) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (" << + arg_name << "." << member << ", this->" << dom_doc << " ())"; + } + + private: + String arg_name; + }; + + + // Element parsing c-tor initializers. + // + struct ElementCtorMember: Traversal::Member, Context + { + ElementCtorMember (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& m) + { + if (skip (m)) + return; + + String const& member (emember (m)); + + os << "," << endl + << " " << member << " (f, this)"; + } + }; + + struct ElementCtorAny: Traversal::Any, + Traversal::AnyAttribute, + Context + { + ElementCtorAny (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + + // Default c-tor member initializer. + // + struct DefaultCtorMemberInit: Traversal::Element, + Traversal::Attribute, + Context + { + DefaultCtorMemberInit (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& member (emember (e)); + + os << "," << endl + << " " << member << " (" << flags_type << " (), this)"; + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& member (emember (a)); + + if (a.default_p ()) + { + // This is an attribute with default or fixed value. We are + // going to initialize it to its default value. + // + os << "," << endl + << " " << member << " (" << + edefault_value (a) << " (), " << flags_type << " (), this)"; + } + else + os << "," << endl + << " " << member << " (" << flags_type << " (), this)"; + } + }; + + struct DefaultCtorAnyInit: Traversal::Any, + Traversal::AnyAttribute, + Context + { + DefaultCtorAnyInit (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& member (emember (a)); + String const& dom_doc ( + edom_document ( + dynamic_cast<SemanticGraph::Complex&> (a.scope ()))); + + os << "," << endl + << " " << member << " (this->" << dom_doc << " ())"; + } + }; + + // Test whether the base has comparison operators. + // + struct HasComparisonOperator: Traversal::Fundamental::Type, + Traversal::List, + Traversal::Union, + Traversal::Complex, + Traversal::Enumeration, + Traversal::Member, + Traversal::Any, + Traversal::AnyAttribute, + Context + { + // generate should initially be false. + // + HasComparisonOperator (Context& c, Boolean& generate) + : Context (c), generate_ (generate) + { + *this >> inherits_ >> *this; + *this >> names_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Fundamental::Type&) + { + // All built-in types are comparable. + generate_ = true; + } + + virtual Void + traverse (SemanticGraph::List&) + { + generate_ = true; + } + + virtual Void + traverse (SemanticGraph::Union&) + { + generate_ = true; + } + + virtual Void + traverse (SemanticGraph::Enumeration& e) + { + Traversal::Enumeration::inherits (e); + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + Complex::names (c); + + if (!generate_) + Complex::inherits (c); + } + + virtual Void + traverse (SemanticGraph::Member& m) + { + if (!skip (m)) + generate_ = true; + } + + virtual Void + traverse (SemanticGraph::Any&) + { + if (options.value<CLI::generate_wildcard> ()) + generate_ = true; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.value<CLI::generate_wildcard> ()) + generate_ = true; + } + + private: + Boolean& generate_; + + Traversal::Inherits inherits_; + Traversal::Names names_; + }; + + // + // + struct MemberComparison: Traversal::Element, + Traversal::Attribute, + Context + { + MemberComparison (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + String const& aname (eaname (e)); + + // Check if we need to handle xsi:type and substitution groups. + // If this element's type is anonymous then we don't need to do + // anything. Note that if the type is anonymous then it can't be + // derived from which makes it impossible to substitute or + // dynamically-type with xsi:type. + // + SemanticGraph::Type& t (e.type ()); + Boolean poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); + + if (!poly) + { + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + else + { + // aCC cannot handle an inline call to comparison_map_instance. + // + os << "{" + << "::xsd::cxx::tree::comparison_map< " << char_type + << " >& cm (" << endl + << "::xsd::cxx::tree::comparison_map_instance< 0, " << + char_type << " > ());" + << endl; + + if (max (e) != 1) + { + // sequence + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (a.size () != b.size ())" << endl + << "return false;" + << endl; + + os << "for (" << scope << "::" << econst_iterator (e) << endl + << "ai (a.begin ()), bi (b.begin ()), " << + "ae (a.end ()), be (b.end ());" << endl + << "ai != ae; ++ai, ++bi)" + << "{" + << "if (!cm.compare (*ai, *bi))" << endl + << "return false;" + << "}"; + } + else if (min (e) == 0) + { + // optional + // + String const& scope (ename (e.scope ())); + + os << scope << "::" << econtainer (e) << + " a (x." << aname << " ()), b (y." << aname << " ());" + << endl; + + os << "if (!a || !b)" + << "{" + << "if (a.present () != b.present ())" << endl + << "return false;" + << "}" + << "else" + << "{" + << "if (!cm.compare (*a, *b))" << endl + << "return false;" + << "}"; + } + else + { + // one + // + os << "if (!cm.compare (x." << aname << " (), y." << + aname << " ()))" << endl + << "return false;"; + } + + os << "}"; + } + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + struct AnyComparison: Traversal::Any, + Traversal::AnyAttribute, + Context + { + AnyComparison (Context& c) + : Context (c) + { + } + + virtual Void + traverse (SemanticGraph::Any& a) + { + String const& aname (eaname (a)); + + if (max (a) == 1 && min (a) == 1) + os << "if (!x." << aname << " ().isEqualNode (&y." << + aname << " ()))"; + else + os << "if (!(x." << aname << " () == y." << aname << " ()))"; + + os << endl + << "return false;" + << endl; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute& a) + { + String const& aname (eaname (a)); + + os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl + << "return false;" + << endl; + } + }; + + // Check whether a type has a parse() function (i.e., has any + // members, recursively). + // + struct HasParseFunction: Traversal::Complex, + Traversal::Element, + Traversal::Any, + Traversal::Attribute, + Traversal::AnyAttribute, + Context + { + HasParseFunction (Context& c, Boolean& has_el, Boolean& has_at) + : Context (c), has_el_ (has_el), has_at_ (has_at) + { + *this >> names_ >> *this; + *this >> inherits_ >> *this; + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + names (c); + + if (!(has_el_ && has_at_)) + inherits (c); + } + + virtual Void + traverse (SemanticGraph::Element&) + { + has_el_ = true; + } + + virtual Void + traverse (SemanticGraph::Any&) + { + has_el_ = true; + } + + virtual Void + traverse (SemanticGraph::Attribute&) + { + has_at_ = true; + } + + virtual Void + traverse (SemanticGraph::AnyAttribute&) + { + if (options.value<CLI::generate_wildcard> ()) + has_at_ = true; + } + + private: + Boolean& has_el_; + Boolean& has_at_; + + Traversal::Names names_; + Traversal::Inherits inherits_; + }; + + // + // + struct FacetArray: Traversal::Complex, Context + { + FacetArray (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& c) + { + Facets f; + FacetCollector col (f); + col.traverse (c); + + for (Facets::ConstIterator i (f.begin ()); i != f.end (); ++i) + { + if (i->first == L"fractionDigits") + os << "{::xsd::cxx::tree::facet::fraction_digits, " << + i->second << "UL}," << endl; + else if (i->first == L"totalDigits") + os << "{::xsd::cxx::tree::facet::total_digits, " << + i->second << "UL}," << endl; + } + } + + private: + typedef Cult::Containers::Map<String, String> Facets; + + struct FacetCollector: Traversal::Complex + { + FacetCollector (Facets& facets) + : facets_ (facets) + { + *this >> inherits_ >> *this; + } + + virtual Void + traverse (Type& c) + { + if (c.inherits_p ()) + { + // First collect our base so that we can override its + // facets. + // + inherits (c); + + using SemanticGraph::Restricts; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty ()) + { + Restricts::FacetIterator i (r->facet_find ("totalDigits")); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + + i = r->facet_find ("fractionDigits"); + + if (i != r->facet_end ()) + facets_[i->first] = i->second; + } + } + } + } + + private: + Traversal::Inherits inherits_; + Facets& facets_; + }; + }; + + // + // + struct Complex: Traversal::Complex, Context + { + Complex (Context& c) + : Context (c), + member_name_ (c), + any_ (c), + element_ (c), + any_test_ (c), + element_test_ (c), + attribute_ (c), + attribute_test_ (c), + any_attribute_ (c), + default_ctor_any_init_ (c), + default_ctor_member_init_ (c), + ctor_any_ (c), + ctor_member_ (c), + element_ctor_any_ (c), + element_ctor_member_ (c), + comparison_any_ (c), + comparison_member_ (c), + facet_array_ (c) + { + inherits_member_ >> member_name_; + + names_element_ >> element_; + if (options.value<CLI::generate_wildcard> ()) + names_element_ >> any_; + + names_element_test_ >> element_test_; + if (options.value<CLI::generate_wildcard> ()) + names_element_test_ >> any_test_; + + names_attribute_ >> attribute_; + names_attribute_test_ >> attribute_test_; + names_any_attribute_ >> any_attribute_; + + default_ctor_init_names_ >> default_ctor_member_init_; + if (options.value<CLI::generate_wildcard> ()) + default_ctor_init_names_ >> default_ctor_any_init_; + + ctor_names_ >> ctor_member_; + if (options.value<CLI::generate_wildcard> ()) + ctor_names_ >> ctor_any_; + + element_ctor_names_ >> element_ctor_member_; + if (options.value<CLI::generate_wildcard> ()) + element_ctor_names_ >> element_ctor_any_; + + comparison_names_ >> comparison_member_; + if (options.value<CLI::generate_wildcard> ()) + comparison_names_ >> comparison_any_; + } + + + virtual Void + traverse (Type& c) + { + String name (ename (c)); + + // If renamed name is empty then we do not need to generate + // anything for this type. + // + if (renamed_type (c, name) && !name) + return; + + Boolean string_based (false); + { + IsStringBasedType t (string_based); + t.dispatch (c); + } + + SemanticGraph::Enumeration* enum_base (0); + { + IsEnumBasedType t (enum_base); + t.dispatch (c); + } + + Boolean facets (false); + String base; // base type name + if (c.inherits_p ()) + { + // Get base name. + // + std::wostringstream o; + + BaseTypeName base_type (*this, o); + Traversal::Inherits inherits_type (base_type); + + // Cannot use inherits_none here because need the + // result in a string. + // + inherits (c, inherits_type); + + base = o.str (); + + // See if we have any facets that we need to handle. + // + using SemanticGraph::Restricts; + using SemanticGraph::Fundamental::Decimal; + + if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ())) + { + if (!r->facet_empty () && + (r->facet_find ("fractionDigits") != r->facet_end () || + r->facet_find ("totalDigits") != r->facet_end ()) && + ultimate_base (c).is_a<Decimal> ()) + facets = true; + } + } + else + base = any_type; + + os << "// " << name << endl + << "//" << endl + << endl; + + // + // + { + Member member (*this, name); + Traversal::Names names_member (member); + names (c, names_member); + } + + // facets + // + if (facets) + { + os << "static const ::xsd::cxx::tree::facet _xsd_" << name << + "_facet_table[] = " + << "{"; + + facet_array_.traverse (c); + + os << "{::xsd::cxx::tree::facet::none, 0UL}" + << "};"; + } + + // c-tors + // + Boolean generate_no_base_ctor (false); + { + GenerateWithoutBaseCtor t (generate_no_base_ctor); + t.traverse (c); + } + + Boolean has_complex_non_op_args (false); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, true, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + Boolean generate (false); + { + GenerateDefaultCtor t (*this, generate, generate_no_base_ctor); + t.traverse (c); + } + + if (generate) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << base << " ()"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, default_ctor_init_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + // c-tor (base, all-non-optional-members) + // + if (options.value<CLI::generate_from_base_ctor> ()) + { + Boolean generate (false); + { + GenerateFromBaseCtor t (*this, generate); + t.traverse (c); + } + + if (generate) + { + Boolean has_complex_non_op_args (false); + Boolean has_poly_non_op_args (false); + Boolean complex_poly_args_clash (true); + { + HasComplexPolyNonOptArgs t (*this, false, + has_complex_non_op_args, + has_poly_non_op_args, + complex_poly_args_clash); + t.traverse (c); + } + + String base_arg ( + L"_xsd_" + ename (c.inherits ().base ()) + L"_base"); + + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args (*this, FromBaseCtorArg::arg_type, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args ( + *this, FromBaseCtorArg::arg_complex_auto_ptr, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + os << name << "::" << endl + << name << " (const "; + inherits (c, inherits_member_); + os << "& " << base_arg; + { + FromBaseCtorArg args ( + *this, FromBaseCtorArg::arg_poly_auto_ptr, true); + Traversal::Names args_names (args); + names (c, args_names); + } + os << ")" << endl + << ": " << base << " (" << base_arg << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + } + + // c-tor (all-non-optional-members) + // + if (generate_no_base_ctor) + { + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. One case where + // this c-tor will be generated is restriction of anyType. + // + if (has_complex_non_op_args) + { + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_complex_auto_ptr, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + os << name << "::" << endl + << name << " ("; + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_poly_auto_ptr, true, true); + ctor_args.dispatch (c); + } + os << ")" << endl + << ": " << base << " ("; + { + CtorBase base (*this, ""); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + } + + if (string_based) + { + // We might not have the value type if this enum is customized. + // + if (enum_base != 0 && enum_base->context ().count ("value")) + { + // c-tor (enum-value, all-non-optional-members) + // + String base_arg (L"_xsd_" + ename (*enum_base) + L"_base"); + + os << name << "::" << endl + << name << " (" << fq_name (*enum_base) << "::" << + evalue (*enum_base) << " " << base_arg; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base"); + + // c-tor (const char*, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << char_type << "* " << base_arg; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + + // c-tor (const std::string&, all-non-optional-members) + // + os << name << "::" << endl + << name << " (const " << string_type << "& " << base_arg; + + { + CtorArgsWithoutBase ctor_args ( + *this, CtorArgsWithoutBase::arg_type, true, false); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // c-tor (ultimate-base, all-non-optional-members) + // + + os << name << "::" << endl + << name << " ("; + + String base_arg; + + { + CtorArgs ctor_args (*this, CtorArgs::arg_type, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // If we have any complex arguments in the previous c-tor + // then also generate the auto_ptr version. + // + if (has_complex_non_op_args) + { + os << name << "::" << endl + << name << " ("; + + String base_arg; + + { + CtorArgs ctor_args ( + *this, CtorArgs::arg_complex_auto_ptr, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + // If we are generating polymorphic code then we also need to + // provide auto_ptr version for every polymorphic type. + // + if (polymorphic && + has_poly_non_op_args && !complex_poly_args_clash) + { + os << name << "::" << endl + << name << " ("; + + String base_arg; + + { + CtorArgs ctor_args ( + *this, CtorArgs::arg_poly_auto_ptr, base_arg); + ctor_args.dispatch (c); + } + + os << ")" << endl + << ": " << base << " ("; + + { + CtorBase base (*this, base_arg); + Traversal::Inherits inherits_base (base); + + inherits (c, inherits_base); + } + + os << ")"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, ctor_names_); + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + } + + + // copy c-tor + // + + os << name << "::" << endl + << name << " (const " << name << "& x," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (x, f, c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + { + CopyAny copy_any (*this, "x"); + CopyMember copy_member (*this, "x"); + Traversal::Names names; + + names >> copy_member; + + if (options.value<CLI::generate_wildcard> ()) + names >> copy_any; + + Complex::names (c, names); + } + + os << "{"; + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + os << "}"; + + // + // + Boolean he (has<Traversal::Element> (c)); + Boolean hae (has<Traversal::Any> (c)); + + Boolean ha (has<Traversal::Attribute> (c)); + Boolean haa (has<Traversal::AnyAttribute> (c)); + + Boolean gen_wildcard (options.value<CLI::generate_wildcard> ()); + + // + // + if (!options.value<CLI::suppress_parsing> ()) + { + // c-tor (xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (e, f"; + + if (he || ha || hae || (haa && gen_wildcard)) + os << " | " << flags_type << "::base"; + + os << ", c)"; + + if (edom_document_member_p (c)) + { + os << "," << endl + << " " << edom_document_member (c) << " (" << + "::xsd::cxx::xml::dom::create_document< " << char_type << + " > ())"; + } + + names (c, element_ctor_names_); + + os << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);" + << endl; + + Boolean base_has_el (false), base_has_at (false); + + // We are only interested in this information if we are + // generating out own parse(). + // + if (he || ha || hae || (haa && gen_wildcard)) + { + if (c.inherits_p ()) + { + HasParseFunction test (*this, base_has_el, base_has_at); + test.dispatch (c.inherits ().base ()); + } + } + + //@@ throw if p is no exhausted at the end. + // + if (he || ha || hae || (haa && gen_wildcard)) + os << "if ((f & " << flags_type << "::base) == 0)" + << "{" + << parser_type << " p (e, " << + (he || hae || base_has_el ? "true, " : "false, ") << + (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false") + << ");" + << "this->" << unclash (name, "parse") << " (p, f);" + << "}"; + + os << "}"; + + Boolean simple (true); + { + IsSimpleType t (simple); + t.dispatch (c); + } + + if (simple) + { + // c-tor (xercesc::DOMAttr) + // + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMAttr& a," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (a, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + + // c-tor (string const&, xercesc::DOMElement) + // + os << name << "::" << endl + << name << " (const " << string_type << "& s," << endl + << "const " << xerces_ns << "::DOMElement* e," << endl + << flags_type << " f," << endl + << container << "* c)" << endl + << ": " << base << " (s, e, f, c)" + << "{"; + + if (facets) + os << "this->_facet_table (_xsd_" << name << "_facet_table);"; + + os << "}"; + } + + if (he || ha || hae || (haa && gen_wildcard)) + { + os << "void " << name << "::" << endl + << unclash (name, "parse") << " (" << + parser_type << "& p," << endl + << flags_type << + (he || ha || base_has_el || base_has_at ? " f" : "") << ")" + << "{"; + + // Allow the base to parse its part. + // + if (base_has_el || base_has_at) + os << "this->" << base << "::parse (p, f);" + << endl; + + if (he || hae) + { + os << "for (; p.more_elements (); p.next_element ())" + << "{" + << "const " << xerces_ns << "::DOMElement& i (" << + "p.cur_element ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_element_); + + os << "break;" + << "}"; + + // Make sure all non-optional elements are set. + // + names (c, names_element_test_); + } + + if (ha || (haa && gen_wildcard)) + { + if (base_has_at) + os << "p.reset_attributes ();" + << endl; + + os << "while (p.more_attributes ())" + << "{" + << "const " << xerces_ns << "::DOMAttr& i (" << + "p.next_attribute ());" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));" + << endl; + + names (c, names_attribute_); + + // Generate anyAttribute code after all the attributes. + // + if (gen_wildcard) + names (c, names_any_attribute_); + + + // os << "{" // else block + // @@ + // This doesn't play well with inheritance because we + // don't expect base's attributes. Also there are other + // "special" attributes such as xmlns, etc. + // + // << "throw ::xsd::cxx::tree::unexpected_attribute ... " + // << "}"; + + os << "}"; // while loop + + // Make sure all non-optional attributes are set. + // + names (c, names_attribute_test_); + } + + os << "}"; + } + } + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f," << endl + << container << "* c) const" + << "{" + << "return new class " << name << " (*this, f, c);" + << "}"; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Register with type factory map. + // + if (polymorphic && polymorphic_p (c) && !anonymous_p (c)) + { + // Note that we are using the original type name. + // + String const& name (ename (c)); + + if (!options.value<CLI::suppress_parsing> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_type_factory_init (" << endl + << strlit (c.name ()) << "," << endl + << strlit (xml_ns_name (c)) << ");" + << endl; + + if (options.value<CLI::generate_comparison> ()) + os << "static" << endl + << "const ::xsd::cxx::tree::comparison_initializer< 0, " << + char_type << ", " << name << " >" << endl + << "_xsd_" << name << "_comparison_init;" + << endl; + } + + // Comparison operators. + // + if (options.value<CLI::generate_comparison> () && + (he || ha || !c.inherits_p () || + ((hae || haa) && gen_wildcard))) + { + Boolean base_comp (false); + + if (c.inherits_p ()) + { + HasComparisonOperator test (*this, base_comp); + test.dispatch (c.inherits ().base ()); + } + + Boolean has_body (he || ha || base_comp || + ((hae || haa) && gen_wildcard)); + + os << "bool" << endl + << "operator== (const " << name << "&" << + (has_body ? " x" : "") << ", " << + "const " << name << "&" << (has_body ? " y" : "") << ")" + << "{"; + + if (base_comp) + os << "if (!(static_cast< const " << base << "& > (x) ==" << endl + << "static_cast< const " << base << "& > (y)))" << endl + << "return false;" + << endl; + + { + Complex::names (c, comparison_names_); + } + + os << "return true;" + << "}"; + + os << "bool" << endl + << "operator!= (const " << name << "& x, " << + "const " << name << "& y)" + << "{" + << "return !(x == y);" + << "}"; + } + } + + private: + Traversal::Inherits inherits_member_; + MemberTypeName member_name_; + + Traversal::Names names_element_; + Traversal::Names names_element_test_; + + Traversal::Names names_attribute_; + Traversal::Names names_any_attribute_; + Traversal::Names names_attribute_test_; + + Any any_; + Element element_; + + AnyTest any_test_; + ElementTest element_test_; + + Attribute attribute_; + AttributeTest attribute_test_; + + AnyAttribute any_attribute_; + + DefaultCtorAnyInit default_ctor_any_init_; + DefaultCtorMemberInit default_ctor_member_init_; + Traversal::Names default_ctor_init_names_; + + CtorAny ctor_any_; + CtorMember ctor_member_; + Traversal::Names ctor_names_; + + ElementCtorAny element_ctor_any_; + ElementCtorMember element_ctor_member_; + Traversal::Names element_ctor_names_; + + AnyComparison comparison_any_; + MemberComparison comparison_member_; + Traversal::Names comparison_names_; + + FacetArray facet_array_; + }; + + + // Generate element types and substitution group map entries. + // + struct GlobalElement: Traversal::Element, + GlobalElementBase, + Context + { + GlobalElement (Context& c) + : GlobalElementBase (c), + Context (c), + element_type_ (c.options.value<CLI::generate_element_type> ()), + element_map_ (c.options.value<CLI::generate_element_map> ()), + type_name_ (c) + { + belongs_ >> type_name_; + } + + virtual Void + traverse (Type& e) + { + if (element_type_ && doc_root_p (e)) + { + SemanticGraph::Type& t (e.type ()); + + Boolean fund (false); + { + IsFundamentalType test (fund); + test.dispatch (t); + } + + Boolean simple (true); + if (!fund) + { + IsSimpleType test (simple); + test.dispatch (t); + } + + String const& name (ename (e)); + String const& type (etype (e)); + String const& member (emember (e)); + + os << "// " << name << endl + << "// " << endl + << endl; + + // Virtual accessors. + // + os << "const " << any_type << "* " << name << "::" << endl + << "_value () const" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + os << any_type << "* " << name << "::" << endl + << "_value ()" + << "{"; + + if (fund) + os << "return 0;"; + else + os << "return &this->" << member << ".get ();"; + + os << "}"; + + // default c-tor + // + if (options.value<CLI::generate_default_ctor> ()) + { + os << name << "::" << endl + << name << " ()" << endl + << ": " << member << " (0, 0)" + << "{" + << "}"; + } + + // c-tor (value) + // + os << name << "::" << endl + << name << " (const " << type << "& x)" << endl + << ": " << member << " (x, 0, 0)" + << "{" + << "}"; + + + // c-tor (auto_ptr<value>) + // + if (!simple || (polymorphic && polymorphic_p (t))) + { + os << name << "::" << endl + << name << " (::std::auto_ptr< " << type << " > p)" << endl + << ": " << member << " (p, 0, 0)" + << "{" + << "}"; + } + + // c-tor (xercesc::DOMElement) + // + SemanticGraph::Context& ec (e.context ()); + String const& name_member (ec.get<String> ("element-name-member")); + String const& ns_member (ec.get<String> ("element-ns-member")); + + Boolean parsing (!options.value<CLI::suppress_parsing> ()); + if (parsing) + { + String const& tr (etraits (e)); + + os << name << "::" << endl + << name << " (const " << xerces_ns << "::DOMElement& e, " << + flags_type << " f)" << endl + << ": " << member << " (f, 0)" + << "{" + << "const " << qname_type << " n (" << endl + << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" + << endl + << "if (n.name () == " << name_member << " && " << + "n.namespace_ () == " << ns_member << ")" << endl + << "this->" << member << ".set (" << tr << + "::create (e, f, 0));" + << "else" << endl + << "throw ::xsd::cxx::tree::unexpected_element < " << + char_type << " > (" << endl + << "n.name (), n.namespace_ ()," << endl + << name_member << ", " << ns_member << ");" + << "}"; + } + + // copy c-tor + // + os << name << "::" << endl + << name << " (const " << name << "& x, " << + flags_type << " f)" << endl + << ": " << element_type << " ()," << endl + << " " << member << " (x." << member << ", f, 0)" + << "{" + << "}"; + + // _clone + // + os << name << "* " << name << "::" << endl + << "_clone (" << flags_type << " f) const" + << "{" + << "return new class " << name << " (*this, f);" + << "}"; + + // Element name and namespace accessors. + // + String const& aname (ec.get<String> ("element-name")); + String const& ans (ec.get<String> ("element-ns")); + + os << "const " << string_type << "& " << name << "::" << endl + << aname << " ()" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << ans << " ()" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_name () const" + << "{" + << "return " << name_member << ";" + << "}"; + + os << "const " << string_type << "& " << name << "::" << endl + << "_namespace () const" + << "{" + << "return " << ns_member << ";" + << "}"; + + os << "const " << string_type << " " << name << "::" << endl + << name_member << " (" << strlit (e.name ()) << ");" + << endl + << "const " << string_type << " " << name << "::" << endl + << ns_member << " (" << strlit (e.namespace_ ().name ()) << ");" + << endl; + + // d-tor + // + os << name << "::" << endl + << "~" << name << " ()" + << "{" + << "}"; + + // Element map registration. + // + if (element_map_ && parsing) + { + os << "static " << endl + << "const ::xsd::cxx::tree::parser_init< " << name << ", " << + char_type << ", " << any_type << " >" << endl + << "_xsd_" << name << "_parser_init (" << + name << "::" << aname << " (), " << + name << "::" << ans << " ());" + << endl; + } + } + + if (polymorphic && e.substitutes_p () && + !options.value<CLI::suppress_parsing> ()) + { + String const& name (ename (e)); + Type& r (e.substitutes ().root ()); + + os << "static" << endl + << "const ::xsd::cxx::tree::element_factory_initializer< 0, " << + char_type << ", "; + + belongs (e, belongs_); + + os << " >" << endl + << "_xsd_" << name << "_element_factory_init (" << endl + << strlit (r.name ()) << "," << endl + << strlit (r.namespace_ ().name ()) << "," << endl + << strlit (e.name ()) << "," << endl + << strlit (e.namespace_ ().name ()) << ");" + << endl + << endl; + } + } + + private: + Boolean element_type_; + Boolean element_map_; + Traversal::Belongs belongs_; + MemberTypeName type_name_; + }; + } + + Void + generate_tree_source (Context& ctx, + UnsignedLong first, + UnsignedLong last) + { + if (ctx.options.value<CLI::generate_wildcard> ()) + { + ctx.os << "#include <xsd/cxx/xml/dom/wildcard-source.hxx>" << endl + << endl; + } + + if (!ctx.options.value<CLI::suppress_parsing> ()) + ctx.os << "#include <xsd/cxx/xml/dom/parsing-source.hxx>" << endl + << endl; + + if (ctx.polymorphic) + { + Boolean parsing (!ctx.options.value<CLI::suppress_parsing> ()); + Boolean comparison (ctx.options.value<CLI::generate_comparison> ()); + + if (parsing) + ctx.os << "#include <xsd/cxx/tree/type-factory-map.hxx>" << endl + << endl; + + if (comparison) + ctx.os << "#include <xsd/cxx/tree/comparison-map.hxx>" << endl + << endl; + + if (parsing || comparison) + { + Boolean import_maps (ctx.options.value<CLI::import_maps> ()); + Boolean export_maps (ctx.options.value<CLI::export_maps> ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifndef XSD_NO_EXPORT" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{" + << "#ifdef _MSC_VER" << endl; + + if (parsing && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "type_factory_plate< 0, " << ctx.char_type << " >;"; + + if (parsing && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "type_factory_plate< 0, " << ctx.char_type << " >;"; + + if (comparison && export_maps) + ctx.os << "template struct __declspec (dllexport) " << + "comparison_plate< 0, " << ctx.char_type << " >;"; + + if (comparison && import_maps) + ctx.os << "template struct __declspec (dllimport) " << + "comparison_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl; + + if (parsing) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "type_factory_plate< 0, " << ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct __attribute__ ((visibility(\"default\"))) " << + "comparison_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl; + + if (parsing) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "type_factory_plate< 0, " << ctx.char_type << " >;"; + + if (comparison) + ctx.os << "template struct XSD_MAP_VISIBILITY " << + "comparison_plate< 0, " << ctx.char_type << " >;"; + + ctx.os << "#endif" << endl + << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // XSD_NO_EXPORT" << endl + << endl; + } + + ctx.os << "namespace _xsd" + << "{"; + + if (parsing) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::type_factory_plate< 0, " << + ctx.char_type << " >" << endl + << "type_factory_plate_init;" + << endl; + + if (comparison) + ctx.os << "static" << endl + << "const ::xsd::cxx::tree::comparison_plate< 0, " << + ctx.char_type << " >" << endl + << "comparison_plate_init;" + << endl; + + ctx.os << "}"; + } + } + + Traversal::Schema schema; + Traversal::Sources sources; + Traversal::Names names_ns, names; + Namespace ns (ctx, first, last); + + List list (ctx); + Union union_ (ctx); + Complex complex (ctx); + Enumeration enumeration (ctx); + GlobalElement element (ctx); + + schema >> sources >> schema; + schema >> names_ns >> ns >> names; + + names >> list; + names >> union_; + names >> complex; + names >> enumeration; + names >> element; + + schema.dispatch (ctx.schema_root); + } + } +} diff --git a/xsd/xsd/cxx/tree/tree-source.hxx b/xsd/xsd/cxx/tree/tree-source.hxx new file mode 100644 index 0000000..a1b4778 --- /dev/null +++ b/xsd/xsd/cxx/tree/tree-source.hxx @@ -0,0 +1,20 @@ +// file : xsd/cxx/tree/tree-source.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_TREE_SOURCE_HXX +#define CXX_TREE_TREE_SOURCE_HXX + +#include <cxx/tree/elements.hxx> + +namespace CXX +{ + namespace Tree + { + Void + generate_tree_source (Context&, UnsignedLong first, UnsignedLong last); + } +} + +#endif // CXX_TREE_TREE_SOURCE_HXX diff --git a/xsd/xsd/cxx/tree/validator.cxx b/xsd/xsd/cxx/tree/validator.cxx new file mode 100644 index 0000000..88451ba --- /dev/null +++ b/xsd/xsd/cxx/tree/validator.cxx @@ -0,0 +1,680 @@ +// file : xsd/cxx/tree/validator.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/validator.hxx> + +#include <cult/containers/set.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cxx/tree/elements.hxx> + +#include <iostream> + +using std::wcerr; + +namespace CXX +{ + namespace Tree + { + namespace + { + class ValidationContext: public Context + { + public: + ValidationContext (SemanticGraph::Schema& root, + SemanticGraph::Path const& path, + CLI::Options const& options, + const WarningSet& disabled_warnings, + Counts const& counts, + Boolean generate_xml_schema, + Boolean& valid_) + : Context (std::wcerr, + root, + path, + options, + counts, + generate_xml_schema, + 0, + 0, + 0, + 0), + disabled_warnings_ (disabled_warnings), + disabled_warnings_all_ (false), + valid (valid_), + subst_group_warning_issued (subst_group_warning_issued_), + subst_group_warning_issued_ (false) + { + if (disabled_warnings_.find ("all") != disabled_warnings_.end ()) + disabled_warnings_all_ = true; + } + + public: + Boolean + is_disabled (Char const* w) + { + return disabled_warnings_all_ || + disabled_warnings_.find (w) != disabled_warnings_.end (); + } + + public: + String + xpath (SemanticGraph::Nameable& n) + { + if (n.is_a<SemanticGraph::Namespace> ()) + return L"<namespace-level>"; // There is a bug if you see this. + + if (n.named_p ()) + { + SemanticGraph::Scope& scope (n.scope ()); + + if (scope.is_a<SemanticGraph::Namespace> ()) + return n.name (); + + return xpath (scope) + L"/" + n.name (); + } + else + { + return L"(anonymous type for " + + n.context ().get<String> ("instance-name") + L")"; + } + } + + protected: + ValidationContext (ValidationContext& c) + : Context (c), + disabled_warnings_ (c.disabled_warnings_), + disabled_warnings_all_ (c.disabled_warnings_all_), + valid (c.valid), + subst_group_warning_issued (c.subst_group_warning_issued) + { + } + + protected: + const WarningSet& disabled_warnings_; + Boolean disabled_warnings_all_; + + Boolean& valid; + + Boolean& subst_group_warning_issued; + Boolean subst_group_warning_issued_; + }; + + + // + // + struct Any: Traversal::Any, ValidationContext + { + Any (ValidationContext& c) + : ValidationContext (c) + { + } + + struct Element: Traversal::Element, ValidationContext + { + Element (ValidationContext& c, SemanticGraph::Any& any) + : ValidationContext (c), + any_ (any), + ns_ (any.definition_namespace ().name ()) + { + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) + return; + + using SemanticGraph::Any; + + Boolean q (e.qualified_p ()); + String ns (q ? e.namespace_ ().name () : ""); + + for (Any::NamespaceIterator i (any_.namespace_begin ()); + i != any_.namespace_end (); ++i) + { + Boolean failed (false); + + if (*i == L"##any") + { + failed = true; + } + else if (*i == L"##other") + { + if (ns_) + { + // Note that here I assume that ##other does not + // include names without target namespace. This + // is not what the spec says but that seems to be + // the consensus. + // + failed = q && ns != ns_; + } + else + { + // No target namespace. + // + failed = q && ns != L""; + } + } + else if (*i == L"##local") + { + failed = !q || ns == L""; + } + else if (*i == L"##targetNamespace") + { + failed = (q && ns_ == ns) || (!q && ns_ == L""); + } + else + { + failed = q && *i == ns; + } + + if (failed) + { + Any& a (any_); + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning T001: namespace '" << *i << "' allows for " + << "element '" << e.name () << "'" << endl; + + os << a.file () << ":" << a.line () << ":" << a.column () + << ": warning T001: generated code may not associate element '" + << e.name () << "' correctly if it appears in place of " + << "this wildcard" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: element '" << e.name () << "' is defined " + << "here" << endl; + } + } + } + + private: + SemanticGraph::Any& any_; + String ns_; + }; + + struct Complex: Traversal::Complex + { + Complex () + : up_ (true), down_ (true) + { + } + + virtual Void + post (Type& c) + { + // Go down the inheritance hierarchy. + // + if (down_) + { + Boolean up = up_; + up_ = false; + + if (c.inherits_p ()) + dispatch (c.inherits ().base ()); + + up_ = up; + } + + // Go up the inheritance hierarchy. + // + if (up_) + { + Boolean down = down_; + down_ = false; + + for (Type::BegetsIterator i (c.begets_begin ()); + i != c.begets_end (); ++i) + { + dispatch (i->derived ()); + } + + down_ = down; + } + } + + private: + Boolean up_, down_; + }; + + virtual Void + traverse (SemanticGraph::Any& a) + { + using SemanticGraph::Compositor; + + // Find our complex type. + // + Compositor* c (&a.contained_particle ().compositor ()); + + while(!c->contained_compositor_p ()) + c = &c->contained_particle ().compositor (); + + SemanticGraph::Complex& type ( + dynamic_cast<SemanticGraph::Complex&> ( + c->contained_compositor ().container ())); + + Complex complex; + Traversal::Names names; + Element element (*this, a); + + complex >> names >> element; + + complex.dispatch (type); + } + }; + + + // + // + struct Traverser: Traversal::Schema, + Traversal::Complex, + Traversal::Type, + Traversal::Element, + ValidationContext + { + Traverser (ValidationContext& c) + : ValidationContext (c), any_ (c) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_; + + names_ >> *this >> names_; + + // Any + // + if (!is_disabled ("T001")) + { + *this >> contains_compositor_ >> compositor_ >> contains_particle_; + contains_particle_ >> compositor_; + contains_particle_ >> any_; + } + } + + virtual Void + traverse (SemanticGraph::Complex& c) + { + using SemanticGraph::Schema; + + traverse (static_cast<SemanticGraph::Type&> (c)); + + if (c.inherits_p ()) + { + SemanticGraph::Type& t (c.inherits ().base ()); + + if (t.named_p () && + types_.find ( + t.scope ().name () + L"#" + t.name ()) == types_.end ()) + { + // Don't worry about types that are in included/imported + // schemas. + // + Schema& s (dynamic_cast<Schema&> (t.scope ().scope ())); + + if (&s == &schema_root || sources_p (schema_root, s)) + { + valid = false; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": error: type '" << xpath (c) << "' inherits from " + << "yet undefined type '" << xpath (t) << "'" << endl; + + os << t.file () << ":" << t.line () << ":" << t.column () + << ": info: '" << xpath (t) << "' is defined here" + << endl; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": info: inheritance from a yet-undefined type is " + << "not supported" << endl; + + os << c.file () << ":" << c.line () << ":" << c.column () + << ": info: re-arrange your schema and try again" + << endl; + } + } + } + + Complex::traverse (c); + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + // This is also used to traverse Complex. + // + if (t.named_p ()) + { + types_.insert (t.scope ().name () + L"#" + t.name ()); + } + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (is_disabled ("T002")) + return; + + // Note that there is no test for generate_p since we want + // to catch cases when things are not being generated but + // most likely should have been. + // + if (e.substitutes_p () && !polymorphic && + !subst_group_warning_issued) + { + subst_group_warning_issued = true; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": warning T002: substitution groups are used but " + << "--generate-polymorphic was not specified" << endl; + + os << e.file () << ":" << e.line () << ":" << e.column () + << ": info: generated code may not be able to handle " + << "some conforming instances" << endl; + } + } + + // Return true if root sources s. + // + Boolean + sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s) + { + using SemanticGraph::Schema; + using SemanticGraph::Sources; + + for (Schema::UsesIterator i (root.uses_begin ()); + i != root.uses_end (); ++i) + { + if (i->is_a<Sources> ()) + { + if (&i->schema () == &s || sources_p (i->schema (), s)) + return true; + } + } + + return false; + } + + private: + Containers::Set<String> types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + + // Any. + // + Any any_; + Traversal::Compositor compositor_; + Traversal::ContainsParticle contains_particle_; + Traversal::ContainsCompositor contains_compositor_; + }; + + + struct AnonymousType: Traversal::Schema, + Traversal::Complex, + Traversal::Element, + Traversal::Attribute, + ValidationContext + { + AnonymousType (ValidationContext& c) + : ValidationContext (c), + anonymous_error_issued_ (false) + { + *this >> sources_ >> *this; + *this >> schema_names_ >> ns_ >> names_ >> *this; + *this >> names_; + } + + Boolean + traverse_common (SemanticGraph::Member& m) + { + SemanticGraph::Type& t (m.type ()); + + if (!t.named_p () + && !t.is_a<SemanticGraph::Fundamental::IdRef> () + && !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) + { + if (!anonymous_error_issued_) + { + valid = false; + anonymous_error_issued_ = true; + + wcerr << t.file () + << ": error: anonymous types detected" + << endl; + + wcerr << t.file () + << ": info: " + << "anonymous types are not supported in this mapping" + << endl; + + wcerr << t.file () + << ": info: consider explicitly naming these types or " + << "remove the --preserve-anonymous option to " + << "automatically name them" + << endl; + + if (!options.value<CLI::show_anonymous> ()) + wcerr << t.file () + << ": info: use --show-anonymous option to see these " + << "types" << endl; + } + + return true; + } + + return false; + } + + virtual Void + traverse (SemanticGraph::Element& e) + { + if (skip (e)) return; + + if (traverse_common (e)) + { + if (options.value<CLI::show_anonymous> ()) + { + wcerr << e.file () << ":" << e.line () << ":" << e.column () + << ": error: element '" << xpath (e) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Element::traverse (e); + } + + virtual Void + traverse (SemanticGraph::Attribute& a) + { + if (traverse_common (a)) + { + if (options.value<CLI::show_anonymous> ()) + { + wcerr << a.file () << ":" << a.line () << ":" << a.column () + << ": error: attribute '" << xpath (a) << "' " + << "is of anonymous type" << endl; + } + } + else + Traversal::Attribute::traverse (a); + } + + private: + Boolean anonymous_error_issued_; + + Containers::Set<String> types_; + + Traversal::Sources sources_; + + Traversal::Names schema_names_; + Traversal::Namespace ns_; + + Traversal::Names names_; + }; + } + + Validator:: + Validator () + { + // Dummy ctor, helps with long symbols on HP-UX. + } + + Boolean Validator:: + validate (CLI::Options const& options, + SemanticGraph::Schema& schema, + SemanticGraph::Path const& path, + const WarningSet& disabled_warnings, + Counts const& counts) + { + Boolean valid (true); + ValidationContext ctx ( + schema, path, options, disabled_warnings, counts, false, valid); + + // + // + Boolean import_maps (options.value<CLI::import_maps> ()); + Boolean export_maps (options.value<CLI::export_maps> ()); + + if (import_maps && export_maps) + { + wcerr << "error: --import-maps and --export-maps are " + << "mutually exclusive" << endl; + + return false; + } + + if (import_maps && !ctx.polymorphic) + { + wcerr << "error: --import-maps can only be specified together with " + << "--generate-polymorphic" << endl; + + return false; + } + + if (export_maps && !ctx.polymorphic) + { + wcerr << "error: --export-maps can only be specified together " << + "with --generate-polymorphic" << endl; + + return false; + } + + // + // + if (options.value<CLI::char_type> () != "char" && + options.value<CLI::char_type> () != "wchar_t" && + !ctx.is_disabled ("T003")) + { + wcerr << "warning T003: unknown base character type '" << + options.value<CLI::char_type> ().c_str () << "'" << endl; + } + + // + // + NarrowString tn (options.value<CLI::type_naming> ()); + + if (tn != "knr" && tn != "ucc" && tn != "java") + { + wcerr << "error: unknown type naming style specified: '" << + tn.c_str () << "'" << endl; + + return false; + } + + NarrowString fn (options.value<CLI::function_naming> ()); + + if (fn != "knr" && fn != "lcc" && fn != "java") + { + wcerr << "error: unknown function naming style specified: '" << + fn.c_str () << "'" << endl; + + return false; + } + + // + // + Boolean element_type (options.value<CLI::generate_element_type> ()); + Boolean par (!options.value<CLI::suppress_parsing> ()); + Boolean ser (options.value<CLI::generate_serialization> ()); + + if (options.value<CLI::generate_element_map> ()) + { + if (!element_type) + { + wcerr << "error: --generate-element-map can only be specified " << + "together with --generate-element-type" << endl; + + return false; + } + + if (!(par || ser)) + { + wcerr << "error: --generate-element-map is specified but " << + "neither parsing nor serialization code is generated" << endl; + + return false; + } + } + + // Issue a warning if there are more than one global element + // and we are generating parsing/serialization functions or + // element types for all of them by default. + // + + if (counts.global_elements > 1 && + (element_type || par || ser) && + !options.value<CLI::root_element_first> () && + !options.value<CLI::root_element_last> () && + !options.value<CLI::root_element_all> () && + !options.value<CLI::root_element_none> () && + options.value<CLI::root_element> ().empty () && + !ctx.is_disabled ("T004")) + { + wcerr << schema.file () << ": warning T004: generating "; + + if (element_type) + wcerr << "element types"; + else + { + wcerr << (par ? "parsing " : "") << + (ser ? (par ? "and serialization " : "serialization ") : "") << + "functions"; + } + wcerr << " for " << counts.global_elements << " global elements" << + endl; + + wcerr << schema.file () << ": info: use --root-element-* options " + << "to specify document root(s)" << endl; + } + + + // Test for anonymout types. + // + { + AnonymousType traverser (ctx); + traverser.dispatch (schema); + } + + // Test the rest. + // + if (valid) + { + Traverser traverser (ctx); + traverser.dispatch (schema); + } + + return valid; + + // T005 is used in polymorphism-processor.cxx. + // + } + } +} diff --git a/xsd/xsd/cxx/tree/validator.hxx b/xsd/xsd/cxx/tree/validator.hxx new file mode 100644 index 0000000..da0c441 --- /dev/null +++ b/xsd/xsd/cxx/tree/validator.hxx @@ -0,0 +1,33 @@ +// file : xsd/cxx/tree/validator.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CXX_TREE_VALIDATOR_HXX +#define CXX_TREE_VALIDATOR_HXX + +#include <cxx/tree/elements.hxx> +#include <cxx/tree/cli.hxx> + +#include <xsd.hxx> + +namespace CXX +{ + namespace Tree + { + class Validator + { + public: + Validator (); // Dummy ctor, helps with long symbols on HP-UX. + + Boolean + validate (CLI::Options const& options, + SemanticGraph::Schema&, + SemanticGraph::Path const& tu, + const WarningSet& disabled_warnings, + Counts const& counts); + }; + } +} + +#endif // CXX_TREE_VALIDATOR_HXX |