Can't get "write" to work when using IOStreams with custom streambuf

Hi, Boost is a really neat idea, I wish I had less trouble using it (so embarrasing...). Anyway, here's a streambuf class I wrote using IOStream : class CrIPCStreamOutput : public sink { public: CrIPCStreamOutput(RU8 * pio_pInputStorage , RS32 & pio_nStorageLen) : m_pBuffer(pio_pInputStorage), m_nBufferLen(pio_nStorageLen) { } virtual ~CrIPCStreamOutput() { } void write(const char * s , std::streamsize n) { if(!m_pBuffer) { m_nBufferLen = -1; return; } memcpy(m_pBuffer , s , n); m_nBufferLen = n; return; } private: unsigned char *& m_pBuffer; int & m_nBufferLen; }; In my main, I do: int main() { unsigned char p[256] = {0}; int n = sizeof(p); streambuf_facade<CrIPCStreamOutput> sbo(CrIPCStreamOutput(p , n)); //stream_facade<CrIPCStreamOutput> stro(CrIPCStreamOutput(p , n)); iostream stro(&sbo); stro.write("Hello?" , 6); cout << p << endl; return 0; } But the ouput from cout is an empty string, although when debugging I can see m_pBuffer being copied to. How can I get this to work? The motivation for the whole thing is serialization: I want to serialize a class using the boos.serialization lib, for which I need a stream, which has to have certain properties (not shown here). I need to have the archiver write to a specific buffer. IOStreams should do it (I got the reading side working fine), but how? Thanks.

Eyal Susser wrote:
Hi,
Boost is a really neat idea, I wish I had less trouble using it (so embarrasing...). Anyway, here's a streambuf class I wrote using IOStream :
<snip example>
But the ouput from cout is an empty string, although when debugging I can see m_pBuffer being copied to.
Hi,
Thanks for using the Iostreams library.
There are a few problems with you code:
The first, which you couldn't be expected to know, is that write() now returns a
streamsize value indicating how many characters were written.
Second, the character type of iostreams::source is char, not unsigned char. If
you want to use unsigned char, you can do:
class CrIPCStreamOutput {
public:
typedef unsigned char char_type;
typedef sink_tag io_category;
/* ... */
};
But be warned that standard libraries may not let you instantiate a
streambuf_facade with this char_type.
Third, you should flush the stream_facade after writing to it, to make sure that
buffered data has made its way to your sink.
Fourth, the implementation of write is unsafe, since you don't check for
overflow. Writing too many characters will lead to stack corruption.
Finally, and most importantly, you declare the member variable m_pBuffer as a
*reference* to a pointer. When you pass an instance of CrIPCStreamOutput to the
streambuf_facade constructor, a copy is made, and you end up with a reference to
a temporary pointer rather than the original pointer. Declaring m_pBuffer to
have type char* fixes this.
One last point is that if you want to define a stream which writes to a
preexisting buffer, you can use an array_sink, defined in the header
Thanks.
Jonathan

Jonathan Turkanis wrote:
Fourth, the implementation of write is unsafe, since you don't check for overflow. Writing too many characters will lead to stack corruption.
I forgot to mention that m_nBufferLen = n; should be m_nBufferLen += n; Jonathan

Thanks.
I'm using your code along with the serialization lib from boost.
Together, they seem to be pretty powerful. I used to think I was a
decent programmer, but you boost guys...what can I say. Hats off.
On 5/8/05, Jonathan Turkanis
Eyal Susser wrote:
Hi,
Boost is a really neat idea, I wish I had less trouble using it (so embarrasing...). Anyway, here's a streambuf class I wrote using IOStream :
<snip example>
But the ouput from cout is an empty string, although when debugging I can see m_pBuffer being copied to.
Hi,
Thanks for using the Iostreams library.
There are a few problems with you code:
The first, which you couldn't be expected to know, is that write() now returns a streamsize value indicating how many characters were written.
Second, the character type of iostreams::source is char, not unsigned char. If you want to use unsigned char, you can do:
class CrIPCStreamOutput { public: typedef unsigned char char_type; typedef sink_tag io_category; /* ... */ };
But be warned that standard libraries may not let you instantiate a streambuf_facade with this char_type.
Third, you should flush the stream_facade after writing to it, to make sure that buffered data has made its way to your sink.
Fourth, the implementation of write is unsafe, since you don't check for overflow. Writing too many characters will lead to stack corruption.
Finally, and most importantly, you declare the member variable m_pBuffer as a *reference* to a pointer. When you pass an instance of CrIPCStreamOutput to the streambuf_facade constructor, a copy is made, and you end up with a reference to a temporary pointer rather than the original pointer. Declaring m_pBuffer to have type char* fixes this.
One last point is that if you want to define a stream which writes to a preexisting buffer, you can use an array_sink, defined in the header
: iostreams::stream_facadeiostreams::array_sink out(buf, len);
Thanks.
Jonathan
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Eyal Susser wrote:
Thanks.
I'm using your code along with the serialization lib from boost. Together, they seem to be pretty powerful. I used to think I was a decent programmer, but you boost guys...what can I say. Hats off.
Thanks! (I gather your code is working now.) Jonathan
participants (2)
-
Eyal Susser
-
Jonathan Turkanis