diff options
author | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-05-24 02:39:14 +0000 |
---|---|---|
committer | levine <levine@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-05-24 02:39:14 +0000 |
commit | 9f5f2ecd526db5689ff6712f2a317845dfb2b90a (patch) | |
tree | 3934dba31e9d8d7f402a68a9767ddcb2e23a9a30 | |
parent | 49d2b1a9b3ec1595a9d1273b758f7fa2ba5743d5 (diff) | |
download | ATCD-9f5f2ecd526db5689ff6712f2a317845dfb2b90a.tar.gz |
ACE_IOStream updates: mainly split out templates into separate _T files
-rw-r--r-- | ace/IOStream.cpp | 231 | ||||
-rw-r--r-- | ace/IOStream.h | 275 | ||||
-rw-r--r-- | ace/IOStream_T.cpp | 189 | ||||
-rw-r--r-- | ace/IOStream_T.h | 280 | ||||
-rw-r--r-- | ace/README | 1 |
5 files changed, 512 insertions, 464 deletions
diff --git a/ace/IOStream.cpp b/ace/IOStream.cpp index 8f9ceb042e7..4737cf6318a 100644 --- a/ace/IOStream.cpp +++ b/ace/IOStream.cpp @@ -4,10 +4,10 @@ #if !defined (ACE_IOSTREAM_C) #define ACE_IOSTREAM_C +#if !defined (ACE_LACKS_ACE_IOSTREAM) + #define ACE_BUILD_DLL #include "ace/IOStream.h" -#include "ace/Thread.h" -#include "ace/Handle_Set.h" /////////////////////////////////////////////////////////////////////////// @@ -42,7 +42,7 @@ // invokes iostream::operator>> (int&) then iostream::operator>> (String&) // // What has happened is that the first >> is invoked on the base class and returns - // a reference to iostream. The second >> has no idea of the ACE_IOStream and + // a reference to iostream. The second >> has no idea of the ACE_IOStream_T and // gets invoked on iostream. Probably NOT what you wanted! @@ -84,10 +84,8 @@ // a myiostream&, the second >> will be invoked as desired. */ -#if ! defined (ACE_IOSTREAM_BUILDING_TEMPLATE) - -ACE_Time_Value * -ACE_Streambuf_T::recv_timeout (ACE_Time_Value * tv) +ACE_Time_Value * +ACE_Streambuf::recv_timeout (ACE_Time_Value * tv) { ACE_Time_Value * rval = recv_timeout_; if (tv) @@ -102,7 +100,7 @@ ACE_Streambuf_T::recv_timeout (ACE_Time_Value * tv) } int -ACE_Streambuf_T::underflow (void) +ACE_Streambuf::underflow (void) { // If input mode is not set, any attempt to read from the stream is // a failure. @@ -221,7 +219,7 @@ ACE_Streambuf_T::underflow (void) // rather than repeating a lot of what you've already seen. int -ACE_Streambuf_T::overflow (int c) +ACE_Streambuf::overflow (int c) { // Check to see if output is allowed at all. if (! (mode_ & ios::out)) @@ -291,7 +289,7 @@ ACE_Streambuf_T::overflow (int c) // syncin int -ACE_Streambuf_T::syncin (void) +ACE_Streambuf::syncin (void) { // As discussed, there really isn't any way to sync input from a socket-like // device. We specifially override this base-class function so that it won't @@ -302,7 +300,7 @@ ACE_Streambuf_T::syncin (void) // syncout int -ACE_Streambuf_T::syncout (void) +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 () @@ -315,7 +313,7 @@ ACE_Streambuf_T::syncout (void) } int -ACE_Streambuf_T::sync (void) +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 @@ -334,7 +332,7 @@ ACE_Streambuf_T::sync (void) // flushbuf int -ACE_Streambuf_T::flushbuf (void) +ACE_Streambuf::flushbuf (void) { // pptr () is one character beyond the last character put // into the buffer. pbase () points to the beginning of @@ -395,8 +393,8 @@ ACE_Streambuf_T::flushbuf (void) return 0; } -int -ACE_Streambuf_T::get_one_byte (void) +int +ACE_Streambuf::get_one_byte (void) { // 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 @@ -411,7 +409,7 @@ ACE_Streambuf_T::get_one_byte (void) } int -ACE_Streambuf_T::fillbuf (void) +ACE_Streambuf::fillbuf (void) // This will be called when the read (get) buffer has been // exhausted (ie -- gptr == egptr) { @@ -422,7 +420,7 @@ ACE_Streambuf_T::fillbuf (void) return EOF; // Now, get whatever else may be in the buffer. This will return if - // there is nothing in the buffer. + // there is nothing in the buffer. int bc = this->recv (base (), blen (), recv_timeout_); @@ -441,7 +439,7 @@ ACE_Streambuf_T::fillbuf (void) return bc; } -ACE_Streambuf_T::ACE_Streambuf_T (u_int streambuf_size, int io_mode) +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 get_mode_ (1), @@ -454,26 +452,26 @@ ACE_Streambuf_T::ACE_Streambuf_T (u_int streambuf_size, int io_mode) (void)reset_put_buffer (); } -u_int ACE_Streambuf_T::streambuf_size (void) +u_int ACE_Streambuf::streambuf_size (void) { return streambuf_size_; } -u_int ACE_Streambuf_T::get_waiting (void) +u_int ACE_Streambuf::get_waiting (void) // Return the number of bytes not yet gotten. // eback + get_waiting = gptr { return this->gptr_saved_ - this->eback_saved_; } -u_int ACE_Streambuf_T::get_avail (void) +u_int ACE_Streambuf::get_avail (void) // Return the number of bytes in the get area (includes some already gotten); // eback + get_avail = egptr { return this->egptr_saved_ - this->eback_saved_; } -u_int ACE_Streambuf_T::put_avail (void) +u_int ACE_Streambuf::put_avail (void) // Return the number of bytes to be 'put' onto the stream media. // pbase + put_avail = pptr { @@ -481,7 +479,7 @@ u_int ACE_Streambuf_T::put_avail (void) } char * -ACE_Streambuf_T::reset_get_buffer (char * newBuffer, u_int _streambuf_size, u_int _gptr, u_int _egptr) +ACE_Streambuf::reset_get_buffer (char * newBuffer, u_int _streambuf_size, u_int _gptr, u_int _egptr) // // Typical usage: // @@ -536,7 +534,7 @@ ACE_Streambuf_T::reset_get_buffer (char * newBuffer, u_int _streambuf_size, u_in } char * -ACE_Streambuf_T::reset_put_buffer (char * newBuffer, u_int _streambuf_size, u_int _pptr) +ACE_Streambuf::reset_put_buffer (char * newBuffer, u_int _streambuf_size, u_int _pptr) // // Typical usage: // @@ -584,7 +582,7 @@ ACE_Streambuf_T::reset_put_buffer (char * newBuffer, u_int _streambuf_size, u_in } void -ACE_Streambuf_T::reset_base (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. @@ -602,191 +600,12 @@ ACE_Streambuf_T::reset_base (void) // 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_T::~ACE_Streambuf_T (void) +ACE_Streambuf::~ACE_Streambuf (void) { delete [] this->eback_saved_; delete [] this->pbase_saved_; } -#endif // ACE_IOSTREAM_BUILDING_TEMPLATE - -/////////////////////////////////////////////////////////////////////////// - - -// We will be given a STREAM by the iostream object which creates us. -// See the ACE_IOStream template for how that works. Like other -// streambuf objects, we can be input-only, output-only or both. - -template <class STREAM> -ACE_Streambuf<STREAM>::ACE_Streambuf (STREAM *peer, u_int streambuf_size, int io_mode) - : ACE_Streambuf_T (streambuf_size, io_mode), peer_ (peer) -{ - // A streambuf allows for unbuffered IO where every character is - // read as requested and written as provided. To me, this seems - // terribly inefficient for socket-type operations, so I've disabled - // it. All of the work would be done by the underflow/overflow - // functions anyway and I haven't implemented anything there to - // support unbuffered IO. - - this->unbuffered (0); - - // Linebuffered is similar to unbuffered. Again, I don't have any - // need for this and I don't see the advantage. I believe this - // would have to be supported by underflow/overflow to be effective. -#if !defined (ACE_LACKS_LINEBUFFERED_STREAMBUF) - this->linebuffered (0); -#endif /* ! ACE_LACKS_LINEBUFFERED_STREAMBUF */ - -} - - -/////////////////////////////////////////////////////////////////////////// - - -// The typical constructor. This will initiailze your STREAM and then -// setup the iostream baseclass to use a custom streambuf based on -// STREAM. - -template <class STREAM> -ACE_IOStream<STREAM>::ACE_IOStream (STREAM & stream, u_int streambuf_size) - : iostream (streambuf_ = new ACE_Streambuf<STREAM> ((STREAM *) this, streambuf_size)), - STREAM (stream) -{ - iostream::init (this->streambuf_); -} - -template <class STREAM> -ACE_IOStream<STREAM>::ACE_IOStream (u_int streambuf_size) - : iostream (streambuf_ = new ACE_Streambuf<STREAM> ((STREAM *) this, streambuf_size)) -{ - iostream::init (this->streambuf_); -} - -// We have to get rid of the streambuf_ ourselves since we gave it to -// iostream () - -template <class STREAM> -ACE_IOStream<STREAM>::~ACE_IOStream (void) -{ - delete this->streambuf_; -} - -// The only ambituity in the multiple inheritance is the close () -// function. - -template <class STREAM> int -ACE_IOStream<STREAM>::close (void) -{ - return STREAM::close (); -} - -template <class STREAM> ACE_IOStream<STREAM> & -ACE_IOStream<STREAM>::operator>> (ACE_Time_Value *& tv) -{ - ACE_Time_Value * old_tv = this->streambuf_->recv_timeout (tv); - tv = old_tv; - return *this; -} - -#if defined (ACE_HAS_STRING_CLASS) +#endif /* !ACE_LACKS_ACE_IOSTREAM */ -// A simple string operator. The base iostream has 'em for char* but -// that isn't always the best thing for a String. If we don't provide -// our own here, we may not get what we want. - -template <class STREAM> ACE_IOStream<STREAM> & -ACE_IOStream<STREAM>::operator>> (ACE_IOStream_String & v) -{ - if (ipfx0 ()) - { - char c; - iostream::operator>> (c); - - for (v = c ; this->get (c) && !isspace (c) ; v += c) - continue; - } - - isfx (); - - return *this; -} - - -template <class STREAM> ACE_IOStream<STREAM> & -ACE_IOStream<STREAM>::operator<< (ACE_IOStream_String & v) -{ - if (opfx ()) - { -#if defined (ACE_WIN32) - for (int i = 0 ; i < v.GetLength () ; ++i) -#else - for (u_int i = 0 ; i < (u_int) v.length () ; ++i) -#endif - this->put (v[i]); - } - - osfx (); - - return *this; -} - - -////////////////////////////////////////////////////////////////// -// A more clever put operator for strings that knows how to -// deal with quoted strings containing back-quoted quotes. -// -template <class STREAM> ACE_IOStream<STREAM> & -ACE_IOStream<STREAM>::operator>> (QuotedString & str) -{ - if (ipfx0 ()) - { - char c; - - if (! (*this >> c)) // eat space up to the first char - // this->set (ios::eofbit|ios::failbit); - return *this; - - str = ""; // Initialize the string - - // if we don't have a quote, append until we see space - if (c != '"') - for (str = c ; this->get (c) && !isspace (c) ; str += c) - continue; - else - for (; this->get (c) && c != '"' ; str += c) - if (c == '\\') - { - this->get (c); - if (c != '"') - str += '\\'; - } - } - - isfx (); - - return *this; -} - -template <class STREAM> ACE_IOStream<STREAM> & -ACE_IOStream<STREAM>::operator<< (QuotedString & str) -{ - if (opfx ()) - { - this->put ('"'); - for (u_int i = 0 ; i < str.length () ; ++i) - { - if (str[i] == '"') - this->put ('\\'); - this->put (str[i]); - } - this->put ('"'); - } - - osfx (); - - return *this; -} - -#endif /* ACE_HAS_STRING_CLASS */ #endif /* ACE_IOSTREAM_C */ - diff --git a/ace/IOStream.h b/ace/IOStream.h index 454f803e829..1a9ac2886a5 100644 --- a/ace/IOStream.h +++ b/ace/IOStream.h @@ -7,7 +7,7 @@ // ace // // = FILENAME -// iostream.h +// IOStream.h // // = AUTHOR // James CE Johnson <jcej@lads.com> @@ -20,7 +20,7 @@ /* Changes 4/5/97 - ACE_Streambuf_T + ACE_Streambuf New public functions added @@ -62,26 +62,27 @@ Constructor changed Initialization of the get/put buffers was moved here from - the derived class/template ACE_Streambuf<...> + the derived class/template ACE_Streambuf_T<...> At the same time, the new functions reset_get/put_buffer are now used instead of the previous monolithic function. - ACE_Streambuf<...> + ACE_Streambuf_T<...> Constructor changed: Initialization of the get/put buffers has been moved to the - baseclass ACE_Streambuf_T. This will reduce template bloat + baseclass ACE_Streambuf. This will reduce template bloat as well as giving us more functionality as described above. */ #if !defined (ACE_IOSTREAM_H) #define ACE_IOSTREAM_H +#if !defined (ACE_LACKS_ACE_IOSTREAM) + #include "ace/INET_Addr.h" #include "ace/Handle_Set.h" -#include <iomanip.h> #if defined (ACE_HAS_STRING_CLASS) #if defined (ACE_WIN32) @@ -104,15 +105,15 @@ public: inline QuotedString (void) { *this = ""; } inline QuotedString (const char * c) { *this = ACE_IOStream_String (c); } inline QuotedString (const ACE_IOStream_String& s) { *this = s; } - inline QuotedString& operator= (const ACE_IOStream_String& s) + inline QuotedString& operator= (const ACE_IOStream_String& s) { return (QuotedString&) ACE_IOStream_String::operator= (s); } inline QuotedString & operator = (const char c) { - return (QuotedString&) ACE_IOStream_String::operator= (c); + return (QuotedString&) ACE_IOStream_String::operator= (c); } - inline QuotedString & operator = (const char* c) { - return (QuotedString&) ACE_IOStream_String::operator= (c); + inline QuotedString & operator = (const char* c) { + return (QuotedString&) ACE_IOStream_String::operator= (c); } inline bool operator < (const QuotedString& s) const { return *(ACE_IOStream_String *) this < (ACE_IOStream_String) s; @@ -126,7 +127,7 @@ public: /////////////////////////////////////////////////////////////////////////// -class ACE_Export ACE_Streambuf_T : public streambuf +class ACE_Export ACE_Streambuf : public streambuf // = TITLE // Create your custom streambuf by providing and ACE_*_Stream // object to this template. I have tested it with @@ -190,7 +191,7 @@ class ACE_Export ACE_Streambuf_T : public streambuf { public: - virtual ~ACE_Streambuf_T (void); + virtual ~ACE_Streambuf (void); // 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 @@ -232,7 +233,7 @@ public: // Query the streambuf for the size of it's buffers. protected: - ACE_Streambuf_T (u_int streambuf_size, int io_mode); + ACE_Streambuf (u_int streambuf_size, int io_mode); virtual int sync (void); // Sync both input and output. See syncin/syncout below for @@ -322,47 +323,6 @@ protected: /////////////////////////////////////////////////////////////////////////// -template <class STREAM> -class ACE_Streambuf : public ACE_Streambuf_T -{ -public: - ACE_Streambuf (STREAM * peer, u_int streambuf_size = ACE_STREAMBUF_SIZE, int io_mode = ios::in | ios::out); - // We will be given a STREAM by the iostream object which creates - // us. See the ACE_IOStream template for how that works. Like - // other streambuf objects, we can be input-only, output-only or - // both. - - virtual ssize_t send ( char * buf, ssize_t len ) - { - return peer_->send_n(buf,len); - } - virtual ssize_t recv ( char * buf, ssize_t len, ACE_Time_Value * tv = NULL ) - { - return this->recv( buf, len, 0, tv ); - } - virtual ssize_t recv ( char * buf, ssize_t len, int flags, ACE_Time_Value * tv = NULL ) - { - ssize_t rval = peer_->recv(buf,len,flags,tv); - return rval; - } - virtual ssize_t recv_n( char * buf, ssize_t len, int flags = 0, ACE_Time_Value * tv = NULL ) - { - ssize_t rval = peer_->recv_n(buf,len,flags,tv); - return rval; - } - -protected: - STREAM * peer_; - // This will be our ACE_SOCK_Stream or similar object. - - virtual ACE_HANDLE get_handle(void) - { - return peer_ ? peer_->get_handle() : 0 ; - } -}; - -/////////////////////////////////////////////////////////////////////////// - // These typedefs are provided by G++ (on some systems?) without the // trailing '_'. Since we can't count on 'em, I've defined them to // what GNU wants here. @@ -478,210 +438,9 @@ typedef ostream& (*__omanip_)(ostream&); /////////////////////////////////////////////////////////////////////////// -template <class STREAM> -class ACE_IOStream : public iostream, public STREAM - // = TITLE - // A template adapter for creating an iostream-like object using - // an ACE IPC Stream for the actual I/O. Iostreams use an - // underlying streambuf object for the IO interface. The - // iostream class and derivatives provide you with a host of - // convenient operators that access the streambuf. - // - // = DESCRIPTION - // We inherit all characteristics of iostream and your <STREAM> - // class. When you create a new class from this template, you - // can use it anywhere you would have used your original - // <STREAM> class. - // - // To create an iostream for your favorite ACE IPC class (e.g., - // <ACE_SOCK_Stream>), feed that class to this template's - // <STREAM> parameter, e.g., - // - // typedef ACE_Svc_Handler<ACE_SOCK_iostream, - // ACE_INET_Addr, ACE_NULL_SYNCH> - // Service_Handler; - // - // Because the operators in the iostream class are not virtual, - // you cannot easily provide overloads in your custom - // ACE_IOStream classes. To make these things work correctly, - // you need to overload ALL operators of the ACE_IOStream you - // create. I've attempted to do that here to make things easier - // for you but there are no guarantees. - // - // In the iostream.cpp file is an example of why it is necessary - // to overload all of the get/put operators when you want to - // customize only one or two. -{ -public: - ACE_IOStream (STREAM & stream, u_int streambuf_size = ACE_STREAMBUF_SIZE); - ACE_IOStream (u_int streambuf_size = ACE_STREAMBUF_SIZE); - // The default constructor. This will initiailze your STREAM and - // then setup the iostream baseclass to use a custom streambuf based - // on STREAM. - - virtual ~ACE_IOStream (void); - // We have to get rid of the streambuf_ ourselves since we gave it - // to iostream(); - - virtual int close (void); - // The only ambituity in the multiple inheritance is the close() - // function. - -#if defined (ACE_HAS_STRING_CLASS) - virtual ACE_IOStream<STREAM> & operator>>(ACE_IOStream_String & v); - // A simple string operator. The base iostream has 'em for char* - // but that isn't always the best thing for a String. If we don't - // provide our own here, we may not get what we want. - - virtual ACE_IOStream<STREAM> & operator<<(ACE_IOStream_String & v); - // The converse of the String put operator. - - virtual ACE_IOStream<STREAM> & operator>>(QuotedString &v); - // A more clever operator that handles quoted strings so that we - // can get strings containing whitespace! - - virtual ACE_IOStream<STREAM> & operator<<(QuotedString &v); - // The converse of the QuotedString put operator. -#endif /* ACE_HAS_STRING_CLASS */ - - // = Using the macros to provide get/set operators. - GETPUT_FUNC_SET (ACE_IOStream<STREAM>) - -#if defined (ACE_LACKS_IOSTREAM_FX) - virtual int ipfx (int need = 0) { return good(); } - virtual int ipfx0(void) { return good(); } // Optimized ipfx(0) - virtual int ipfx1(void) { return good(); } // Optimized ipfx(1) - virtual void isfx (void) { return; } - virtual int opfx (void) { return good(); } - virtual void osfx (void) { put(' '); return; } -#else -#if defined (__GNUC__) - virtual int ipfx0(void) { return(iostream::ipfx0()); } // Optimized ipfx(0) - virtual int ipfx1(void) { return(iostream::ipfx1()); } // Optimized ipfx(1) -#else - virtual int ipfx0(void) { return(iostream::ipfx(0)); } - virtual int ipfx1(void) { return(iostream::ipfx(1)); } -#endif - virtual int ipfx (int need = 0) { return(iostream::ipfx(need)); } - virtual void isfx (void) { iostream::isfx(); return; } - virtual int opfx (void) { return(iostream::opfx()); } - virtual void osfx (void) { iostream::osfx(); return; } -#endif /* ACE_LACKS_IOSTREAM_FX */ - - ACE_IOStream<STREAM> & operator>>(ACE_Time_Value *&tv); - // Allow the programmer to provide a timeout for read operations. - // Give it a pointer to NULL to block forever. - -protected: - - ACE_Streambuf<STREAM> *streambuf_; - // This is where all of the action takes place. The - // streambuf_ is the interface to the underlying STREAM. - -private: - // We move these into the private section so that they cannot - // be used by the application programmer. This is necessary - // because streambuf_ will be buffering IO on the STREAM - // object. If these functions were used in your program, - // there is a danger of getting the datastream out of sync. - ssize_t send (...); - ssize_t recv (...); - ssize_t send_n (...); - ssize_t recv_n (...); -}; - -/////////////////////////////////////////////////////////////////////////// - -template <class STREAM> -class ACE_SOCK_Dgram_SC : public STREAM -// Datagrams don't have the notion of a "peer". Each send and receive -// on a datagram can go to a different peer if you want. If you're -// using datagrams for stream activity, you probably want 'em all to -// go to (and come from) the same place. That's what this class is -// for. BTW: 'Dgram_SC' is short for 'Datagram-Self-Contained'. -// Here, we keep an address object so that we can remember who last -// sent us data. When we write back, we're then able to write back to -// that same address. -{ -protected: - ACE_INET_Addr peer_; +// Include the templates here. +#include "ace/IOStream_T.h" -public: - ACE_SOCK_Dgram_SC (void) - { - } - - ACE_SOCK_Dgram_SC (STREAM &source, ACE_INET_Addr &dest) - : STREAM (source), peer_ (dest) - { - } - - inline ssize_t send_n (char *buf, ssize_t len) - { - return STREAM::send (buf, len, peer_); - } - - inline ssize_t recv (char * buf, ssize_t len, ACE_Time_Value * tv = NULL) - { - return recv (buf, len, 0, tv); - } - - inline ssize_t recv (char * buf, ssize_t len, int flags, ACE_Time_Value * tv = NULL) - { - if (tv != 0) - { - ACE_HANDLE handle = this->get_handle (); - ACE_Handle_Set handle_set; - - handle_set.set_bit (handle); - - switch (ACE_OS::select (int (handle) + 1, - (fd_set *) handle_set, // read_fds. - (fd_set *) 0, // write_fds. - (fd_set *) 0, // exception_fds. - tv)) - { - case 0: - errno = ETIME; - case -1: - return -1; - default: - ; // Do the 'recv' below - } - } - - int rval = STREAM::recv (buf, len, peer_, flags); -#ifdef WIN32 - if (rval == SOCKET_ERROR) - if (WSAGetLastError() == WSAEMSGSIZE) - if (flags & MSG_PEEK) - rval = len; -#endif - - return rval < len ? rval : len; - } - inline ssize_t recv_n (char * buf, - ssize_t len, int flags = 0, - ACE_Time_Value * tv = NULL) - { - int rval = this->recv (buf, len, flags, tv); - return rval; - } - - inline int get_remote_addr (ACE_INET_Addr &addr) const - { - addr = peer_; - return 0; - } - -}; - -#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) -# if ! defined( ACE_IOSTREAM_C ) -# define ACE_IOSTREAM_BUILDING_TEMPLATE -# endif -# include "ace/IOStream.cpp" -#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ +#endif /* !ACE_LACKS_ACE_IOSTREAM */ #endif /* ACE_IOSTREAM_H */ - diff --git a/ace/IOStream_T.cpp b/ace/IOStream_T.cpp new file mode 100644 index 00000000000..003ced1dbb5 --- /dev/null +++ b/ace/IOStream_T.cpp @@ -0,0 +1,189 @@ +// IOStream.cpp +// $Id$ + +#if !defined (ACE_IOSTREAM_T_C) +#define ACE_IOSTREAM_T_C + +#define ACE_BUILD_DLL +#include "ace/IOStream_T.h" + +/////////////////////////////////////////////////////////////////////////// + + +// We will be given a STREAM by the iostream object which creates us. +// See the ACE_IOStream_T template for how that works. Like other +// streambuf objects, we can be input-only, output-only or both. + +template <class STREAM> +ACE_Streambuf_T<STREAM>::ACE_Streambuf_T (STREAM *peer, u_int streambuf_size, int io_mode) + : ACE_Streambuf (streambuf_size, io_mode), peer_ (peer) +{ + // A streambuf allows for unbuffered IO where every character is + // read as requested and written as provided. To me, this seems + // terribly inefficient for socket-type operations, so I've disabled + // it. All of the work would be done by the underflow/overflow + // functions anyway and I haven't implemented anything there to + // support unbuffered IO. + + this->unbuffered (0); + + // Linebuffered is similar to unbuffered. Again, I don't have any + // need for this and I don't see the advantage. I believe this + // would have to be supported by underflow/overflow to be effective. +#if !defined (ACE_LACKS_LINEBUFFERED_STREAMBUF) + this->linebuffered (0); +#endif /* ! ACE_LACKS_LINEBUFFERED_STREAMBUF */ + +} + + +/////////////////////////////////////////////////////////////////////////// + + +// The typical constructor. This will initiailze your STREAM and then +// setup the iostream baseclass to use a custom streambuf based on +// STREAM. + +template <class STREAM> +ACE_IOStream_T<STREAM>::ACE_IOStream_T (STREAM & stream, u_int streambuf_size) + : iostream (streambuf_ = new ACE_Streambuf_T<STREAM> ((STREAM *) this, streambuf_size)), + STREAM (stream) +{ + iostream::init (this->streambuf_); +} + +template <class STREAM> +ACE_IOStream_T<STREAM>::ACE_IOStream_T (u_int streambuf_size) + : iostream (streambuf_ = new ACE_Streambuf_T<STREAM> ((STREAM *) this, streambuf_size)) +{ + iostream::init (this->streambuf_); +} + +// We have to get rid of the streambuf_ ourselves since we gave it to +// iostream () + +template <class STREAM> +ACE_IOStream_T<STREAM>::~ACE_IOStream_T (void) +{ + delete this->streambuf_; +} + +// The only ambituity in the multiple inheritance is the close () +// function. + +template <class STREAM> int +ACE_IOStream_T<STREAM>::close (void) +{ + return STREAM::close (); +} + +template <class STREAM> ACE_IOStream_T<STREAM> & +ACE_IOStream_T<STREAM>::operator>> (ACE_Time_Value *& tv) +{ + ACE_Time_Value * old_tv = this->streambuf_->recv_timeout (tv); + tv = old_tv; + return *this; +} + +#if defined (ACE_HAS_STRING_CLASS) + +// A simple string operator. The base iostream has 'em for char* but +// that isn't always the best thing for a String. If we don't provide +// our own here, we may not get what we want. + +template <class STREAM> ACE_IOStream_T<STREAM> & +ACE_IOStream_T<STREAM>::operator>> (ACE_IOStream_String & v) +{ + if (ipfx0 ()) + { + char c; + iostream::operator>> (c); + + for (v = c ; this->get (c) && !isspace (c) ; v += c) + continue; + } + + isfx (); + + return *this; +} + + +template <class STREAM> ACE_IOStream_T<STREAM> & +ACE_IOStream_T<STREAM>::operator<< (ACE_IOStream_String & v) +{ + if (opfx ()) + { +#if defined (ACE_WIN32) + for (int i = 0 ; i < v.GetLength () ; ++i) +#else + for (u_int i = 0 ; i < (u_int) v.length () ; ++i) +#endif + this->put (v[i]); + } + + osfx (); + + return *this; +} + + +////////////////////////////////////////////////////////////////// +// A more clever put operator for strings that knows how to +// deal with quoted strings containing back-quoted quotes. +// +template <class STREAM> ACE_IOStream_T<STREAM> & +ACE_IOStream_T<STREAM>::operator>> (QuotedString & str) +{ + if (ipfx0 ()) + { + char c; + + if (! (*this >> c)) // eat space up to the first char + // this->set (ios::eofbit|ios::failbit); + return *this; + + str = ""; // Initialize the string + + // if we don't have a quote, append until we see space + if (c != '"') + for (str = c ; this->get (c) && !isspace (c) ; str += c) + continue; + else + for (; this->get (c) && c != '"' ; str += c) + if (c == '\\') + { + this->get (c); + if (c != '"') + str += '\\'; + } + } + + isfx (); + + return *this; +} + +template <class STREAM> ACE_IOStream_T<STREAM> & +ACE_IOStream_T<STREAM>::operator<< (QuotedString & str) +{ + if (opfx ()) + { + this->put ('"'); + for (u_int i = 0 ; i < str.length () ; ++i) + { + if (str[i] == '"') + this->put ('\\'); + this->put (str[i]); + } + this->put ('"'); + } + + osfx (); + + return *this; +} + +#endif /* ACE_HAS_STRING_CLASS */ +#endif /* ACE_IOSTREAM_T_C */ + diff --git a/ace/IOStream_T.h b/ace/IOStream_T.h new file mode 100644 index 00000000000..51e74447d70 --- /dev/null +++ b/ace/IOStream_T.h @@ -0,0 +1,280 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// IOStream_T.h +// +// = AUTHOR +// James CE Johnson <jcej@lads.com> +// +// = COAUTHOR +// Jim Crossley <jim@lads.com> +// +// = NOTE +// This file should not be #included directly by application code. +// Instead, it should #include "ace/IOStream.h". That's because +// we only put some conditional compilations in that file. +// +// ============================================================================ + +#if !defined (ACE_IOSTREAM_T_H) +#define ACE_IOSTREAM_T_H + +#include "ace/IOStream.h" +#include <iomanip.h> + +/////////////////////////////////////////////////////////////////////////// + +template <class STREAM> +class ACE_Streambuf_T : public ACE_Streambuf +{ +public: + ACE_Streambuf_T (STREAM * peer, u_int streambuf_size = ACE_STREAMBUF_SIZE, int io_mode = ios::in | ios::out); + // We will be given a STREAM by the iostream object which creates + // us. See the ACE_IOStream_T template for how that works. Like + // other streambuf objects, we can be input-only, output-only or + // both. + + virtual ssize_t send ( char * buf, ssize_t len ) + { + return peer_->send_n(buf,len); + } + virtual ssize_t recv ( char * buf, ssize_t len, ACE_Time_Value * tv = NULL ) + { + return this->recv( buf, len, 0, tv ); + } + virtual ssize_t recv ( char * buf, ssize_t len, int flags, ACE_Time_Value * tv = NULL ) + { + ssize_t rval = peer_->recv(buf,len,flags,tv); + return rval; + } + virtual ssize_t recv_n( char * buf, ssize_t len, int flags = 0, ACE_Time_Value * tv = NULL ) + { + ssize_t rval = peer_->recv_n(buf,len,flags,tv); + return rval; + } + +protected: + STREAM * peer_; + // This will be our ACE_SOCK_Stream or similar object. + + virtual ACE_HANDLE get_handle(void) + { + return peer_ ? peer_->get_handle() : 0 ; + } +}; + +/////////////////////////////////////////////////////////////////////////// + +template <class STREAM> +class ACE_IOStream_T : public iostream, public STREAM + // = TITLE + // A template adapter for creating an iostream-like object using + // an ACE IPC Stream for the actual I/O. Iostreams use an + // underlying streambuf object for the IO interface. The + // iostream class and derivatives provide you with a host of + // convenient operators that access the streambuf. + // + // = DESCRIPTION + // We inherit all characteristics of iostream and your <STREAM> + // class. When you create a new class from this template, you + // can use it anywhere you would have used your original + // <STREAM> class. + // + // To create an iostream for your favorite ACE IPC class (e.g., + // <ACE_SOCK_Stream>), feed that class to this template's + // <STREAM> parameter, e.g., + // + // typedef ACE_Svc_Handler<ACE_SOCK_iostream, + // ACE_INET_Addr, ACE_NULL_SYNCH> + // Service_Handler; + // + // Because the operators in the iostream class are not virtual, + // you cannot easily provide overloads in your custom + // ACE_IOStream_T classes. To make these things work correctly, + // you need to overload ALL operators of the ACE_IOStream_T you + // create. I've attempted to do that here to make things easier + // for you but there are no guarantees. + // + // In the iostream.cpp file is an example of why it is necessary + // to overload all of the get/put operators when you want to + // customize only one or two. +{ +public: + ACE_IOStream_T (STREAM & stream, u_int streambuf_size = ACE_STREAMBUF_SIZE); + ACE_IOStream_T (u_int streambuf_size = ACE_STREAMBUF_SIZE); + // The default constructor. This will initiailze your STREAM and + // then setup the iostream baseclass to use a custom streambuf based + // on STREAM. + + virtual ~ACE_IOStream_T (void); + // We have to get rid of the streambuf_ ourselves since we gave it + // to iostream(); + + virtual int close (void); + // The only ambituity in the multiple inheritance is the close() + // function. + +#if defined (ACE_HAS_STRING_CLASS) + virtual ACE_IOStream_T<STREAM> & operator>>(ACE_IOStream_String & v); + // A simple string operator. The base iostream has 'em for char* + // but that isn't always the best thing for a String. If we don't + // provide our own here, we may not get what we want. + + virtual ACE_IOStream_T<STREAM> & operator<<(ACE_IOStream_String & v); + // The converse of the String put operator. + + virtual ACE_IOStream_T<STREAM> & operator>>(QuotedString &v); + // A more clever operator that handles quoted strings so that we + // can get strings containing whitespace! + + virtual ACE_IOStream_T<STREAM> & operator<<(QuotedString &v); + // The converse of the QuotedString put operator. +#endif /* ACE_HAS_STRING_CLASS */ + + // = Using the macros to provide get/set operators. + GETPUT_FUNC_SET (ACE_IOStream_T<STREAM>) + +#if defined (ACE_LACKS_IOSTREAM_FX) + virtual int ipfx (int need = 0) { return good(); } + virtual int ipfx0(void) { return good(); } // Optimized ipfx(0) + virtual int ipfx1(void) { return good(); } // Optimized ipfx(1) + virtual void isfx (void) { return; } + virtual int opfx (void) { return good(); } + virtual void osfx (void) { put(' '); return; } +#else +#if defined (__GNUC__) + virtual int ipfx0(void) { return(iostream::ipfx0()); } // Optimized ipfx(0) + virtual int ipfx1(void) { return(iostream::ipfx1()); } // Optimized ipfx(1) +#else + virtual int ipfx0(void) { return(iostream::ipfx(0)); } + virtual int ipfx1(void) { return(iostream::ipfx(1)); } +#endif + virtual int ipfx (int need = 0) { return(iostream::ipfx(need)); } + virtual void isfx (void) { iostream::isfx(); return; } + virtual int opfx (void) { return(iostream::opfx()); } + virtual void osfx (void) { iostream::osfx(); return; } +#endif /* ACE_LACKS_IOSTREAM_FX */ + + ACE_IOStream_T<STREAM> & operator>>(ACE_Time_Value *&tv); + // Allow the programmer to provide a timeout for read operations. + // Give it a pointer to NULL to block forever. + +protected: + + ACE_Streambuf_T<STREAM> *streambuf_; + // This is where all of the action takes place. The + // streambuf_ is the interface to the underlying STREAM. + +private: + // We move these into the private section so that they cannot + // be used by the application programmer. This is necessary + // because streambuf_ will be buffering IO on the STREAM + // object. If these functions were used in your program, + // there is a danger of getting the datastream out of sync. + ssize_t send (...); + ssize_t recv (...); + ssize_t send_n (...); + ssize_t recv_n (...); +}; + +/////////////////////////////////////////////////////////////////////////// + +template <class STREAM> +class ACE_SOCK_Dgram_SC : public STREAM +// Datagrams don't have the notion of a "peer". Each send and receive +// on a datagram can go to a different peer if you want. If you're +// using datagrams for stream activity, you probably want 'em all to +// go to (and come from) the same place. That's what this class is +// for. BTW: 'Dgram_SC' is short for 'Datagram-Self-Contained'. +// Here, we keep an address object so that we can remember who last +// sent us data. When we write back, we're then able to write back to +// that same address. +{ +protected: + ACE_INET_Addr peer_; + +public: + ACE_SOCK_Dgram_SC (void) + { + } + + ACE_SOCK_Dgram_SC (STREAM &source, ACE_INET_Addr &dest) + : STREAM (source), peer_ (dest) + { + } + + inline ssize_t send_n (char *buf, ssize_t len) + { + return STREAM::send (buf, len, peer_); + } + + inline ssize_t recv (char * buf, ssize_t len, ACE_Time_Value * tv = NULL) + { + return recv (buf, len, 0, tv); + } + + inline ssize_t recv (char * buf, ssize_t len, int flags, ACE_Time_Value * tv = NULL) + { + if (tv != 0) + { + ACE_HANDLE handle = this->get_handle (); + ACE_Handle_Set handle_set; + + handle_set.set_bit (handle); + + switch (ACE_OS::select (int (handle) + 1, + (fd_set *) handle_set, // read_fds. + (fd_set *) 0, // write_fds. + (fd_set *) 0, // exception_fds. + tv)) + { + case 0: + errno = ETIME; + case -1: + return -1; + default: + ; // Do the 'recv' below + } + } + + int rval = STREAM::recv (buf, len, peer_, flags); +#ifdef WIN32 + if (rval == SOCKET_ERROR) + if (WSAGetLastError() == WSAEMSGSIZE) + if (flags & MSG_PEEK) + rval = len; +#endif + + return rval < len ? rval : len; + } + inline ssize_t recv_n (char * buf, + ssize_t len, int flags = 0, + ACE_Time_Value * tv = NULL) + { + int rval = this->recv (buf, len, flags, tv); + return rval; + } + + inline int get_remote_addr (ACE_INET_Addr &addr) const + { + addr = peer_; + return 0; + } + +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/IOStream_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("IOStream_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ACE_IOSTREAM_T_H */ diff --git a/ace/README b/ace/README index ccca38a3464..129abaedc40 100644 --- a/ace/README +++ b/ace/README @@ -162,6 +162,7 @@ ACE_HAS_XLI Platform has the XLI version of TLI ACE_HAS_XT Platform has Xt and Motif ACE_HAS_YIELD_VOID_PTR Platform requires pthread_yield() to take a NULL. ACE_LACKS_ACCESS Platform lacks access() (e.g., VxWorks and Chorus) +ACE_LACKS_ACE_IOSTREAM Platform can not build ace/IOStream{,_T}.cpp. This does not necessarily mean that the platform does not support iostreams. ACE_LACKS_CONST_STRBUF_PTR Platform uses struct strbuf * rather than const struct strbuf * (e.g., HP/UX 10.x) ACE_LACKS_CONST_TIMESPEC_PTR Platform forgot const in cond_timewait (e.g., HP/UX). ACE_LACKS_COND_T Platform lacks condition variables (e.g., Win32 and VxWorks) |