summaryrefslogtreecommitdiff
path: root/xsd/cxx/tree/stream-insertion-source.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xsd/cxx/tree/stream-insertion-source.cxx')
-rw-r--r--xsd/cxx/tree/stream-insertion-source.cxx532
1 files changed, 532 insertions, 0 deletions
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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 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, 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<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 && !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<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 && !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<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 && !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<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 && !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<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 << "#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);
+ }
+ }
+}