# Create a stringstream from cinder::Buffer (avoiding copying)

**URL:** <https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153>\
**Category:** Using Cinder\
**Created:** [July 12, 2016, 9:05pm UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153 "2016-07-12T21:05:24Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![sansumbrella](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/sansumbrella/32/30_2.png) [@sansumbrella](https://discourse.libcinder.org/u/sansumbrella)\
**Post date:** [July 12, 2016, 9:05pm UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/1 "2016-07-12T21:05:24Z")

</div>

I’m using the new OSC block to pass a [Cerealized](http://uscilab.github.io/cereal/) blob of binary data. My current issue is figuring out how to construct a valid stringstream from a ci::Buffer with minimal copying, and vice versa (as Cereal uses std::streams for data i/o).

For converting into a Buffer (handled by appendBlob), I’m fairly certain the following is the best I can hope for. Data is written into the stream, linearized into a string, then finally copied into the message buffer. Not _too_ bad, with two-ish copies.

```auto
std::stringstream ss(std::stringstream::binary | std::stringstream::out);
auto str = ss.str();
msg.appendBlob((void*)str.data(), str.size());

```

Going from Buffer to stringstream, things look a bit worse. The blob is copied out of the message, copied into a string, then copied into a stream before being deserialized. Three-ish copies before we start deserializing.

```auto
auto blob = msg[2].blob();
stringstream ss;
auto str = std::string((char*)blob.getData(), blob.getSize());
ss << str;
cereal::PortableBinaryInputArchive archive(ss);
archive(value, another);

```

Any advice on avoiding unnecessary copies is appreciated. I tried using `pubsetbuf` to use the Buffer directly within the stringstream, but without success.

Thanks.

---

<div class="post-metadata">

**Author:** ![ryanbartley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/ryanbartley/32/5_2.png) [@ryanbartley](https://discourse.libcinder.org/u/ryanbartley)\
**Post date:** [July 14, 2016, 12:51am UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/2 "2016-07-14T00:51:44Z")

</div>

`getArgBlobData` Doesn’t copy, which would reduce the number of copies but you’d have to keep the message within the full scope of use.

Does cereal really only allow a stringstream to interface with the library?

---

<div class="post-metadata">

**Author:** ![ryanbartley](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/ryanbartley/32/5_2.png) [@ryanbartley](https://discourse.libcinder.org/u/ryanbartley)\
**Post date:** [July 14, 2016, 1:07am UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/3 "2016-07-14T01:07:52Z")

</div>

Also, I don’t know if you have access to it but `string_view` could then be used to interface with stringstream negating another copy.

---

<div class="post-metadata">

**Author:** ![sansumbrella](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/sansumbrella/32/30_2.png) [@sansumbrella](https://discourse.libcinder.org/u/sansumbrella)\
**Post date:** [July 14, 2016, 3:29pm UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/4 "2016-07-14T15:29:13Z")

</div>

Yeah, Cereal really only works with [streams (any std::stream)](https://github.com/USCiLab/cereal/blob/master/include/cereal/archives/portable_binary.hpp#L120). Maybe I’ll open an issue there to ask about reading linear arrays of data as a stream.

I’ll have a look at using `string_view` in conjunction with getArgBlobData to at least reduce the number of copies. Perhaps there is also a `stream_view` that can wrap a linear array of data; would be handy here.

---

<div class="post-metadata">

**Author:** ![sansumbrella](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/sansumbrella/32/30_2.png) [@sansumbrella](https://discourse.libcinder.org/u/sansumbrella)\
**Post date:** [July 14, 2016, 7:04pm UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/5 "2016-07-14T19:04:44Z")

</div>

I found a solution when searching for “stream facade for buffer.” You can inherit from std::streambuf and provide a pointer to your custom buffer type to std::stream constructors. The custom buffer type gains access to a protected method that lets it set the buffer’s pointers in memory.

Mine looks like the following:

```auto
// Define a custom buffer type so you can point the memory of your choosing
class StreamView : public std::streambuf {
public:
    StreamView(char *data, size_t size) {
        this->setg(data, data, data + size);
    }
};
…
// pull data from OSC blob
const void* data;
size_t size;
msg[1].blobData(&data, &size);
// Construct a streambuf that points to our message blob data
StreamView view((char*)data, size);
std::istream stream(&view);

```

Referenced the following:  
[Beginner’s guide to streambuf](http://www.mr-edd.co.uk/blog/beginners_guide_streambuf)  
[C++ reference](http://www.cplusplus.com/reference/streambuf/streambuf/setg/)

---

<div class="post-metadata">

**Author:** ![sansumbrella](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/sansumbrella/32/30_2.png) [@sansumbrella](https://discourse.libcinder.org/u/sansumbrella)\
**Post date:** [July 14, 2016, 7:31pm UTC](https://discourse.libcinder.org/t/create-a-stringstream-from-cinder-buffer-avoiding-copying/153/6 "2016-07-14T19:31:55Z")

</div>

Note that the above is probably only a sane maneuver with input streams. If you tried writing to a stream with that buffer, you should be prepared for wild, undefined behavior and memory corruption.
