Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

alternatives to std::string to use with boost::asio

Tags:

c++

boost-asio

boost::asio's various read and write functions and methods accept boost::asio::buffer. According to buffer's documentation, a mutable std::string cannot be wrapped in boost::asio::buffer, and thus cannot be used for asio's read functions. This is probably due to the fact that std::string does not allow mutable access to its internal buffer (this was discussed previously here).

This is a shame, because std::string is a convenient way to represent mutable buffers of data in C++. Without it, we're either left with POD arrays, boost::array and std::vector<char>. The first two are inconvenient with variable-length messages. std::vector<char> can work, but it's an unnatural way to carry buffers of data around (*)

Questions:

  1. Are there other alternatives to std::string with boost::asio for reading buffers? Am I missing something here?
  2. I wonder why std::vector<char> is supported in a mutable buffer. Is it because it guarantees its internal buffer is contiguous in memory and allows mutable access to it with &vec[0] ?

Thanks in advance


(*) IMHO. Look at protobuf serialization for instance - it offers serialization into std::string but not into std::vector<char>, at least not explicitly.


EDIT: I ended up using vector<char> after all. protobuf allows serialization into a vector<char> by means of the SerializeToArray call which takes a pointer (&vec[0] can be passed there).

like image 513
Eli Bendersky Avatar asked Mar 09 '11 15:03

Eli Bendersky


2 Answers

Mutable access to a string buffer using &str[0] works fine on all known implementations, and the wording of the upcoming C++0x standardizes makes it officially allowed.

Still, I think you're insane to think that a std::vector is an unnatural representation for a variable-length buffer.

like image 147
Ben Voigt Avatar answered Nov 02 '22 04:11

Ben Voigt


This is to answer Eli's comment

I didn't mention asio::streambuf in my question originally, indeed because it wasn't 100% clear to me how to use it with fixed size reads and asio. Could you point to an example (or add one as an answer) of showing how to read fixed-length chunks into a std::sstream?

Here's a previous answer about using asio::streambuf and Boost.Serialization. The asio documentation also has an example of a synchronous read:

boost::asio::streambuf b;

// reserve 512 bytes in output sequence
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);

size_t n = sock.receive(bufs);

// received data is "committed" from output sequence to input sequence
b.commit(n);

std::istream is(&b);
std::string s;
is >> s;
like image 5
Sam Miller Avatar answered Nov 02 '22 04:11

Sam Miller