Search code examples
c++xmlboosttinyxmlstreambuf

Boost streambuf to const char* with buffer_cast vs std::string vs ostringstream


I have a client/server application using boost::read_until with a boost::streambuf. I'm reading an XML message from a socket and want to parse this with tinyXML2 like so:

XMLDocument doc;
doc.parse(strPtr); // strPtr is const char* 

I need to somehow extract const char *strPtr from the streambuf. So far I found three methods here on stack exchange:

// method 1, string constructor
const char * streambufToPtr(boost::asio::streambuf &message) {
    boost::asio::streambuf::const_buffers_type bufs = message.data();
    std::string astr(boost::asio::buffers_begin(bufs), boost::asio::buffers_begin(bufs) + message.size());
    return astr.c_str();
}

// method 2, stringstream
const char * streambufToPtr(boost::asio::streambuf &message) {
    std::ostringstream ss;
    ss << &message;
    std::string astr = ss.str();
    return astr.c_str();
}

// method 3, buffer_cast
const char * streambufToPtr(boost::asio::streambuf &message) {
    const char* bufPtr=boost::asio::buffer_cast<const char*>(message.data());
    return bufPtr;
}

All three methods work in my code (so far). Method 1 and 2 probably copies the data at least once (or more), while method 3 does something else.

What goes on in each of the methods? How fast are they in comparison? Is any of these unsafer in terms of buffer overflows, threading or other traps I might run into later with a network client/server application?


Solution

  • What goes on in each of the methods?

    The first method copies the bytes into a std::string and returns a pointer to the underlying char array. This results in undefined behavior as the string is destroyed when the function returns, do not use it.

    The second method copies the bytes first into an ostringstream, then to a string (ss.str();) and then to yet another string (std::string astr =, although the compiler will probably elide the last copy). It also returns a pointer to something that will no longer exist when the function returns, do not use it.

    Your final function is simply returning a pointer to the underlying bytes of the buffer, and is the only one out of the three with well-defined behavior (assuming your streambuf outlives the char pointer you pass to tinyXML2, and isn't modified in the meantime).

    How fast are they in comparison? Is any of these unsafer in terms of buffer overflows, threading or other traps I might run into later with a network client/server application?

    These are moot because the other two functions are useless.