Search code examples
c++boostbuffer

Convert a streambuf to const_buffer


How do I "consume" a streambuf and thereby convert it to a const_buffer? Example:

const_buffer read(boost::shared_ptr<tcp::socket> sock)
{
    boost::system::error_code error;
    // getting response from server
    boost::asio::streambuf receive_buffer;
    boost::asio::read(*sock, receive_buffer, boost::asio::transfer_all(), error);
    if( error && error != boost::asio::error::eof ) {
        cout << "receive failed: " << error.message() << endl;
        exit(1);
    }
    else {
        // I want something like
        return const_buffer(receive_buffer);
    }
}

Being able to convert it to a mutable buffer is also ok.


Solution

  • const_buffer is not an owning data structure. Logically, you cannot consume the data and still have a const_buffer referencing it.

    You should probably use a container like std::string or std::vector:

    return std::string(buffers_begin(receive_buffer.data()),
                       buffers_end(receive_buffer.data()));
    // or
    return std::vector<uint8_t>(buffers_begin(receive_buffer.data()),
                                buffers_end(receive_buffer.data()));
    

    That said, since you're not interested in the dynamic streambuf, why use it?

    auto read(tcp::socket& sock) {
        std::string result;
        // std::vector<uint8_t> result;
    
        boost::system::error_code ec;
        asio::read(sock, asio::dynamic_buffer(result), ec);
    
        if (ec && ec != asio::error::eof) {
            std::cout << "receive failed: " << ec.message() << std::endl;
            exit(1);
        }
    
        return result;
    }
    

    That has the same effect but more efficiently.

    PS

    If you ever need a const_buffer referencing the chosen container type (std::string or std::vector), a simple asio::buffer(s) will do precisely that.