From 9a764d4ed5606c5f171ae05a7409128a88184b11 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 21 May 2010 19:18:52 +0200 Subject: 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. --- libxsd/xsd/cxx/tree/istream.hxx | 46 ++++++++++++++++++++++++++ libxsd/xsd/cxx/tree/ostream.hxx | 47 ++++++++++++++++++++++++++- libxsd/xsd/cxx/tree/stream-extraction-map.txx | 27 +++++++++++++-- libxsd/xsd/cxx/tree/stream-insertion-map.txx | 19 ++++++++++- tests/cxx/tree/binary/polymorphic/driver.cxx | 15 +++++++++ 5 files changed, 150 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 +#include +#include // std::auto_ptr #include // std::size_t #include @@ -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 + void + pool_add (const std::basic_string& s) + { + typedef pool_impl pool_type; + + if (pool_.get () == 0) + pool_.reset (new pool_type); + + pool_type& p (*static_cast (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::pool_string. + // + template + void + pool_string (std::size_t id, std::basic_string& out) + { + typedef pool_impl pool_type; + pool_type& p (*static_cast (pool_.get ())); + out = p[id - 1]; + } + public: // 8-bit // @@ -190,7 +223,20 @@ namespace xsd operator= (const istream&); private: + struct pool + { + virtual + ~pool () {} + }; + + template + struct pool_impl: pool, std::vector > + { + }; + S& s_; + std::size_t seq_; + std::auto_ptr 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 +#include +#include // std::auto_ptr #include // 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 + std::size_t + pool_string (const std::basic_string& s) + { + typedef pool_impl pool_type; + + if (pool_.get () == 0) + pool_.reset (new pool_type); + + pool_type& p (*static_cast (pool_.get ())); + + std::pair r ( + p.insert (std::pair, 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 + struct pool_impl: pool, std::map, std::size_t> + { + }; + S& s_; + std::size_t seq_; + std::auto_ptr 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 stream_extraction_map:: extract (istream& s, flags f, container* c) { - std::basic_string name, ns; - s >> ns >> name; + std::basic_string ns, name; + + // The namespace and name strings are pooled. + // + std::size_t id; + istream_common::as_size 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& ns (qn.namespace_ ()); + const std::basic_string& 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 (ns_id); + + if (ns_id == 0) + s << ns; + + s << ostream_common::as_size (n_id); + + if (n_id == 0) + s << n; + ti->inserter () (s, x); } else diff --git a/tests/cxx/tree/binary/polymorphic/driver.cxx b/tests/cxx/tree/binary/polymorphic/driver.cxx index 3c3e057..1b537d1 100644 --- a/tests/cxx/tree/binary/polymorphic/driver.cxx +++ b/tests/cxx/tree/binary/polymorphic/driver.cxx @@ -11,6 +11,8 @@ #include #include +#include // ACE_HEX_DUMP + #include "test.hxx" using namespace std; @@ -35,6 +37,19 @@ main (int argc, char* argv[]) xml_schema::ostream ocdr (ace_ocdr); ocdr << *r; + /* + // Print the binary representation. + // + cerr << "binary representation size: " << ace_ocdr.total_length () << endl; + + for (const ACE_Message_Block* mb = ace_ocdr.begin (); + mb != 0; + mb = mb->cont ()) + { + ACE_HEX_DUMP ((LM_DEBUG, mb->rd_ptr (), mb->length ())); + } + */ + // Load from a CDR stream. // ACE_InputCDR ace_icdr (ace_ocdr); -- cgit v1.1