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:
auto data = static_cast<const char*>(src.data().data()); guaranteed to return a C string?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?
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
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.