193 lines
5.4 KiB
Plaintext
193 lines
5.4 KiB
Plaintext
|
|
#pragma GCC system_header
|
||
|
|
|
||
|
|
#ifndef _LIBCXX_STREAMBUF
|
||
|
|
#define _LIBCXX_STREAMBUF
|
||
|
|
|
||
|
|
#include <__config>
|
||
|
|
#include <algorithm>
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <ios>
|
||
|
|
#include <iosfwd>
|
||
|
|
#include <string>
|
||
|
|
|
||
|
|
_LIBCXX_BEGIN_NAMESPACE_STD
|
||
|
|
|
||
|
|
template <class CharT, class Traits>
|
||
|
|
class basic_streambuf {
|
||
|
|
public:
|
||
|
|
using char_type = CharT;
|
||
|
|
using traits_type = Traits;
|
||
|
|
using int_type = typename traits_type::int_type;
|
||
|
|
using pos_type = typename traits_type::pos_type;
|
||
|
|
using off_type = typename traits_type::off_type;
|
||
|
|
|
||
|
|
virtual ~basic_streambuf() = default;
|
||
|
|
|
||
|
|
// TODO: Add locales
|
||
|
|
|
||
|
|
basic_streambuf* pubsetbuf(char_type* s, streamsize n) { return setbuf(s, n); }
|
||
|
|
pos_type pubseekoff(off_type off, ios_base::seekdir dir, ios_base::openmode which = ios_base::in | ios_base::out) { return seekoff(off, dir, which); }
|
||
|
|
pos_type pubseekpos(pos_type pos, ios_base::openmode which = ios_base::in | ios_base::out) { return seekpos(pos, which); }
|
||
|
|
int pubsync() { return sync(); }
|
||
|
|
|
||
|
|
streamsize in_avail()
|
||
|
|
{
|
||
|
|
if (egptr() - gptr() > 0) {
|
||
|
|
return egptr() - gptr();
|
||
|
|
}
|
||
|
|
return showmanyc();
|
||
|
|
}
|
||
|
|
|
||
|
|
int_type snextc()
|
||
|
|
{
|
||
|
|
if (sbumpc() == traits_type::eof()) {
|
||
|
|
return traits_type::eof();
|
||
|
|
}
|
||
|
|
return sgetc();
|
||
|
|
}
|
||
|
|
|
||
|
|
int_type sbumpc()
|
||
|
|
{
|
||
|
|
if (gptr() == egptr()) {
|
||
|
|
return uflow();
|
||
|
|
}
|
||
|
|
return Traits::to_int_type(*m_gptr++);
|
||
|
|
}
|
||
|
|
|
||
|
|
int_type sgetc()
|
||
|
|
{
|
||
|
|
if (gptr() == egptr()) {
|
||
|
|
return underflow();
|
||
|
|
}
|
||
|
|
return Traits::to_int_type(*gptr());
|
||
|
|
}
|
||
|
|
|
||
|
|
streamsize sgetn(char_type* s, streamsize n) { return xsgetn(s, n); }
|
||
|
|
|
||
|
|
int_type sputc(char_type c)
|
||
|
|
{
|
||
|
|
if (pptr() == epptr()) {
|
||
|
|
return overflow(c);
|
||
|
|
}
|
||
|
|
*pptr() = c;
|
||
|
|
m_pptr++;
|
||
|
|
return Traits::to_int_type(c);
|
||
|
|
}
|
||
|
|
|
||
|
|
streamsize sputn(const char_type* s, streamsize n) { return xsputn(s, n); }
|
||
|
|
|
||
|
|
int_type sputbackc(char_type c)
|
||
|
|
{
|
||
|
|
if (eback() == egptr() || traits_type::eq(c, egptr()[-1])) {
|
||
|
|
return pbackfail(c);
|
||
|
|
}
|
||
|
|
return traits_type::to_int_type(*(--m_gptr));
|
||
|
|
}
|
||
|
|
|
||
|
|
int_type sungetc()
|
||
|
|
{
|
||
|
|
if (eback() == egptr())
|
||
|
|
return pbackfail();
|
||
|
|
return traits_type::to_int_type(*(--m_gptr));
|
||
|
|
}
|
||
|
|
|
||
|
|
protected:
|
||
|
|
basic_streambuf() = default;
|
||
|
|
|
||
|
|
virtual basic_streambuf* setbuf(char_type* s, streamsize n) { return this; }
|
||
|
|
virtual pos_type seekoff(off_type off, ios_base::seekdir dir, ios_base::openmode which) { return pos_type(off_type(-1)); }
|
||
|
|
virtual pos_type seekpos(pos_type pos, ios_base::openmode which) { return pos_type(off_type(-1)); }
|
||
|
|
virtual int sync() { return 0; }
|
||
|
|
|
||
|
|
virtual streamsize showmanyc() { return 0; }
|
||
|
|
virtual int_type underflow() { return traits_type::eof(); }
|
||
|
|
virtual int_type uflow()
|
||
|
|
{
|
||
|
|
if (underflow() == traits_type::eof()) {
|
||
|
|
return traits_type::eof();
|
||
|
|
}
|
||
|
|
return traits_type::to_int_type(*m_gptr++);
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual streamsize xsgetn(char_type* s, streamsize count)
|
||
|
|
{
|
||
|
|
auto eof = traits_type::eof();
|
||
|
|
int_type tmpcint;
|
||
|
|
for (streamsize i = 0; i < count;) {
|
||
|
|
if (gptr() < egptr()) {
|
||
|
|
streamsize can_get = std::min(static_cast<streamsize>(egptr() - gptr()), count);
|
||
|
|
traits_type::copy(s, gptr(), can_get);
|
||
|
|
this->gbump(can_get);
|
||
|
|
s += can_get;
|
||
|
|
i += can_get;
|
||
|
|
} else if ((tmpcint = uflow()) != eof) {
|
||
|
|
*s = traits_type::to_char_type(tmpcint);
|
||
|
|
s++;
|
||
|
|
i++;
|
||
|
|
} else {
|
||
|
|
return i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
char_type* eback() const { return m_eback; }
|
||
|
|
char_type* gptr() const { return m_gptr; }
|
||
|
|
char_type* egptr() const { return m_egptr; }
|
||
|
|
|
||
|
|
void gbump(int n) { m_gptr += n; }
|
||
|
|
void setg(char_type* gbeg, char_type* gcurr, char_type* gend)
|
||
|
|
{
|
||
|
|
m_eback = gbeg;
|
||
|
|
m_gptr = gcurr;
|
||
|
|
m_egptr = gend;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual streamsize xsputn(const char_type* s, streamsize count)
|
||
|
|
{
|
||
|
|
auto eof = traits_type::eof();
|
||
|
|
int_type tmpcint;
|
||
|
|
for (streamsize i = 0; i < count;) {
|
||
|
|
if (pptr() < epptr()) {
|
||
|
|
streamsize can_put = std::min(static_cast<streamsize>(egptr() - gptr()), count);
|
||
|
|
traits_type::copy(pptr(), s, can_put);
|
||
|
|
this->pbump(can_put);
|
||
|
|
s += can_put;
|
||
|
|
i += can_put;
|
||
|
|
} else if ((tmpcint = overflow(*s)) != eof) {
|
||
|
|
s++;
|
||
|
|
i++;
|
||
|
|
} else {
|
||
|
|
return i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual int_type overflow(int_type ch = traits_type::eof()) { return traits_type::eof(); }
|
||
|
|
|
||
|
|
char_type* pbase() const { return m_pbase; }
|
||
|
|
char_type* pptr() const { return m_pptr; }
|
||
|
|
char_type* epptr() const { return m_epptr; }
|
||
|
|
void pbump(int n) { m_pptr += n; }
|
||
|
|
|
||
|
|
void setg(char_type* pbeg, char_type* pend)
|
||
|
|
{
|
||
|
|
m_pbase = m_pptr = pbeg;
|
||
|
|
m_epptr = pend;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual int_type pbackfail(int_type c = traits_type::eof()) { return traits_type::eof(); }
|
||
|
|
|
||
|
|
private:
|
||
|
|
char_type* m_eback { nullptr };
|
||
|
|
char_type* m_gptr { nullptr };
|
||
|
|
char_type* m_egptr { nullptr };
|
||
|
|
char_type* m_pbase { nullptr };
|
||
|
|
char_type* m_pptr { nullptr };
|
||
|
|
char_type* m_epptr { nullptr };
|
||
|
|
};
|
||
|
|
|
||
|
|
_LIBCXX_END_NAMESPACE_STD
|
||
|
|
|
||
|
|
#endif // _LIBCXX_STREAMBUF
|