diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-05-21 19:18:52 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-05-21 19:18:52 +0200 |
commit | 9a764d4ed5606c5f171ae05a7409128a88184b11 (patch) | |
tree | 8f1c862354e5c6f112e7e52e3641ad87e4d276df /libxsd | |
parent | efb2476d01b2bcc62569c8748327754a836195c3 (diff) |
Pool polymorphic type-id strings in binary representations
Add support for an implicit string pool in istream and ostream
templates. Use this support to pool type namespace and name
when dealing with polymorphic types.
Diffstat (limited to 'libxsd')
-rw-r--r-- | libxsd/xsd/cxx/tree/istream.hxx | 46 | ||||
-rw-r--r-- | libxsd/xsd/cxx/tree/ostream.hxx | 47 | ||||
-rw-r--r-- | libxsd/xsd/cxx/tree/stream-extraction-map.txx | 27 | ||||
-rw-r--r-- | libxsd/xsd/cxx/tree/stream-insertion-map.txx | 19 |
4 files changed, 135 insertions, 4 deletions
diff --git a/libxsd/xsd/cxx/tree/istream.hxx b/libxsd/xsd/cxx/tree/istream.hxx index 07bba53..a4daa3e 100644 --- a/libxsd/xsd/cxx/tree/istream.hxx +++ b/libxsd/xsd/cxx/tree/istream.hxx @@ -6,6 +6,9 @@ #ifndef XSD_CXX_TREE_ISTREAM_HXX #define XSD_CXX_TREE_ISTREAM_HXX +#include <map> +#include <string> +#include <memory> // std::auto_ptr #include <cstddef> // std::size_t #include <xsd/cxx/tree/istream-fwd.hxx> @@ -138,6 +141,36 @@ namespace xsd return s_; } + // Add string to the pool. The application should add every + // potentially pooled string to correctly re-create the pool + // constructed during insertion. + // + template <typename C> + void + pool_add (const std::basic_string<C>& s) + { + typedef pool_impl<C> pool_type; + + if (pool_.get () == 0) + pool_.reset (new pool_type); + + pool_type& p (*static_cast<pool_type*> (pool_.get ())); + p.push_back (s); + } + + // Get string from pool id. We return the result via an argument + // instead of as a return type to avoid difficulties some compilers + // (e.g., GCC) experience with calls like istream<S>::pool_string<C>. + // + template <typename C> + void + pool_string (std::size_t id, std::basic_string<C>& out) + { + typedef pool_impl<C> pool_type; + pool_type& p (*static_cast<pool_type*> (pool_.get ())); + out = p[id - 1]; + } + public: // 8-bit // @@ -190,7 +223,20 @@ namespace xsd operator= (const istream&); private: + struct pool + { + virtual + ~pool () {} + }; + + template <typename C> + struct pool_impl: pool, std::vector<std::basic_string<C> > + { + }; + S& s_; + std::size_t seq_; + std::auto_ptr<pool> pool_; }; diff --git a/libxsd/xsd/cxx/tree/ostream.hxx b/libxsd/xsd/cxx/tree/ostream.hxx index cf2d9ee..7c76793 100644 --- a/libxsd/xsd/cxx/tree/ostream.hxx +++ b/libxsd/xsd/cxx/tree/ostream.hxx @@ -6,6 +6,9 @@ #ifndef XSD_CXX_TREE_OSTREAM_HXX #define XSD_CXX_TREE_OSTREAM_HXX +#include <map> +#include <string> +#include <memory> // std::auto_ptr #include <cstddef> // std::size_t namespace xsd @@ -126,7 +129,7 @@ namespace xsd public: explicit ostream (S& s) - : s_ (s) + : s_ (s), seq_ (1) { } @@ -136,13 +139,55 @@ namespace xsd return s_; } + // If the string is not in the pool, add it and return 0. Otherwise + // return the string's pool id. In the former case the application + // should serialize the original string. + // + // The returned ids are sequential and start with 1. 0 is reserved + // as a special marker to be used by the application for the first + // encounter of the string. + // + template <typename C> + std::size_t + pool_string (const std::basic_string<C>& s) + { + typedef pool_impl<C> pool_type; + + if (pool_.get () == 0) + pool_.reset (new pool_type); + + pool_type& p (*static_cast<pool_type*> (pool_.get ())); + + std::pair<typename pool_type::iterator, bool> r ( + p.insert (std::pair<std::basic_string<C>, std::size_t> (s, seq_))); + + if (!r.second) + return r.first->second; + + seq_++; + return 0; + } + private: ostream (const ostream&); ostream& operator= (const ostream&); private: + struct pool + { + virtual + ~pool () {} + }; + + template <typename C> + struct pool_impl: pool, std::map<std::basic_string<C>, std::size_t> + { + }; + S& s_; + std::size_t seq_; + std::auto_ptr<pool> pool_; }; diff --git a/libxsd/xsd/cxx/tree/stream-extraction-map.txx b/libxsd/xsd/cxx/tree/stream-extraction-map.txx index a4e429e..faabe7c 100644 --- a/libxsd/xsd/cxx/tree/stream-extraction-map.txx +++ b/libxsd/xsd/cxx/tree/stream-extraction-map.txx @@ -236,8 +236,31 @@ namespace xsd std::auto_ptr<type> stream_extraction_map<S, C>:: extract (istream<S>& s, flags f, container* c) { - std::basic_string<C> name, ns; - s >> ns >> name; + std::basic_string<C> ns, name; + + // The namespace and name strings are pooled. + // + std::size_t id; + istream_common::as_size<std::size_t> as_size (id); + s >> as_size; + + if (id != 0) + s.pool_string (id, ns); + else + { + s >> ns; + s.pool_add (ns); + } + + s >> as_size; + + if (id != 0) + s.pool_string (id, name); + else + { + s >> name; + s.pool_add (name); + } if (extractor e = find (qualified_name (name, ns))) { diff --git a/libxsd/xsd/cxx/tree/stream-insertion-map.txx b/libxsd/xsd/cxx/tree/stream-insertion-map.txx index 07bfa8b..d5799c2 100644 --- a/libxsd/xsd/cxx/tree/stream-insertion-map.txx +++ b/libxsd/xsd/cxx/tree/stream-insertion-map.txx @@ -269,7 +269,24 @@ namespace xsd { const qualified_name& qn (ti->name ()); - s << qn.namespace_ () << qn.name (); + // Pool the namespace and name strings. + // + const std::basic_string<C>& ns (qn.namespace_ ()); + const std::basic_string<C>& n (qn.name ()); + + std::size_t ns_id (s.pool_string (ns)); + std::size_t n_id (s.pool_string (n)); + + s << ostream_common::as_size<std::size_t> (ns_id); + + if (ns_id == 0) + s << ns; + + s << ostream_common::as_size<std::size_t> (n_id); + + if (n_id == 0) + s << n; + ti->inserter () (s, x); } else |