|
Boost : |
From: mfdylan (dylan_at_[hidden])
Date: 2001-12-19 01:22:57
--- In boost_at_y..., "rtougher" <rtougher_at_y...> wrote:
> I've put "boost_sockets.hpp" in the sockets3 directory of the files
> section.
>
> All suggestions are welcome!
>
Here's a quick&dirty socketbuf template, better would be one that
derived from a streambuf that used an ABC interface to do the actual
read/write/availability checking (why the std library doesn't have
this I really don't understand). Your low-level socket class could
then derive from this.
struct socket_exception { };
template<class E, class T = std::char_traits<E> >
class basic_socketbuf : public std::basic_streambuf<E, T>
{
public:
basic_socketbuf(int sock = 0, int bufsize = 4096)
: m_socket(sock)
{
E* buf;
buf = new E[bufsize];
setg(buf, buf, buf);
m_egbuf = buf + bufsize;
buf = new E[bufsize]; // exception safety? huh?
setp(buf, buf + bufsize);
}
virtual ~basic_socketbuf()
{
delete [] eback();
delete [] pbase();
closesocket(m_socket);
}
unsigned long avail() const
{
if (gptr() < egptr())
return egptr() - gptr();
u_long ret = 0;
ioctlsocket(m_socket, FIONREAD, &ret);
return ret;
}
protected:
virtual int_type overflow(int_type c = T::eof())
{
if (T::eq_int_type(T::eof(), c))
return T::not_eof(c);
if (pptr() < epptr())
{
*pptr() = T::to_char_type(c);
if (c == '\n')
sync();
}
else
sync();
return c;
}
virtual int_type pbackfail(int_type c = T::eof())
{
if (eback() < gptr())
{
gbump(-1);
if (!T::eq_int_type(T::eof(), c))
*gptr() = c;
return T::not_eof(c);
}
return T::eof();
}
virtual int_type underflow()
{
if (gptr() < egptr())
return T::to_int_type(*gptr());
if (egbuf() - gptr() < gptr() - eback())
setg(eback(), eback(), eback());
int r = recv(m_socket, gptr(), egbuf() - gptr(), 0);
if (r == 0)
return T::eof();
else if (r == -1)
throw socket_exception();
setg(eback(), gptr(), gptr() + r);
return *gptr();
}
virtual int sync()
{
int len = pptr() - pbase();
if (send(m_socket, pbase(), len, 0) != len)
throw socket_exception();
setp(pbase(), pbase(), epptr());
return 0;
}
private:
inline E* egbuf() { return m_egbuf; }
E* m_egbuf;
int m_socket;
};
template<class E, class T = std::char_traits<E> >
class basic_socketstream : public std::basic_iostream<E, T>
{
public:
explicit basic_socketstream(int sock) :
std::basic_iostream<E, T>(&m_buf), m_buf(sock) { }
basic_socketbuf<E, T>* rdbuf() const { return &m_buf; }
unsigned long avail() const { return m_buf.avail(); }
private:
basic_socketbuf<E, T> m_buf;
};
typedef basic_socketbuf<char> socketbuf;
typedef basic_socketbuf<wchar_t> wsocketbuf;
typedef basic_socketstream<char> socketstream;
typedef basic_socketstream<wchar_t> wsocketstream;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk