aboutsummaryrefslogtreecommitdiff
path: root/dep/ACE_wrappers/ace/IOStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/ACE_wrappers/ace/IOStream.cpp')
-rw-r--r--dep/ACE_wrappers/ace/IOStream.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/dep/ACE_wrappers/ace/IOStream.cpp b/dep/ACE_wrappers/ace/IOStream.cpp
index f047c62fe7b..0b6ac17ca6f 100644
--- a/dep/ACE_wrappers/ace/IOStream.cpp
+++ b/dep/ACE_wrappers/ace/IOStream.cpp
@@ -1,14 +1,22 @@
// $Id: IOStream.cpp 80826 2008-03-04 14:51:23Z wotte $
+
#ifndef ACE_IOSTREAM_CPP
#define ACE_IOSTREAM_CPP
+
#include "ace/IOStream.h"
+
ACE_RCSID(ace, IOStream, "$Id: IOStream.cpp 80826 2008-03-04 14:51:23Z wotte $")
+
#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
# include "ace/OS_NS_errno.h"
# include "ace/OS_Memory.h"
+
///////////////////////////////////////////////////////////////////////////
+
/* Here's a simple example of how iostream's non-virtual operators can
get you in a mess:
+
class myiostream : public iostream
{
public:
@@ -17,16 +25,21 @@ ACE_RCSID(ace, IOStream, "$Id: IOStream.cpp 80826 2008-03-04 14:51:23Z wotte $")
...
}
};
+
...
+
int i;
String s;
myiostream foo (...);
+
foo >> s;
// OK
// invokes myiostream::operator>> (String&) returning myiostream&
+
foo >> i;
// OK
// invokes iostream::operator>> (int&) returning iostream&
+
foo >> i >> s;
// BAD
// invokes iostream::operator>> (int&) then iostream::operator>> (String&)
@@ -35,7 +48,9 @@ ACE_RCSID(ace, IOStream, "$Id: IOStream.cpp 80826 2008-03-04 14:51:23Z wotte $")
// a reference to iostream. The second >> has no idea of the ACE_IOStream and
// gets invoked on iostream. Probably NOT what you wanted!
+
// In order to make all of this work the way you want, you have to do this:
+
class myiostream : public iostream
{
public:
@@ -43,33 +58,42 @@ ACE_RCSID(ace, IOStream, "$Id: IOStream.cpp 80826 2008-03-04 14:51:23Z wotte $")
{
return ((myiostream&)iostream::operator>> (i));
}
+
myiostream& operator>> (String & s)
{
...
}
};
+
...
+
int i;
String s;
myiostream foo (...);
+
foo >> s;
// OK
// invokes myiostream::operator>> (String&) returning myiostream&
+
foo >> i;
// OK
// invokes myiostream::operator>> (int&) returning myiostream&
+
foo >> i >> s;
// OK
// Because you provided operator>> (int&) in class myiostream, that
// function will be invoked by the first >>. Since it returns
// a myiostream&, the second >> will be invoked as desired. */
+
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
ACE_HANDLE
ACE_Streambuf::get_handle (void)
{
return 0;
}
+
ACE_Time_Value *
ACE_Streambuf::recv_timeout (ACE_Time_Value *tv)
{
@@ -81,17 +105,22 @@ ACE_Streambuf::recv_timeout (ACE_Time_Value *tv)
}
else
recv_timeout_ = 0;
+
return rval;
}
+
int
ACE_Streambuf::underflow (void)
{
// If input mode is not set, any attempt to read from the stream is
// a failure.
+
if (ACE_BIT_DISABLED (mode_, ios::in))
return EOF;
+
// If base () is empty then this is the first time any get/put
// operation has been attempted on the stream.
+
if (!this->base ())
{
// Set base () to use our private read buffer. The arguments are:
@@ -101,8 +130,10 @@ ACE_Streambuf::underflow (void)
//
// We have to say "no" to the third parameter because we want to
// explicitly handle deletion of the TWO buffers at destruction.
+
setb (this->eback_saved_,
this->eback_saved_ + streambuf_size_, 0);
+
// Remember that we are now in getMode. This will help us if
// we're called prior to a mode change as well as helping us
// when the mode does change.
@@ -111,6 +142,7 @@ ACE_Streambuf::underflow (void)
// This simply sets eback (), gptr () and egptr () described
// earlier.
setg (base (), base (), base ());
+
// Set the put buffer such that puts will be disabled. Any
// attempt to put data will now cause overflow to be invoked.
setp (0, 0);
@@ -132,6 +164,7 @@ ACE_Streambuf::underflow (void)
// need what we're sending before it can respond.
if (out_waiting () && syncout () == EOF)
return EOF;
+
if( ! pbase() )
{
delete [] pbase_saved_;
@@ -145,20 +178,26 @@ ACE_Streambuf::underflow (void)
this->pptr_saved_ = pptr ();
this->epptr_saved_ = epptr ();
}
+
// Disable put mode as described in the constructor.
setp (0, 0);
+
// Like the case where base () is false, we now point base
// () to use our private get buffer.
setb (this->eback_saved_,
this->eback_saved_ + streambuf_size_,
0);
+
// And restore the previous state of the get pointers.
+
setg (this->eback_saved_, this->gptr_saved_,
this->egptr_saved_);
+
// Finally, set our mode so that we don't get back into this
// if () and so that overflow can operate correctly.
cur_mode_ = get_mode_;
}
+
// There could be data in the input buffer if we switched to put
// mode before reading everything. In that case, we take this
// opportunity to feed it back to the iostream.
@@ -168,11 +207,15 @@ ACE_Streambuf::underflow (void)
// char when we're not returning EOF.
return (u_char) *gptr ();
}
+
// We really shouldn't be here unless there is a lack of data in the
// read buffer. So... go get some more data from the peer.
+
int result = fillbuf ();
+
// Fillbuf will give us EOF if there was an error with the peer. In
// that case, we can do no more input.
+
if (EOF == result)
{
// Disable ourselves and return failure to the iostream. That
@@ -180,28 +223,35 @@ ACE_Streambuf::underflow (void)
setg (0, 0, 0);
return EOF;
}
+
// Return the next available character in the input buffer. Again,
// we protect against sign extension.
+
return (u_char) *gptr ();
}
+
// Much of this is similar to underflow. I'll just hit the highlights
// rather than repeating a lot of what you've already seen.
+
int
ACE_Streambuf::overflow (int c)
{
// Check to see if output is allowed at all.
if (! (mode_ & ios::out))
return EOF;
+
if (!base ())
{
// Set base () to use put's private buffer.
//
setb (this->pbase_saved_,
this->pbase_saved_ + streambuf_size_, 0);
+
// Set the mode for optimization.
this->cur_mode_ = this->put_mode_;
// Set the put area using the new base () values.
setp (base (), ebuf ());
+
// Disable the get area.
setg (0, 0, 0);
}
@@ -230,21 +280,28 @@ ACE_Streambuf::overflow (int c)
this->egptr_saved_ = egptr ();
}
// <-- JCEJ 6/6/98
+
// then disable the get buffer
setg (0, 0, 0);
+
// Reconfigure base () and restore the put pointers.
setb (pbase_saved_, pbase_saved_ + streambuf_size_, 0);
setp (base (), ebuf ());
+
// Save the new mode.
this->cur_mode_ = this->put_mode_;
}
+
// If there is output to be flushed, do so now. We shouldn't
// get here unless this is the case...
+
if (out_waiting () && EOF == syncout ())
return EOF;
}
+
// If we're not putting EOF, then we have to deal with the character
// that is being put. Perhaps we should do something special with EOF???
+
if (c != EOF)
{
// We've already written any data that may have been in the
@@ -254,9 +311,12 @@ ACE_Streambuf::overflow (int c)
*pptr () = (char) c;
pbump (1);
}
+
return 0;
}
+
// syncin
+
int
ACE_Streambuf::syncin (void)
{
@@ -265,33 +325,42 @@ ACE_Streambuf::syncin (void)
// function so that it won't do anything evil to us.
return 0;
}
+
// syncout
+
int
ACE_Streambuf::syncout (void)
{
// Unlike syncin, syncout is a doable thing. All we have to do is
// write whatever is in the output buffer to the peer. flushbuf ()
// is how we do it.
+
if (flushbuf () == EOF)
return EOF;
else
return 0;
}
+
int
ACE_Streambuf::sync (void)
{
// sync () is fairly traditional in that it syncs both input and
// output. We could have omitted the call to syncin () but someday,
// we may want it to do something.
+
syncin ();
+
// Don't bother syncing the output unless there is data to be
// sent...
+
if (out_waiting ())
return syncout ();
else
return 0;
}
+
// flushbuf
+
int
ACE_Streambuf::flushbuf (void)
{
@@ -299,8 +368,10 @@ ACE_Streambuf::flushbuf (void)
// buffer. pbase () points to the beginning of the put buffer.
// Unless pptr () is greater than pbase () there is nothing to be
// sent to the peer.
+
if (pptr () <= pbase ())
return 0;
+
// 4/12/97 -- JCEJ
// Kludge!!!
// If the remote side shuts down the connection, an attempt to send
@@ -332,25 +403,32 @@ ACE_Streambuf::flushbuf (void)
// The correct way to handle this is for the application to trap
// (and ignore?) SIGPIPE. Thanks to Amos Shapira for reminding me
// of this.
+
// Starting at the beginning of the buffer, send as much data as
// there is waiting. send guarantees that all of the data will be
// sent or an error will be returned.
+
if (this->send (pbase (), pptr () - pbase ()) == -1)
return EOF;
+
// Now that we've sent everything in the output buffer, we reset the
// buffer pointers to appear empty.
setp (base (), ebuf ());
+
return 0;
}
+
int
ACE_Streambuf::get_one_byte (void)
{
this->timeout_ = 0;
+
// The recv function will return immediately if there is no data
// waiting. So, we use recv_n to wait for exactly one byte to come
// from the peer. Later, we can use recv to see if there is
// anything else in the buffer. (Ok, we could use flags to tell it
// to block but I like this better.)
+
if (this->recv_n (base (), 1, MSG_PEEK, this->recv_timeout_) != 1)
{
if (errno == ETIME)
@@ -360,32 +438,43 @@ ACE_Streambuf::get_one_byte (void)
else
return 1;
}
+
// This will be called when the read (get) buffer has been exhausted
// (ie -- gptr == egptr).
+
int
ACE_Streambuf::fillbuf (void)
{
// Invoke recv_n to get exactly one byte from the remote. This will
// block until something shows up.
+
if (get_one_byte () == EOF)
return EOF;
+
// Now, get whatever else may be in the buffer. This will return if
// there is nothing in the buffer.
+
int bc = this->recv (base (), blen (), this->recv_timeout_);
+
// recv will give us -1 if there was a problem. If there was
// nothing waiting to be read, it will give us 0. That isn't an
// error.
+
if (bc < 0)
{
if (errno == ETIME)
this->timeout_ = 1;
return EOF;
}
+
// Move the get pointer to reflect the number of bytes we just read.
+
setg (base (), base (), base () + bc);
+
// Return the byte-read-count including the one from <get_one_byte>.
return bc;
}
+
ACE_Streambuf::ACE_Streambuf (u_int streambuf_size, int io_mode)
: eback_saved_ (0), // to avoid Purify UMR
pbase_saved_ (0), // to avoid Purify UMR
@@ -398,32 +487,40 @@ ACE_Streambuf::ACE_Streambuf (u_int streambuf_size, int io_mode)
(void)reset_get_buffer ();
(void)reset_put_buffer ();
}
+
u_int
ACE_Streambuf::streambuf_size (void)
{
return streambuf_size_;
}
+
// Return the number of bytes not yet gotten. eback + get_waiting =
// gptr.
+
u_int
ACE_Streambuf::get_waiting (void)
{
return this->gptr_saved_ - this->eback_saved_;
}
+
// Return the number of bytes in the get area (includes some already
// gotten); eback + get_avail = egptr.
+
u_int
ACE_Streambuf::get_avail (void)
{
return this->egptr_saved_ - this->eback_saved_;
}
+
// Return the number of bytes to be 'put' onto the stream media.
// pbase + put_avail = pptr.
+
u_int
ACE_Streambuf::put_avail (void)
{
return this->pptr_saved_ - this->pbase_saved_;
}
+
// Typical usage:
//
// u_int newGptr = otherStream->get_waiting ();
@@ -433,6 +530,7 @@ ACE_Streambuf::put_avail (void)
//
// 'myStream' now has the get buffer of 'otherStream' and can use it in any way.
// 'otherStream' now has a new, empty get buffer.
+
char *
ACE_Streambuf::reset_get_buffer (char *newBuffer,
u_int _streambuf_size,
@@ -440,6 +538,7 @@ ACE_Streambuf::reset_get_buffer (char *newBuffer,
u_int _egptr)
{
char * rval = this->eback_saved_;
+
// The get area is where the iostream will get data from. This is
// our read buffer. There are three pointers which describe the
// read buffer:
@@ -466,25 +565,32 @@ ACE_Streambuf::reset_get_buffer (char *newBuffer,
ACE_NEW_RETURN (this->eback_saved_,
char[streambuf_size_],
0);
+
this->gptr_saved_ = this->eback_saved_ + _gptr;
this->egptr_saved_ = this->eback_saved_ + _egptr;
+
// Disable the get area initially. This will cause underflow to be
// invoked on the first get operation.
setg (0, 0, 0);
+
reset_base ();
+
return rval;
}
+
// Typical usage:
//
// u_int newPptr = otherStream->put_avail ();
// char * newBuf = otherStream->reset_put_buffer ();
// char * oldputbuf = otherStream->reset_put_buffer (newBuf, otherStream->streambuf_size (), newPptr);
+
char *
ACE_Streambuf::reset_put_buffer (char *newBuffer,
u_int _streambuf_size,
u_int _pptr)
{
char *rval = this->pbase_saved_;
+
// The put area is where the iostream will put data that needs to be
// sent to the peer. This becomes our write buffer. The three
// pointers which maintain this area are:
@@ -508,20 +614,26 @@ ACE_Streambuf::reset_put_buffer (char *newBuffer,
ACE_NEW_RETURN (this->pbase_saved_,
char[streambuf_size_],
0);
+
this->pptr_saved_ = this->pbase_saved_ + _pptr;
this->epptr_saved_ = this->pbase_saved_ + streambuf_size_;
+
// Disable the put area. Overflow will be called by the first call
// to any put operator.
setp (0, 0);
+
reset_base ();
+
return rval;
}
+
void
ACE_Streambuf::reset_base (void)
{
// Until we experience the first get or put operation, we do not
// know what our current IO mode is.
this->cur_mode_ = 0;
+
// The common area used for reading and writting is called "base".
// We initialize it this way so that the first get/put operation
// will have to "allocate" base. This allocation will set base to
@@ -529,21 +641,26 @@ ACE_Streambuf::reset_base (void)
// value.
setb (0, 0);
}
+
// If the default allocation strategey were used the common buffer
// would be deleted when the object destructs. Since we are providing
// separate read/write buffers, it is up to us to manage their memory.
+
ACE_Streambuf::~ACE_Streambuf (void)
{
delete [] this->eback_saved_;
delete [] this->pbase_saved_;
}
+
u_char ACE_Streambuf::timeout (void)
{
u_char rval = this->timeout_;
this->timeout_ = 0;
return rval;
}
+
ACE_END_VERSIONED_NAMESPACE_DECL
+
#endif /* !ACE_LACKS_ACE_IOSTREAM */
#endif /* ACE_IOSTREAM_CPP */