// file : xsd/cxx/tree/fundamental-header.hxx // copyright : Copyright (c) 2005-2014 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 #include #include #include #include #include namespace CXX { namespace Tree { struct FundamentalNamespace : DocumentedNamespace, Traversal::AnyType, Traversal::AnySimpleType, Traversal::Fundamental::Byte, Traversal::Fundamental::UnsignedByte, Traversal::Fundamental::Short, Traversal::Fundamental::UnsignedShort, Traversal::Fundamental::Int, Traversal::Fundamental::UnsignedInt, Traversal::Fundamental::Long, Traversal::Fundamental::UnsignedLong, Traversal::Fundamental::Integer, Traversal::Fundamental::NonPositiveInteger, Traversal::Fundamental::NonNegativeInteger, Traversal::Fundamental::PositiveInteger, Traversal::Fundamental::NegativeInteger, Traversal::Fundamental::Boolean, Traversal::Fundamental::Float, Traversal::Fundamental::Double, Traversal::Fundamental::Decimal, Traversal::Fundamental::String, Traversal::Fundamental::NormalizedString, Traversal::Fundamental::Token, Traversal::Fundamental::Name, Traversal::Fundamental::NameToken, Traversal::Fundamental::NameTokens, Traversal::Fundamental::NCName, Traversal::Fundamental::Language, Traversal::Fundamental::Id, Traversal::Fundamental::IdRef, Traversal::Fundamental::IdRefs, Traversal::Fundamental::AnyURI, Traversal::Fundamental::QName, Traversal::Fundamental::Base64Binary, Traversal::Fundamental::HexBinary, Traversal::Fundamental::Date, Traversal::Fundamental::DateTime, Traversal::Fundamental::Duration, Traversal::Fundamental::Day, Traversal::Fundamental::Month, Traversal::Fundamental::MonthDay, Traversal::Fundamental::Year, Traversal::Fundamental::YearMonth, Traversal::Fundamental::Time, Traversal::Fundamental::Entity, Traversal::Fundamental::Entities, Context { FundamentalNamespace (Context& c) : DocumentedNamespace (c), Context (c), export_ (c.options.export_xml_schema () && type_exp) { *this >> names_ >> *this; if (export_) xs_ns_ = ns_name (xs_ns ()); } void gen_typedef (String const& name, String const& type, String const& arg1 = L"", String const& arg2 = L"", String const& arg3 = L"", bool export_type = true) { os << "typedef " << type; // Use unqualified arguments since we are in the same // namespace. // if (arg1) { os << arg1; if (arg2) { os << ", " << arg2; if (arg3) os << ", " << arg3; } os << " >"; } os << " " << name << ";"; if (export_type && export_ && type.find (L'<') != String::npos) { String s (type); // Use qualified arguments. // if (arg1) { s += xs_ns_; s += L"::"; s += arg1; if (arg2) { s += L", "; s += xs_ns_; s += L"::"; s += arg2; if (arg3) { s += L", "; s += xs_ns_; s += L"::"; s += arg3; } } s += " >"; } if (exports_set_.count (s) == 0) { exports_.push_back (s); exports_set_.insert (s); } } } String built_in_type (SemanticGraph::Type& t, String const& type, String const& arg1 = L"", String const& arg2 = L"", String const& arg3 = L"") { String custom; String name (ename (t)); // XML Schema built-in type customization is only possible when // we are generating separate header. // if (generate_xml_schema && custom_type (t, custom)) { if (custom.empty ()) custom = name; String new_name; renamed_type (t, new_name); if (new_name) { gen_typedef (new_name, type, arg1, arg2, arg3); if (doxygen) os << endl; } if (doxygen) os << "/**" << endl << " * @brief C++ type corresponding to the " << comment (t.name ()) << " XML Schema" << endl << " * built-in type." << endl << " */" << endl; if (custom == name) os << "class " << name << ";"; else os << "typedef " << custom << " " << name << ";"; if (doxygen) os << endl; } else { // Otherwise generate simple typedef. // if (doxygen) os << "/**" << endl << " * @brief C++ type corresponding to the " << comment (t.name ()) << " XML Schema" << endl << " * built-in type." << endl << " */" << endl; gen_typedef (name, type, arg1, arg2, arg3); if (doxygen) os << endl; } return name; } // anyType and anySimpleType // virtual void traverse (SemanticGraph::AnyType& t) { os << "// anyType and anySimpleType." << endl << "//" << endl; if (doxygen) os << endl; type_ = built_in_type (t, "::xsd::cxx::tree::type"); } virtual void traverse (SemanticGraph::AnySimpleType& t) { simple_type_ = built_in_type ( t, L"::xsd::cxx::tree::simple_type< " + char_type + L", ", type_); if (doxygen) os << "/**" << endl << " * @brief Alias for the anyType type." << endl << " */" << endl; gen_typedef (xs_ns ().context().get ("container"), "::xsd::cxx::tree::type"); os << endl; if (doxygen) os << endl; } // Integrals. // virtual void traverse (SemanticGraph::Fundamental::Byte& t) { os << "// 8-bit" << endl << "//" << endl; if (doxygen) os << endl; built_in_type (t, "signed char"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedByte& t) { built_in_type (t, "unsigned char"); os << endl; } virtual void traverse (SemanticGraph::Fundamental::Short& t) { os << "// 16-bit" << endl << "//" << endl; if (doxygen) os << endl; built_in_type (t, "short"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedShort& t) { built_in_type (t, "unsigned short"); os << endl; } virtual void traverse (SemanticGraph::Fundamental::Int& t) { os << "// 32-bit" << endl << "//" << endl; if (doxygen) os << endl; built_in_type (t, "int"); } virtual void traverse (SemanticGraph::Fundamental::UnsignedInt& t) { built_in_type (t, "unsigned int"); os << endl; } virtual void traverse (SemanticGraph::Fundamental::Long& t) { os << "// 64-bit" << endl << "//" < ("buffer"), L"::xsd::cxx::tree::buffer< " + char_type + L" >"); if (doxygen) os << endl; built_in_type ( t, L"::xsd::cxx::tree::base64_binary< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::HexBinary& t) { built_in_type ( t, L"::xsd::cxx::tree::hex_binary< " + char_type + L", ", simple_type_); os << endl; } // Date/time. // virtual void traverse (SemanticGraph::Fundamental::Date& t) { os << "// Date/time." << endl << "//" << endl; if (doxygen) os << endl << "/**" << endl << " * @brief Time zone type." << endl << " */" << endl; gen_typedef (xs_ns ().context().get ("time-zone"), "::xsd::cxx::tree::time_zone"); if (doxygen) os << endl; built_in_type ( t, L"::xsd::cxx::tree::date< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::DateTime& t) { built_in_type ( t, L"::xsd::cxx::tree::date_time< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::Duration& t) { built_in_type ( t, L"::xsd::cxx::tree::duration< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::Day& t) { built_in_type ( t, L"::xsd::cxx::tree::gday< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::Month& t) { built_in_type ( t, L"::xsd::cxx::tree::gmonth< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::MonthDay& t) { built_in_type ( t, L"::xsd::cxx::tree::gmonth_day< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::Year& t) { built_in_type ( t, L"::xsd::cxx::tree::gyear< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::YearMonth& t) { built_in_type ( t, L"::xsd::cxx::tree::gyear_month< " + char_type + L", ", simple_type_); } virtual void traverse (SemanticGraph::Fundamental::Time& t) { built_in_type ( t, L"::xsd::cxx::tree::time< " + char_type + L", ", simple_type_); os << endl; } // Entity. // virtual void traverse (SemanticGraph::Fundamental::Entity& t) { os << "// Entity." << endl << "//" << endl; if (doxygen) os << endl; entity_ = built_in_type ( t, L"::xsd::cxx::tree::entity< " + char_type + L", ", ncname_); } virtual void traverse (SemanticGraph::Fundamental::Entities& t) { built_in_type ( t, L"::xsd::cxx::tree::entities< " + char_type + L", ", simple_type_, entity_); os << endl; } virtual void post (SemanticGraph::Namespace& n) { SemanticGraph::Context& c (xs_ns ().context()); bool parsing (!options.suppress_parsing ()); bool serialization (options.generate_serialization ()); bool element_map (options.generate_element_map ()); { if (doxygen) os << endl << "/**" << endl << " * @brief Content order sequence entry." << endl << " */" << endl; gen_typedef (c.get ("content-order"), "::xsd::cxx::tree::content_order"); } if (options.generate_element_type ()) { if (doxygen) os << "/**" << endl << " * @brief Base class for element types." << endl << " */" << endl; else os << "// Base class for element types." << endl << "//" << endl; gen_typedef ( c.get ("element-type"), L"::xsd::cxx::tree::element_type< " + char_type + L", ", type_); os << endl; } if (element_map) { if (doxygen) os << "/**" << endl << " * @brief Root element map." << endl << " */" << endl; else os << "// Root element map." << endl << "//" << endl; gen_typedef ( c.get ("element-map"), L"::xsd::cxx::tree::element_map< " + char_type + L", ", type_); os << endl; } if (serialization) { os << "// Namespace information and list stream. Used in" << endl << "// serialization functions." << endl << "//" << endl; if (doxygen) os << "/**" << endl << " * @brief Namespace serialization information." << endl << " */" << endl; gen_typedef ( c.get ("namespace-info"), L"::xsd::cxx::xml::dom::namespace_info< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Namespace serialization information map." << endl << " */" << endl; gen_typedef (c.get ("namespace-infomap"), L"::xsd::cxx::xml::dom::namespace_infomap< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief List serialization stream." << endl << " */" << endl; gen_typedef ( c.get ("list-stream"), L"::xsd::cxx::tree::list_stream< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Serialization wrapper for the %double type." << endl << " */" << endl; // Do not export as_double and as_decimal since they are already // instantiated. // gen_typedef (c.get ("as-double"), L"::xsd::cxx::tree::as_double< ", double_, "", "", false); if (doxygen) os << endl << "/**" << endl << " * @brief Serialization wrapper for the %decimal type." << endl << " */" << endl; gen_typedef (c.get ("as-decimal"), L"::xsd::cxx::tree::as_decimal< ", decimal_, "", "", false); if (doxygen) os << endl << "/**" << endl << " * @brief Simple type facet." << endl << " */" << endl; gen_typedef (c.get ("facet"), "::xsd::cxx::tree::facet"); os << endl; } //@@ Can't change names of ostream/istream since they are // templates. // if (!options.generate_insertion ().empty ()) { if (doxygen) os << "/**" << endl << " * @brief Data representation output stream template." << endl << " */" << endl; else os << "// Data representation output stream template." << endl << "//" << endl; os << "using ::xsd::cxx::tree::ostream;" << endl; } if (!options.generate_extraction ().empty ()) { if (doxygen) os << "/**" << endl << " * @brief Data representation input stream template." << endl << " */" << endl; else os << "// Data representation input stream template." << endl << "//" << endl; os << "using ::xsd::cxx::tree::istream;" << endl; } os << "// Flags and properties." << endl << "//" << endl; if (doxygen) os << endl << "/**" << endl << " * @brief Parsing and serialization flags." << endl << " */" << endl; gen_typedef (c.get ("flags"), "::xsd::cxx::tree::flags"); if (doxygen) os << endl << "/**" << endl << " * @brief Parsing properties." << endl << " */" << endl; gen_typedef (c.get ("properties"), L"::xsd::cxx::tree::properties< " + char_type + L" >"); os << endl; // // if (parsing || serialization) { os << "// Parsing/serialization diagnostics." << endl << "//" << endl; if (doxygen) os << endl << "/**" << endl << " * @brief Error severity." << endl << " */" << endl; gen_typedef (c.get ("severity"), "::xsd::cxx::tree::severity"); if (doxygen) os << endl << "/**" << endl << " * @brief Error condition." << endl << " */" << endl; gen_typedef (c.get ("error"), L"::xsd::cxx::tree::error< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief List of %error conditions." << endl << " */" << endl; gen_typedef (c.get ("diagnostics"), L"::xsd::cxx::tree::diagnostics< " + char_type + L" >"); os << endl; } // // os << "// Exceptions." << endl << "//" << endl; if (doxygen) os << endl << "/**" << endl << " * @brief Root of the C++/Tree %exception hierarchy." << endl << " */" << endl; gen_typedef (c.get ("exception"), L"::xsd::cxx::tree::exception< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that the size argument exceeds" << endl << " * the capacity argument." << endl << " */" << endl; gen_typedef (c.get ("bounds"), L"::xsd::cxx::tree::bounds< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that a duplicate ID value" << endl << " * was encountered in the object model." << endl << " */" << endl; gen_typedef (c.get ("duplicate-id"), L"::xsd::cxx::tree::duplicate_id< " + char_type + L" >"); if (parsing) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating a parsing failure." << endl << " */" << endl; gen_typedef (c.get ("parsing"), L"::xsd::cxx::tree::parsing< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that an expected element" << endl << " * was not encountered." << endl << " */" << endl; gen_typedef ( c.get ("expected-element"), L"::xsd::cxx::tree::expected_element< " + char_type + L" >"); } if (parsing || serialization) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that an unexpected " << "element" << endl << " * was encountered." << endl << " */" << endl; gen_typedef ( c.get ("unexpected-element"), L"::xsd::cxx::tree::unexpected_element< " + char_type + L" >"); } if (parsing) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that an expected " << "attribute" << endl << " * was not encountered." << endl << " */" << endl; gen_typedef ( c.get ("expected-attribute"), L"::xsd::cxx::tree::expected_attribute< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that an unexpected " << "enumerator" << endl << " * was encountered." << endl << " */" << endl; gen_typedef ( c.get ("unexpected-enumerator"), L"::xsd::cxx::tree::unexpected_enumerator< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that the text content " << "was" << endl << " * expected for an element." << endl << " */" << endl; gen_typedef ( c.get ("expected-text-content"), L"::xsd::cxx::tree::expected_text_content< " + char_type + L" >"); if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that a prefix-namespace" << endl << " * mapping was not provided." << endl << " */" << endl; gen_typedef ( c.get ("no-prefix-mapping"), L"::xsd::cxx::tree::no_prefix_mapping< " + char_type + L" >"); } if (options.generate_polymorphic ()) { if (parsing || serialization) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that the type " << "information" << endl << " * is not available for a type." << endl << " */" << endl; gen_typedef ( c.get ("no-type-info"), L"::xsd::cxx::tree::no_type_info< " + char_type + L" >"); } if (parsing) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that the types are not" << endl << " * related by inheritance." << endl << " */" << endl; gen_typedef ( c.get ("not-derived"), L"::xsd::cxx::tree::not_derived< " + char_type + L" >"); } } if (element_map) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating that parsing or " << "serialization" << endl << " * information is not available for an element." << endl << " */" << endl; gen_typedef ( c.get ("no-element-info"), L"::xsd::cxx::tree::no_element_info< " + char_type + L" >"); } if (serialization) { if (doxygen) os << endl << "/**" << endl << " * @brief Exception indicating a serialization " << "failure." << endl << " */" << endl; gen_typedef ( c.get ("serialization"), L"::xsd::cxx::tree::serialization< " + char_type + L" >"); } os << endl; if (parsing || serialization) { if (doxygen) os << "/**" << endl << " * @brief Error handler callback interface." << endl << " */" << endl; else os << "// Error handler callback interface." << endl << "//" << endl; gen_typedef ( c.get ("error-handler"), L"::xsd::cxx::xml::error_handler< " + char_type + L" >"); os << endl; } if (parsing || serialization) { if (doxygen) os << "/**" << endl << " * @brief DOM interaction." << endl << " */" << endl; else os << "// DOM interaction." << endl << "//" << endl; os << "namespace dom" << "{"; // @@ Disregarding current naming convention by using the // fixed name (even in C++11, template alias is not yet // widely supported). // if (doxygen) os << "/**" << endl << " * @brief Automatic pointer for DOMDocument." << endl << " */" << endl; else os << "// Automatic pointer for DOMDocument." << endl << "//" << endl; if (std >= cxx_version::cxx11) os << "using ::xsd::cxx::xml::dom::unique_ptr;"; else os << "using ::xsd::cxx::xml::dom::auto_ptr;"; os << endl; if (parsing) { if (!generate_xml_schema) { String g (L"XSD_CXX_TREE_TREE_NODE_KEY" + ns_name (n)); std::transform (g.begin (), g.end(), g.begin (), upcase); g = escape (g); // Make it a C++ id. os << "#ifndef " << g << endl << "#define " << g << endl; } if (doxygen) os << "/**" << endl << " * @brief DOM user data key for back pointers to " << "tree nodes." << endl << " */" << endl; else os << "// DOM user data key for back pointers to tree nodes." << endl << "//" << endl; os << "const XMLCh* const " << c.get ("tree-node-key") << " = ::xsd::cxx::tree::user_data_keys::node;"; if (!generate_xml_schema) os << "#endif" << endl; } os << "}"; // namespace dom } if (element_map) { if (doxygen) os << "//@cond" << endl << endl; if (!generate_xml_schema) { String g (L"XSD_CXX_TREE_ELEMENT_MAP_INIT" + ns_name (n)); std::transform (g.begin (), g.end(), g.begin (), upcase); g = escape (g); // Make it a C++ id. os << "#ifndef " << g << endl << "#define " << g << endl; } os << "static" << endl << "const ::xsd::cxx::tree::element_map_init< " << char_type << ", " << type_ << " >" << endl << "_xsd_element_map_init;"; if (!generate_xml_schema) os << "#endif" << endl; if (doxygen) os << endl << "//@endcond" << endl; } Namespace::post (n); // Generate exports. // if (export_) { StringSet ns_set; for (StringList::const_iterator i (exports_.begin ()); i != exports_.end (); ++i) { String const& e (*i); // 12 is to skip ::xsd::cxx:: // ns_set.insert (String (e, 12, e.rfind (':', e.find ('<')) - 13)); } os << "#ifndef XSD_NO_EXPORT" << endl << endl << "namespace xsd" << "{" << "namespace cxx" << "{"; for (StringSet::const_iterator i (ns_set.begin ()); i != ns_set.end (); ++i) { String const& ns (*i); String prefix (L"::xsd::cxx::" + ns); size_t n (1); for (size_t b (0), e (ns.find (':')); ; n++) { os << "namespace " << String (ns, b, e) << "{"; if (e == String::npos) break; b = e + 2; e = ns.find (':', b); } for (StringList::const_iterator i (exports_.begin ()); i != exports_.end (); ++i) { String const& e (*i); String ens (e, 12, e.rfind (':', e.find ('<')) - 13); if (ns == ens) { String type (e, e.rfind (':', e.find ('<')) + 1); os << "template class " << type_exp << type << ";"; } } while (n--) os << "}"; } os << "}" // cxx << "}" // xsd << "#endif // XSD_NO_EXPORT" << endl << endl; } } private: typedef std::set StringSet; typedef std::vector StringList; bool export_; StringList exports_; StringSet exports_set_; String xs_ns_; Traversal::Names names_; String type_; String simple_type_; String string_; String norm_string_; String token_; String nmtoken_; String name_; String ncname_; String idref_; String uri_; String entity_; String double_; String decimal_; }; } } #endif // CXX_TREE_FUNDAMENTAL_HEADER_HXX