// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SOCKStREAMBUF_Hh_
#define DLIB_SOCKStREAMBUF_Hh_
#include <iosfwd>
#include <limits>
#include <memory>
#include <streambuf>
#include "../assert.h"
#include "../sockets.h"
#include "sockstreambuf_abstract.h"
#include "sockstreambuf_unbuffered.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class sockstreambuf : public std::streambuf
{
/*!
INITIAL VALUE
- con == a connection
- in_buffer == an array of in_buffer_size bytes
- out_buffer == an array of out_buffer_size bytes
CONVENTION
- in_buffer == the input buffer used by this streambuf
- out_buffer == the output buffer used by this streambuf
- max_putback == the maximum number of chars to have in the put back buffer.
!*/
public:
// These typedefs are here for backwards compatibility with previous versions of
// dlib.
typedef sockstreambuf_unbuffered kernel_1a;
typedef sockstreambuf kernel_2a;
sockstreambuf (
connection* con_,
std::streamsize out_buffer_size_ = 10000,
std::streamsize in_buffer_size_ = 10000,
std::streamsize max_putback_ = 4
) :
con(*con_),
out_buffer_size(out_buffer_size_),
in_buffer_size(in_buffer_size_),
max_putback(max_putback_),
autoflush(false)
{
DLIB_ASSERT(0 < out_buffer_size && out_buffer_size <= std::numeric_limits<int>::max(),
"out_buffer_size must be in the range (0, INT_MAX]");
DLIB_ASSERT(0 < in_buffer_size && in_buffer_size <= std::numeric_limits<int>::max(),
"in_buffer_size must be in the range (0, INT_MAX]");
DLIB_ASSERT(0 <= max_putback && max_putback < in_buffer_size,
"max_putback must be in the range [0, in_buffer_size)");
out_buffer.reset(new char[static_cast<size_t>(out_buffer_size)]);
in_buffer.reset(new char[static_cast<size_t>(in_buffer_size)]);
init();
}
sockstreambuf (
const std::unique_ptr<connection>& con_,
std::streamsize out_buffer_size_ = 10000,
std::streamsize in_buffer_size_ = 10000,
std::streamsize max_putback_ = 4
) : sockstreambuf(
con_.get(),
out_buffer_size_,
in_buffer_size_,
max_putback_
)
{}
virtual ~sockstreambuf (
)
{
sync();
}
connection* get_connection (
) { return &con; }
void flush_output_on_read()
{
autoflush = true;
}
bool flushes_output_on_read() const
{
return autoflush;
}
void do_not_flush_output_on_read()
{
autoflush = false;
}
protected:
void init (
)
{
setp(out_buffer.get(), out_buffer.get() + (out_buffer_size-1));
setg(in_buffer.get()+max_putback,
in_buffer.get()+max_putback,
in_buffer.get()+max_putback);
}
int flush_out_buffer (
)
{
int num = static_cast<int>(pptr()-pbase());
if (con.write(out_buffer.get(),num) != num)
{
// the write was not successful so return EOF
return EOF;
}
pbump(-num);
return num;
}
// output functions
int_type overflow (
int_type c
);
int sync (
)
{
if (flush_out_buffer() == EOF)
{
// an error occurred
return -1;
}
return 0;
}
std::streamsize xsputn (
const char* s,
std::streamsize num
);
// input functions
int_type underflow(
);
std::streamsize xsgetn (
char_type* s,
std::streamsize n
);
private:
// member data
connection& con;
const std::streamsize out_buffer_size;
const std::streamsize in_buffer_size;
const std::streamsize max_putback;
std::unique_ptr<char[]> out_buffer;
std::unique_ptr<char[]> in_buffer;
bool autoflush;
};
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "sockstreambuf.cpp"
#endif
#endif // DLIB_SOCKStREAMBUF_Hh_