From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- xsd/cxx/tree/stream-insertion-source.cxx | 532 +++++++++++++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 xsd/cxx/tree/stream-insertion-source.cxx (limited to 'xsd/cxx/tree/stream-insertion-source.cxx') diff --git a/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/cxx/tree/stream-insertion-source.cxx new file mode 100644 index 0000000..87c7caa --- /dev/null +++ b/xsd/cxx/tree/stream-insertion-source.cxx @@ -0,0 +1,532 @@ +// file : xsd/cxx/tree/stream-insertion-source.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +#include +#include + +namespace CXX +{ + namespace Tree + { + namespace + { + typedef Containers::Vector Streams; + + struct List : Traversal::List, protected virtual 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 ()) + base += L", ::xsd::cxx::tree::schema_type::double_"; + else if (item_type.is_a ()) + base += L", ::xsd::cxx::tree::schema_type::decimal"; + + base += L" >"; + + UnsignedLong n (0); + Streams const& st (options.value ()); + 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 && !l.context ().count ("anonymous")) + { + // 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 + << L << strlit (l.name ()) << "," << endl + << L << 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, protected virtual 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 ()); + 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 && !u.context ().count ("anonymous")) + { + // 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 + << L << strlit (u.name ()) << "," << endl + << L << strlit (xml_ns_name (u)) << ");" + << endl; + } + } + } + }; + + + struct Enumeration : Traversal::Enumeration, protected virtual 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 ()); + 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 && !e.context ().count ("anonymous")) + { + // 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 + << L << strlit (e.name ()) << "," << endl + << L << strlit (xml_ns_name (e)) << ");" + << endl; + } + } + } + + private: + Traversal::Inherits inherits_base_; + BaseTypeName base_; + }; + + struct Element : Traversal::Element, protected virtual 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 or mapped to a fundamental C++ + // type 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 && !t.context ().count ("anonymous")); + + if (poly) + { + Boolean fund (false); + IsFundamentalType traverser (fund); + traverser.dispatch (t); + poly = !fund; + } + + 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, protected virtual Context + { + Attribute (Context& c) + : Context (c) + { + } + + virtual Void + traverse (Type& a) + { + String const& aname (eaname (a)); + + Boolean def (a.default_ () && !is_qname (a.type ())); + + if (a.optional () && !def) + { + os << "{" + << "bool p (x." << aname << " ());" + << "s << p;" + << "if (p)" << endl + << "s << *x." << aname << " ();" + << "}"; + } + else + { + os << "s << x." << aname << " ();"; + } + } + }; + + + struct Complex : Traversal::Complex, protected virtual 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 (c) || c.inherits_p ()); + + UnsignedLong n (0); + Streams const& st (options.value ()); + 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 && !c.context ().count ("anonymous")) + { + // 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 + << L << strlit (c.name ()) << "," << endl + << L << 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 ()); + + ctx.os << "#include " << endl + << endl; + + Boolean import_maps (ctx.options.value ()); + Boolean export_maps (ctx.options.value ()); + + if (import_maps || export_maps) + { + ctx.os << "#ifdef _MSC_VER" << endl + << endl + << "namespace xsd" + << "{" + << "namespace cxx" + << "{" + << "namespace tree" + << "{"; + + for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i) + { + String stream (*i); + + 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 << "}" // tree + << "}" // cxx + << "}" // xsd + << "#endif // _MSC_VER" << 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); + } + } +} -- cgit v1.1