/* * Copyright (C) 2001-2004 Peter J Jones (pjones@pmade.org) * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of the Author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /** @file * This file contains the definition of the Netxx:Netbuf template class. **/ #ifndef _netxx_netbuf_h_ #define _netxx_netbuf_h_ // Netxx includes #include // standard includes #include #include #include namespace { const std::streamsize PUTBACK_SIZE = 4; } namespace Netxx { /** * The Netxx::Netbuf template class is a IOStreams streambuf. After you * create an instance of a Netxx::Netbuf class you can pass a pointer to it * to a std::iostream, std::ostream or std::istream class. Then you can do * basic IOStreams operations on it. * * This streambuf is buffered so you should call std::flush to make sure it * sends the data that you inserted. **/ template > class Netbuf : public std::basic_streambuf { public: /// int type typedef typename std::basic_streambuf::int_type int_type; /// char type typedef typename std::basic_streambuf::char_type char_type; //#################################################################### /** * Construct a Netxx::Netbuf object and link it to the given StreamBase * object. The StreamBase object will be used for reading and writing to * the Netbuf (std::streambuf) object. * * @param stream The StreamBase object to use for reading and writing. * @author Peter Jones **/ //#################################################################### explicit Netbuf (StreamBase &stream); //#################################################################### /** * Netxx::Netbuf class destructor. * * @author Peter Jones **/ //#################################################################### ~Netbuf (void); protected: // TODO streamsize xsputn (const char_type *s, streamsize n); int_type overflow (int_type c=traits_type::eof()); int sync (void); int_type underflow (void); int_type pbackfail (int_type c); private: StreamBase &stream_; charT putbuf_[bufsize]; charT getbuf_[bufsize]; int buffer_out (void); int buffer_in (void); Netbuf (const Netbuf&); Netbuf& operator= (const Netbuf&); }; // end Netxx::Netbuf class //############################################################################# template Netbuf::Netbuf (StreamBase &stream) : stream_(stream) { setp(putbuf_, putbuf_ + bufsize); setg(getbuf_+PUTBACK_SIZE, getbuf_+PUTBACK_SIZE, getbuf_+PUTBACK_SIZE); } //############################################################################# template Netbuf::~Netbuf (void) { sync(); } //############################################################################# template typename Netbuf::int_type Netbuf::overflow (int_type c) { if (buffer_out() < 0) { return traits_type::eof(); } else if (!traits_type::eq_int_type(c, traits_type::eof())) { return sputc(c); } else { return traits_type::not_eof(c); } } //############################################################################# template int Netbuf::sync (void) { return buffer_out(); } //############################################################################# template int Netbuf::buffer_out (void) { int length = pptr() - pbase(); int rc = stream_.write(putbuf_, length); pbump(-length); return rc; } //############################################################################# template typename Netbuf::int_type Netbuf::underflow (void) { if (gptr() < egptr()) return traits_type::to_int_type(*gptr()); if (buffer_in() < 0) return traits_type::eof(); else return traits_type::to_int_type(*gptr()); } //############################################################################# template typename Netbuf::int_type Netbuf::pbackfail(int_type c) { if (gptr() != eback()) { gbump(-1); if (!traits_type::eq_int_type(c, traits_type::eof())) { *(gptr()) = traits_type::to_char_type(c); } return traits_type::not_eof(c); } else { return traits_type::eof(); } } //############################################################################# template int Netbuf::buffer_in (void) { std::streamsize number_putbacks = std::min(gptr() - eback(), PUTBACK_SIZE); std::memcpy(getbuf_ + (PUTBACK_SIZE - number_putbacks) * sizeof(char_type), gptr() - number_putbacks * sizeof(char_type), number_putbacks * sizeof(char_type)); int rc = stream_.read(getbuf_ + PUTBACK_SIZE * sizeof(char_type), bufsize - PUTBACK_SIZE); if (rc <= 0) { setg(0, 0, 0); return -1; } else { setg(getbuf_ + PUTBACK_SIZE - number_putbacks, getbuf_ + PUTBACK_SIZE, getbuf_ + PUTBACK_SIZE + rc); return rc; } } //############################################################################# } // end Netxx namespace #endif