summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-05-21 19:18:52 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-05-21 19:18:52 +0200
commit9a764d4ed5606c5f171ae05a7409128a88184b11 (patch)
tree8f1c862354e5c6f112e7e52e3641ad87e4d276df
parentefb2476d01b2bcc62569c8748327754a836195c3 (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.
-rw-r--r--libxsd/xsd/cxx/tree/istream.hxx46
-rw-r--r--libxsd/xsd/cxx/tree/ostream.hxx47
-rw-r--r--libxsd/xsd/cxx/tree/stream-extraction-map.txx27
-rw-r--r--libxsd/xsd/cxx/tree/stream-insertion-map.txx19
-rw-r--r--tests/cxx/tree/binary/polymorphic/driver.cxx15
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 <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
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 <iostream>
#include <typeinfo>
+#include <ace/Log_Msg.h> // ACE_HEX_DUMP
+
#include "test.hxx"
using namespace std;
@@ -35,6 +37,19 @@ main (int argc, char* argv[])
xml_schema::ostream<ACE_OutputCDR> 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);