c++boostboost-asio

Copy boost::asio::streambuf using std::ostream


I need to copy one boost::asio::streambuf to another. For this I decided to use std::ostream. At the moment I copy the buffer like this

boost::asio::streambuf src;
boost::asio::streambuf dst;

std::ostream os1(&src);
os1 << "hello";

std::ostream os2(&dst);
auto data = static_cast<const char*>(src.data().data());
os2 << data;
std::cout << dst.size() << std::endl; // 5

Data is copied correctly, dst.size() returns 5. But I'm not sure if it's correct to do so. In this regard, I have two questions:

  1. Is the line auto data = static_cast<const char*>(src.data().data()); guaranteed to return a C string?
  2. If not, how does os2 << data know about end of data? Is there UB in my code or not?

In general, I am interested in whether my code has UB or not? Maybe I need to create an intermediate string like this and copy from it?

boost::asio::streambuf src;
boost::asio::streambuf dst;

std::ostream os1(&src);
os1 << "hello";

std::ostream os2(&dst);
auto data = static_cast<const char*>(src.data().data());
std::string tmp(data, src.size());
os2 << tmp;
std::cout << dst.size() << std::endl; // 5

If I need to create an intermediate string, are there other efficient ways to copy?


Solution

  • The good news is that streambuf models the standard library concept! So, you can "just" use overload 17:

    #include <boost/asio.hpp>
    
    int main() {
        boost::asio::streambuf src, dst;
    
        std::ostream(&src) << "hello";
        std::ostream(&dst) << &src;
    
        assert(dst.size() == 5);
    }
    

    See it Live On Coliru


    NOTES

    Yes your original had UB. This would be "fine":

    auto data = static_cast<const char*>(src.data().data());
    os2.write(data, src.size());
    

    However, I don't recommend it because it assumes that src.data() is a single-element buffer sequence. See is it safe to use boost::asio::streambuf as both an istream and an array as string_view? for much more background.