diff options
Diffstat (limited to 'xsde/cxx/hybrid/tree-type-map.cxx')
-rw-r--r-- | xsde/cxx/hybrid/tree-type-map.cxx | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/xsde/cxx/hybrid/tree-type-map.cxx b/xsde/cxx/hybrid/tree-type-map.cxx new file mode 100644 index 0000000..990d62e --- /dev/null +++ b/xsde/cxx/hybrid/tree-type-map.cxx @@ -0,0 +1,248 @@ +// file : xsde/cxx/hybrid/tree-type-map.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/elements.hxx> +#include <cxx/hybrid/tree-type-map.hxx> + +#include <xsd-frontend/semantic-graph.hxx> +#include <xsd-frontend/traversal.hxx> + +#include <cult/containers/set.hxx> + +#include <iostream> + +namespace CXX +{ + namespace Hybrid + { + namespace + { + class Context: public CXX::Context + { + public: + Context (CLI::Options const& ops, SemanticGraph::Schema& root) + : CXX::Context (std::wcerr, + root, + "name", + "char", + ops.value<CLI::include_with_brackets> (), + ops.value<CLI::include_prefix> (), + "", // 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> ()) + { + } + + protected: + Context (Context& c) + : CXX::Context (c) + { + } + }; + + // + // + struct GlobalType: Traversal::Type, Context + { + GlobalType (Context& c, + TypeMap::Namespace* parser, + TypeMap::Namespace* serializer) + : Context (c), parser_ (parser), serializer_ (serializer) + { + } + + virtual Void + traverse (SemanticGraph::Type& t) + { + String const& xn (t.name ()); + String qn (fq_name (t)); + + if (parser_ != 0) + { + if (t.context ().get<Boolean> ("fixed")) + parser_->types_push_back (xn, qn); + else + parser_->types_push_back (xn, qn + L"*"); + } + + if (serializer_ != 0) + serializer_->types_push_back (xn, L"const " + qn + L"&"); + } + + private: + TypeMap::Namespace* parser_; + TypeMap::Namespace* serializer_; + }; + + + struct Namespace: Traversal::Namespace, Context + { + Namespace (Context& c, + String const* hxx_name, + TypeMap::Namespaces* parser_map, + TypeMap::Namespaces* serializer_map) + : Context (c), + hxx_name_ (hxx_name), + parser_map_ (parser_map), + serializer_map_ (serializer_map) + { + } + + virtual Void + traverse (Type& ns) + { + String include; + + if (hxx_name_ != 0) + include = process_include_path (*hxx_name_); + + String const& name (ns.name ()); + + if (parser_map_ != 0) + { + if (name) + parser_map_->push_back (TypeMap::Namespace (name)); + else + parser_map_->push_back ( + TypeMap::Namespace (TypeMap::Pattern ())); + + if (include) + parser_map_->back ().includes_push_back (include); + } + + if (serializer_map_ != 0) + { + if (name) + serializer_map_->push_back (TypeMap::Namespace (name)); + else + serializer_map_->push_back ( + TypeMap::Namespace (TypeMap::Pattern ())); + + if (include) + serializer_map_->back ().includes_push_back (include); + } + + GlobalType type (*this, + (parser_map_ ? &parser_map_->back () : 0), + (serializer_map_ ? &serializer_map_->back () : 0)); + + Traversal::Names names (type); + Namespace::names (ns, names); + } + + private: + String const* hxx_name_; + TypeMap::Namespaces* parser_map_; + TypeMap::Namespaces* serializer_map_; + }; + + // 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 (SemanticGraph::Schema& root) + { + schema_set_.insert (&root); + } + + virtual Void + traverse (SemanticGraph::Sources& sr) + { + SemanticGraph::Schema& s (sr.schema ()); + SemanticGraph::Context& sc (s.context ()); + + if (!sc.count ("cxx-hybrid-tree-type-map-seen")) + { + sc.set ("cxx-hybrid-tree-type-map-seen", true); + Traversal::Sources::traverse (sr); + sc.remove ("cxx-hybrid-tree-type-map-seen"); + } + } + + virtual Void + traverse (SemanticGraph::Includes& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (schema_set_.find (&s) == schema_set_.end ()) + { + schema_set_.insert (&s); + Traversal::Includes::traverse (i); + } + } + + virtual Void + traverse (SemanticGraph::Imports& i) + { + SemanticGraph::Schema& s (i.schema ()); + + if (schema_set_.find (&s) == schema_set_.end ()) + { + schema_set_.insert (&s); + Traversal::Imports::traverse (i); + } + } + + private: + Containers::Set<SemanticGraph::Schema*> schema_set_; + }; + } + + Void + generate_tree_type_map (CLI::Options const& ops, + XSDFrontend::SemanticGraph::Schema& tu, + String const& hxx_name, + TypeMap::Namespaces& parser_map, + TypeMap::Namespaces& serializer_map) + { + if (tu.names_begin ()->named ().name () != + L"http://www.w3.org/2001/XMLSchema") + { + Context ctx (ops, tu); + + // We don't want include in the included/imported/sources + // schema so split the traversal into two part. + // + Traversal::Schema schema; + Traversal::Schema used_schema; + Uses uses (tu); + + schema >> uses >> used_schema >> uses; + + Traversal::Names schema_names; + Namespace ns ( + ctx, &hxx_name, + (ops.value<CLI::generate_parser> () ? &parser_map : 0), + (ops.value<CLI::generate_serializer> () ? &serializer_map : 0)); + + schema >> schema_names >> ns; + + Traversal::Names used_schema_names; + Namespace used_ns ( + ctx, 0, + (ops.value<CLI::generate_parser> () ? &parser_map : 0), + (ops.value<CLI::generate_serializer> () ? &serializer_map : 0)); + + used_schema >> used_schema_names >> used_ns; + + // Some twisted schemas do recusive self-inclusion. + // + SemanticGraph::Context& tuc (tu.context ()); + + tuc.set ("cxx-hybrid-tree-type-map-seen", true); + schema.dispatch (tu); + tuc.remove ("cxx-hybrid-tree-type-map-seen"); + } + } + } +} |