'is it safe to use boost::asio::streambuf as both an istream and an array as string_view?
For example, could there be problems with the memory work inside this buffer if I use code like this? Can I use the input stream and use sv (string_view) with the same streambuf?
boost::asio::streambuf buf_;
std::ostream out(&buf_);
int a = 1488;
out << a;
out << 33;
out << 100005l;
std::basic_string_view<uint8_t> arr_ {boost::asio::buffer_cast<const uint8_t *>(buf_.data()), buf_.size()};
std::istream in(&buf_);
int g;
in >> g;
int d = ArrayToValue<int>(&arr_[0]);
Since I expect the answer to be yes, would there be problems, and if so would not use string_view until the buffer is full? That is, use it along with the input stream, after it fills and read from that buffer!
Solution 1:[1]
streambuf::data()
returns a buffer sequence. So you can't be guaranteed to have string_view
to map its full capacity, in general.
The
basic_streambuf
class is derived fromstd::streambuf
to associate the streambuf's input and output sequences with one or more character arrays.
However, the docs go on to mention
The
basic_streambuf
class's public interface is intended to permit the following implementation strategies:
- A single contiguous character array, which is reallocated as necessary to accommodate changes in the size of the character sequence. This is the implementation approach currently used in Asio.
- A sequence of one or more character arrays, where each array is of the same size. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence.
- A sequence of one or more character arrays of varying sizes. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence.
(highlighting added)
So, iff you asserted your assumption then you might get away with this for now:
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
However, once you use std::istream
on the streambuf object, it will perform calls to basic_stream_buf::consume()
, which doesn't explicitly document that it will not reallocate.
However, the DynamicBuffer_v1 concept that this models documents:
x.consume(n) | Removes n bytes from beginning of the input sequence. If n is greater than the size of the input sequence, the entire input sequence is removed. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated. |
---|
So, in order to follow library patterns, it seems best not depend on the string_view to stay valid after reading from the istream
.
Note also that it would be best to limit scopes of the istream
/ostream
object:
boost::asio::streambuf buf_;
{
std::ostream out(&buf_);
int a = 1488;
out << a;
out << 33;
out << 100005l;
}
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
{
std::istream in(&buf_);
int g;
in >> g;
}
Or even:
int const a = 1488;
boost::asio::streambuf buf_;
std::ostream(&buf_) << a << 33 << 100005l;
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
int g;
std::istream(&buf_) >> g;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |