468,727 Members | 1,668 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,727 developers. It's quick & easy.

streambuf :: getting the data back from a custom stream

For a particular application of mine - I need a simulation of byte
array output stream.

* write data onto a stream
* getback the contiguous content as an array later for network
transport.

My code looks as follows.

#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>

using namespace std;
class outbuf : public std::streambuf
{
public:
virtual ~outbuf()
{
sync();
}
char * getData() const
{
std::cout << "First " << std::hex << (void *)pbase() ;
std::cout << "Current " << std::hex << (void *)pptr() ;

return pbase();
}

streamsize getSize() const
{
return pbase() - pptr();
}
};

class myostream : public std::basic_ostream<char>
{

public:
myostream() :
basic_ostream<char>(new outbuf)
{
}
~myostream()
{
delete rdbuf();
}
};

int main()
{

myostream out;

out << "31 hexadecimal: " << std::hex << 31 << "\n";
st = out.rdbuf();
buf = dynamic_cast<outbuf *>(st);
if (!buf)
{
cerr << "error: dynamic_Cast failed";
return EXIT_FAILURE;
}

//TODO: At this point - I need to get the pointer to the beginning
of the buffer and the size of the same.
buf->getData();

cerr << "Size: " << buf->getSize() << endl;

return 0;
}
I had gone about creating a rudimentary derived class implementation
of streambuf and an output stream.
After writing data to the output stream I need to get the number of
bytes written and the pointer to the beginning of the stream. How do I
go about doing the same ??

The above example does not seem to work btw.

Thanks for the help.

Nov 10 '07 #1
4 5977
<ra***********@gmail.comwrote in message
news:11**********************@e9g2000prf.googlegro ups.com...
For a particular application of mine - I need a simulation of byte
array output stream.

* write data onto a stream
* getback the contiguous content as an array later for network
transport.

My code looks as follows.

#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>

using namespace std;
class outbuf : public std::streambuf
{
public:
virtual ~outbuf()
{
sync();
}
char * getData() const
{
std::cout << "First " << std::hex << (void *)pbase() ;
std::cout << "Current " << std::hex << (void *)pptr() ;

return pbase();
}

streamsize getSize() const
{
return pbase() - pptr();
}
};

class myostream : public std::basic_ostream<char>
{

public:
myostream() :
basic_ostream<char>(new outbuf)
{
}
~myostream()
{
delete rdbuf();
}
};

int main()
{

myostream out;

out << "31 hexadecimal: " << std::hex << 31 << "\n";
st = out.rdbuf();
buf = dynamic_cast<outbuf *>(st);
if (!buf)
{
cerr << "error: dynamic_Cast failed";
return EXIT_FAILURE;
}

//TODO: At this point - I need to get the pointer to the beginning
of the buffer and the size of the same.
buf->getData();

cerr << "Size: " << buf->getSize() << endl;

return 0;
}
I had gone about creating a rudimentary derived class implementation
of streambuf and an output stream.
After writing data to the output stream I need to get the number of
bytes written and the pointer to the beginning of the stream. How do I
go about doing the same ??

The above example does not seem to work btw.

Thanks for the help.
I may be missing something, but why don't you just use stringstream?

#include <sstream>
#include <iostream>
#include <string>

int main()
{

std::stringstream out;

out << "31 hexadecimal: " << std::hex << 31 << "\n";

std::cout << "Size: " << out.str().size() << std::endl;
std::cout << "Data: " << out.str() << std::endl;

return 0;
}

Output:
Size: 19
Data: 31 hexadecimal: 1f
Nov 10 '07 #2
On Nov 9, 10:39 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
<rakesh.use...@gmail.comwrote in message

news:11**********************@e9g2000prf.googlegro ups.com...
For a particular application of mine - I need a simulation of byte
array output stream.
* write data onto a stream
* getback the contiguous content as an array later for network
transport.
My code looks as follows.
#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>
using namespace std;
class outbuf : public std::streambuf
{
public:
virtual ~outbuf()
{
sync();
}
char * getData() const
{
std::cout << "First " << std::hex << (void *)pbase() ;
std::cout << "Current " << std::hex << (void *)pptr() ;
return pbase();
}
streamsize getSize() const
{
return pbase() - pptr();
}
};
class myostream : public std::basic_ostream<char>
{
public:
myostream() :
basic_ostream<char>(new outbuf)
{
}
~myostream()
{
delete rdbuf();
}
};
int main()
{
myostream out;
out << "31 hexadecimal: " << std::hex << 31 << "\n";
st = out.rdbuf();
buf = dynamic_cast<outbuf *>(st);
if (!buf)
{
cerr << "error: dynamic_Cast failed";
return EXIT_FAILURE;
}
//TODO: At this point - I need to get the pointer to the beginning
of the buffer and the size of the same.
buf->getData();
cerr << "Size: " << buf->getSize() << endl;
return 0;
}
I had gone about creating a rudimentary derived class implementation
of streambuf and an output stream.
After writing data to the output stream I need to get the number of
bytes written and the pointer to the beginning of the stream. How do I
go about doing the same ??
The above example does not seem to work btw.
Thanks for the help.

I may be missing something, but why don't you just use stringstream?

#include <sstream>
#include <iostream>
#include <string>

int main()
{

std::stringstream out;

out << "31 hexadecimal: " << std::hex << 31 << "\n";

std::cout << "Size: " << out.str().size() << std::endl;
std::cout << "Data: " << out.str() << std::endl;

return 0;

}

Output:
Size: 19
Data: 31 hexadecimal: 1f

Sorry for mentioning the additional criteria.. My intention is to
have a stream to write binary data and not text data. istringstreams
serve the purpose except that they write text data. I am not sure how
binary data would actually work.
I am looking for something like ibytestream / obytestream .

Nov 10 '07 #3
On Nov 10, 2:28 am, rakesh.use...@gmail.com wrote:
For a particular application of mine - I need a simulation of byte
array output stream.
* write data onto a stream
* getback the contiguous content as an array later for network
transport.
That sounds like stringstream to me. Otherwise, you might want
the old strstream.

Of course, if you really want to (e.g. you have other
constraits), it's pretty trivial to implement a streambuf which
writes to a vector<char>.
My code looks as follows.
#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>
using namespace std;
class outbuf : public std::streambuf
{
public:
virtual ~outbuf()
{
sync();
}
Is the contiguous array owned by outbuf, or is it provided by
the client? I don't see any constructor, so it must be owned by
outbuf. On the other hand, I don't see any private data members
either, which makes me wonder: even if the buffer is owned by
the client, you have to save a pointer to it, or something.

Anyway, if the buffer is owned by outbuf, the sych isn't
necessary, since the buffer(s) won't exist after the destructor.
And for in memory streambuf work, sych is normally a no-op
anyway; the buffer is always synchronized.
char * getData() const
{
std::cout << "First " << std::hex << (void *)pbase() ;
std::cout << "Current " << std::hex << (void *)pptr() ;
I have doubts that std::hex actually affects the output of a
pointer. (It's implementation defined, but I'd always output
pointers in hex, regardless of the base.) If you do want to set
it, however, be sure to restore the base field to its initial
value. (Of course, I'm supposing that these statements are only
here for debugging purposes.)

As currently written, it is guaranteed that pbase and pptr are
always null.
return pbase();
}
streamsize getSize() const
{
return pbase() - pptr();
}
};
And where is your data, or the virtual functions you need to
override (overflow, at least).
class myostream : public std::basic_ostream<char>
{
public:
myostream() :
basic_ostream<char>(new outbuf)
{
}
~myostream()
{
delete rdbuf();
}

};
It's not really necessary to use dynamic allocation here,
although the alternatives are a bit tricky (since we should
ensure that outbuf is constructed before passing its address to
the ostream constructor.
int main()
{
myostream out;
out << "31 hexadecimal: " << std::hex << 31 << "\n";
st = out.rdbuf();
buf = dynamic_cast<outbuf *>(st);
if (!buf)
{
cerr << "error: dynamic_Cast failed";
return EXIT_FAILURE;
}
//TODO: At this point - I need to get the pointer to the beginning
of the buffer and the size of the same.
buf->getData();
cerr << "Size: " << buf->getSize() << endl;
return 0;
}
I had gone about creating a rudimentary derived class implementation
of streambuf and an output stream.
After writing data to the output stream I need to get the number of
bytes written and the pointer to the beginning of the stream. How do I
go about doing the same ??
You might start by allocating a buffer somewhere, and managing
it.
The above example does not seem to work btw.
Obviously. How can it if you don't override overflow? Maybe
something like the following:

class ArrayStreambuf : public std::streambuf
{
public:
typedef std::vector<char>::const_iterator
iterator ;
iterator begin() const
{
return myBuffer.begin() ;
}

iterator end() const
{
return myBuffer.end() ;
}

protected:
virtual int overflow( int ch )
{
if ( ch != EOF ) {
myBuffer.push_back( ch ) ;
size_t start = myBuffer.size() ;
myBuffer.resize( myBuffer.capacity() ) ;
setp( &myBuffer[ 0 ] + start,
&myBuffer[ 0 ] + myBuffer.size() ) ;
}
return ch == EOF ? 0 : ch ;
}

private:
std::vector< char myBuffer ;
} ;

The above simply uses the normal std::vector growth scheme. You
may want something different. Maybe add a constructor which
initializes the buffer to a minium size and calls setp, or
resize to std::max( capacity(), size() + someMinimumIncrement ).
or whatever your application requires.

Similarly, you may want to access the buffer otherwise than
through its iterators. Returning the address of the first
element and the size, for example, will allow calling the low
level system write function directly.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 11 '07 #4
On Nov 10, 6:32 pm, Rakesh Kumar <rakesh.use...@gmail.comwrote:
On Nov 9, 10:39 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
I may be missing something, but why don't you just use stringstream?
#include <sstream>
#include <iostream>
#include <string>
int main()
{
std::stringstream out;
out << "31 hexadecimal: " << std::hex << 31 << "\n";
std::cout << "Size: " << out.str().size() << std::endl;
std::cout << "Data: " << out.str() << std::endl;
return 0;
}
Output:
Size: 19
Data: 31 hexadecimal: 1f
Sorry for mentioning the additional criteria.. My intention is to
have a stream to write binary data and not text data.
And how is that relevant. filebuf is the only standard stream
which makes a distinction (and your example still formatted the
data as text).
istringstreams serve the purpose except that they write text
data. I am not sure how binary data would actually work.
I am looking for something like ibytestream / obytestream .
In that case, istream and ostream aren't really what you want;
their role is formatting text. Write you're own ibytestream and
obytestream (or rather ixdrstream and oxdrstream, or whatever,
according to the binary format you are using), deriving from ios
and using streambuf for the actual data transfers.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 11 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Matt Chaplain | last post: by
3 posts views Thread by Viktor Lundström | last post: by
3 posts views Thread by Christopher Benson-Manica | last post: by
9 posts views Thread by Fred Ma | last post: by
9 posts views Thread by Marcin Kalicinski | last post: by
7 posts views Thread by smith4894 | last post: by
7 posts views Thread by Christopher Pisz | last post: by
9 posts views Thread by bryonone | last post: by
xarzu
1 post views Thread by xarzu | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.