diff options
Diffstat (limited to 'dep/ACE_wrappers/ace/IOStream.cpp')
-rw-r--r-- | dep/ACE_wrappers/ace/IOStream.cpp | 117 |
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 */ |