Search code examples
c++c++11boostcorbaboost-serialization

How to serialize TAO::unbouded_basic_string_sequence<T> using boost::serialization?


This does not work:

    template <class Archive, typename T>
    inline void save(Archive& arch, const TAO::unbounded_basic_string_sequence<T>& varSequence, unsigned int version)
    {
        size_t length = varSequence.length();
        arch & length & make_array(varSequence.get_buffer(), length);
    }

    template <class Archive, typename T>
    void load(Archive& arch, TAO::unbounded_basic_string_sequence<T>& varSequence, unsigned int version)
    {
        size_t length;
        arch & length;

        varSequence.length(length);
        arch & make_array(varSequence.get_buffer(), length);
    }


    template <class Archive, typename T>
    inline void serialize(Archive& arch, TAO::unbounded_basic_string_sequence<T>& varSequence, const unsigned int version)
        {
            split_free(arch, varSequence, version);
        }

The compiller says:

(..)/include/boost/serialization/access.hpp:118:9: error: request for member 'serialize' in 't', which is of non-class type 'char'

I know that C-style strings are not supported by boost::serialization. Theoretically I could use std::string for save(), but I do not know how to go back from std::string to TAO::unbouded_basic_string_sequence - there's almost no documentation for this class.


Solution

  • Your confusion seems to be that you expected the sequence to contain characters, whereas in reality it contains zero-terminated strings.

    From looking at the implementation code (indeed the documentation isn't very helpful) it seems like the Unbounded Basic String Sequence uses the String Traits to know how to operate on the strings.

    The traits for T = char indicate that the StringManager_T<T> class is used to "manage" strings. So, it's a convoluted setup in which the sequence stores raw pointers to "unowned" zero-terminated strings.

    However, implied through the trait is that all operations are done via the string_sequence_element proxy that uses the StringManager, and this emulates value-semantics for null-terminated strings. E.g. assignment is done like

    00055 {
    00056   CORBA::string_free (this->ptr_);
    00057   this->ptr_ = CORBA::string_dup (p);
    00058   return *this;
    00059 }
    

    I have no way to test the correct operation of this all, but here's a raw attempt you can try:

    namespace boost { namespace serialization {
    
        template <typename Archive, typename T>
            inline void save(Archive& ar, TAO::unbounded_basic_string_sequence<T> const& varSequence, unsigned int /*version*/)
            {
                ar & varSequence.length();
    
                std::basic_string<T> scratch;
                scratch.reserve(256); 
    
                for (size_t i = 0; i < varSequence.length(); ++i) {
                    scratch.assign(varSequence[i]); // assumes zero-terminated
                    ar & scratch;
                }
            }
    
        template <typename Archive, typename T>
            void load(Archive& ar, TAO::unbounded_basic_string_sequence<T>& varSequence, unsigned int /*version*/)
            {
                size_t length;
                ar & length;
                varSequence.length(length);
    
                std::basic_string<T> scratch;
                scratch.reserve(256); // some sane starting point?
    
                for (size_t i = 0; i < varSequence.length(); ++i) {
                    ar & scratch;
                    varSequence[i] = scratch.c_str();
                }
            }
    
        template <typename Archive, typename T>
            inline void serialize(Archive& ar, TAO::unbounded_basic_string_sequence<T>& varSequence, const unsigned int version)
            {
                split_free(ar, varSequence, version); 
            }
    
        template <typename Archive>
            inline void serialize(Archive& ar, SequenceOfString& sos, unsigned int /*version*/) {
                ar & base_object<TAO::unbounded_basic_string_sequence<char> >(sos);
            }