Buffer wrapping in a stream

P

Philippe MESMEUR

Hi,

I'm currently trying to wrap a buffer in an ostream in order to access
it as following:



void TestOutStream(ostream & a_oStream)
{
a_oStream << "HELLO" << endl << "WORLD" << endl;
a_oStream << "FOO\nBAR" << endl;
a_oStream << "\001\002\003" << endl;
cout << "=> tellp: " << a_oStream.tellp() << endl;
}

const unsigned int SIZE = 32;
char buf[SIZE];

ostream.SetBuffer(buf, SIZE); /// here is what I would like to do
TestOutStream(ostream);

cout << buf << endl;


The writting in the ostream (or an inherited class, of course) would
write in the buffer buf. The buffer overloading would also be managed.


Do such an std class exist?
What should I do?

Thank you very much for your help

Philippe
 
P

Philippe MESMEUR

Hi,

I'm currently trying to wrap a buffer in an ostream in order to access
it as following:

void TestOutStream(ostream & a_oStream)
{
        a_oStream << "HELLO" << endl << "WORLD" << endl;
        a_oStream << "FOO\nBAR" << endl;
        a_oStream << "\001\002\003" << endl;
        cout << "=> tellp: " << a_oStream.tellp() << endl;

}

const unsigned int SIZE = 32;
char               buf[SIZE];

ostream.SetBuffer(buf, SIZE);  /// here is what I would like to do
TestOutStream(ostream);

cout << buf << endl;

The writting in the ostream (or an inherited class, of course) would
write in the buffer buf. The buffer overloading would also be managed.

Do such an std class exist?
What should I do?

Thank you very much for your help

Philippe

If I try something like:

stringbuf sbuf;
sbuf.pubsetbuf(buf, SIZE);
ostream os(&sbuf);
TestOutStream(os);

The code works under cygwin/g++ but not Visual Studio.
The problème seems to be in the function setbuf (which is called by
pubsetbuf) that is definded as follow in basic_streambuf:

virtual _Myt *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize)
{ // offer buffer to external agent (do nothing)
return (this);
}

Can anyone help me...
Philippe
 
B

Branimir Maksimovic

Philippe said:
ostream.SetBuffer(buf, SIZE); /// here is what I would like to do
TestOutStream(ostream);

cout << buf << endl;


The writting in the ostream (or an inherited class, of course) would
write in the buffer buf. The buffer overloading would also be managed.


Do such an std class exist?
What should I do?

You should write streambuf class, in this group archives and
c.l.c++.moderated you have lot of examples, how to do this, also
anu decent stl book should have it.

This is sample of two buffers to write/read strings via rpc...

class RpcOutBuf: public std::streambuf {
public:

RpcOutBuf(const std::string& sName, const std::string& sHost, unsigned
long ulP
virtual ~RpcOutBuf();

protected:

/**
Flushes buffer
*/

int flushBuffer();

/**
when buffer is full this function is called;
@param current character c
function will write current c, and all previous characters
*/
int overflow(int c);

/**
Synchronizes data with server
*/
int sync();

private:
/**
Service number on Rpc Server
*/
unsigned long ulSvcNum_;
/**
Constant which limits buffers size;
*/
static const int sizeOf = 2048;
/**
Internal buffer
*/
char szBuffer_[sizeOf+1];
/**
Rpc Client used for connection
*/
RpcClient rpcOutBufClient_;

};

class RpcInBuf: public std::streambuf {
public:

RpcInBuf(const std::string& sName, const std::string& sHost, unsigned
long ulPr

protected:

/**
Reads characters via RPC into buffer
*/

virtual int underflow();

private:
/**
Service number on Rpc server
*/
unsigned long ulSvcNum_;
/**
Constant which limits buffers size;
*/
static const int sizeOf = 2048;
/**
Internal buffer
*/
char szBuffer_[sizeOf+1];
/**
Rpc Client used for connection
*/
RpcClient rpcInBufClient_;

};

RpcOutBuf::RpcOutBuf(const std::string& sName, const std::string& sHost,
unsign
: ulSvcNum_(ulSvcNum),
rpcOutBufClient_(sName, sHost, ulProg, ulVer)
{
rpcOutBufClient_.regProc("outbuf", ulSvcNum_,
(xdrproc_t)xdr_wrapstring, (xdrproc_t)xdr_int);

setp(szBuffer_, szBuffer_+(sizeOf-1));
}

RpcOutBuf::~RpcOutBuf()
{
sync();
}

int RpcOutBuf::flushBuffer()
{
int num = pptr()-pbase();
try{
if ( num ) {
szBuffer_[num]=0;
int status;timeval t={5,0};
#ifdef DEBUG
std::clog<<"\nbuffer to send: \n"<<szBuffer_<<'\n';
#endif
char*ptr=szBuffer_;
if(rpcOutBufClient_.call("outbuf",(char*)&ptr, (char*)&status,
t) != R
{
rpcOutBufClient_.throwRpcClientError();
}
}
}catch(const std::exception& e)
{
std::cerr<<e.what()<<'\n';
return EOF;
}
pbump(-num);
return num;
}

/**
when buffer is full this function is called;
function will write current c, and all previous characters
*/
int RpcOutBuf::eek:verflow(int c)
{
if(c!=EOF){
*pptr() = c;
pbump(1);
}
if(flushBuffer() == EOF){ /// this is transmit error
return EOF;
}
return c;
}

/**
Synchronizes data with server
*/
int RpcOutBuf::sync(){
if(flushBuffer() == EOF){ /// this is transmit error
return -1;
}
return 0;
}

RpcInBuf::RpcInBuf(const std::string& sName, const std::string& sHost,
unsigned
:ulSvcNum_(ulSvcNum),
rpcInBufClient_(sName, sHost, ulProg, ulVer)
{
rpcInBufClient_.regProc("inbuf", ulSvcNum_,
(xdrproc_t)xdr_int, (xdrproc_t)xdr_wrapstring);
setg(szBuffer_, szBuffer_, szBuffer_); /// this is the place to init
ungetc ar
/// perhaps to put some chars in
buffer,
/// unused for now....
}


/**
Insert new characters into buffer
*/

int RpcInBuf::underflow()
{
if(gptr() < egptr())
{
return *gptr();
}
try {
int request=1;timeval t={5,0};
char*ptr=szBuffer_;
if(rpcInBufClient_.call("inbuf",
(char*)&request,
(char*)&ptr,
t
)!= RPC_SUCCESS
)
{
rpcInBufClient_.throwRpcClientError();
}
#ifdef DEBUF
std::clog<<"\nbuffer contains: \n"<<szBuffer_<<'\n';
#endif
} catch(const std::exception& e)
{
std::cerr<<e.what()<<'\n';
}
if(!strlen(szBuffer_))
{
std::cerr<<"End of file...\n";
return EOF;
}
setg(szBuffer_, szBuffer_, szBuffer_+strlen(szBuffer_));
return *gptr();
}

I wrote this some 10 years ago, don;t ask for explanations ;)


Greets
 
D

Dietmar Kuehl

ostream.SetBuffer(buf, SIZE);  /// here is what I would like to do
TestOutStream(ostream);

I don't know what "ostream.SetBuffer()" is supposed to be. If you are
referring to std::streambuf::pubsetbuf() you'll find that this
operation is only really useful to turn a file stream into being
unbuffered. All other uses are non-portable and in most cases don't do
anything.

From the looks of it you want to set up a stream to write into a
memory area. The way to do this is to create a simple stream buffer
which only sets up a put area which is never resized. The stream
buffer is then used to initialize an std::eek:stream. Here is how this
would roughly look like:

#include <streambuf>
#include <iostream>

struct membuf:
std::streambuf
{
membuf(char* buffer, size_t size) { this->setp(buffer, buffer +
size); }
char* end() const { return this->pptr(); }
};

int main()
{
char buffer[1024];
membuf sbuf(buffer, sizeof(buffer));
std::eek:stream out(&sbuf);

out << "hello, world\n";

// the sequence [buffer, sbuf.end()) now contains the written
string
}

The code is untested and most likely contains a few typos but should
essentially work...
 

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,968
Messages
2,570,150
Members
46,697
Latest member
AugustNabo

Latest Threads

Top