streambuf :: getting the data back from a custom stream

R

rakesh.usenet

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.
 
J

Jim Langston

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
 
R

Rakesh Kumar

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 .
 
J

James Kanze

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 said:
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.
 
J

James Kanze

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top