///////////////////////////////////////////////////////////////////////////////
// This is a modified version of the std::basic_filebuf from libc++
// (http://libcxx.llvm.org/).
// It allows one to create basic_filebuf from an existing FILE* handle or file
// descriptor.
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source License licenses. See LICENSE.TXT for details (included at the
// bottom).
///////////////////////////////////////////////////////////////////////////////
#ifndef KALDI_UTIL_BASIC_FILEBUF_H_
#define KALDI_UTIL_BASIC_FILEBUF_H_
///////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <cstdio>
#include <cstring>
///////////////////////////////////////////////////////////////////////////////
namespace kaldi
{
///////////////////////////////////////////////////////////////////////////////
template <typename CharT, typename Traits = std::char_traits<CharT> >
class basic_filebuf : public std::basic_streambuf<CharT, Traits>
{
public:
typedef CharT char_type;
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::state_type state_type;
basic_filebuf();
basic_filebuf(basic_filebuf&& rhs);
virtual ~basic_filebuf();
basic_filebuf& operator=(basic_filebuf&& rhs);
void swap(basic_filebuf& rhs);
bool is_open() const;
basic_filebuf* open(const char* s, std::ios_base::openmode mode);
basic_filebuf* open(const std::string& s, std::ios_base::openmode mode);
basic_filebuf* open(int fd, std::ios_base::openmode mode);
basic_filebuf* open(FILE* f, std::ios_base::openmode mode);
basic_filebuf* close();
FILE* file() { return this->_M_file; }
int fd() { return fileno(this->_M_file); }
protected:
int_type underflow() override;
int_type pbackfail(int_type c = traits_type::eof()) override;
int_type overflow (int_type c = traits_type::eof()) override;
std::basic_streambuf<char_type, traits_type>* setbuf(char_type* s, std::streamsize n) override;
pos_type seekoff(off_type off, std::ios_base::seekdir way,
std::ios_base::openmode wch = std::ios_base::in | std::ios_base::out) override;
pos_type seekpos(pos_type sp,
std::ios_base::openmode wch = std::ios_base::in | std::ios_base::out) override;
int sync() override;
void imbue(const std::locale& loc) override;
protected:
char* _M_extbuf;
const char* _M_extbufnext;
const char* _M_extbufend;
char _M_extbuf_min[8];
size_t _M_ebs;
char_type* _M_intbuf;
size_t _M_ibs;
FILE* _M_file;
const std::codecvt<char_type, char, state_type>* _M_cv;
state_type _M_st;
state_type _M_st_last;
std::ios_base::openmode _M_om;
std::ios_base::openmode _M_cm;
bool _M_owns_eb;
bool _M_owns_ib;
bool _M_always_noconv;
const char* _M_get_mode(std::ios_base::openmode mode);
bool _M_read_mode();
void _M_write_mode();
};
///////////////////////////////////////////////////////////////////////////////
template <class CharT, class Traits>
basic_filebuf<CharT, Traits>::basic_filebuf()
: _M_extbuf(nullptr),
_M_extbufnext(nullptr),
_M_extbufend(nullptr),
_M_ebs(0),
_M_intbuf(nullptr),
_M_ibs(0),
_M_file(nullptr),
_M_cv(nullptr),
_M_st(),
_M_st_last(),
_M_om(std::ios_base::openmode(0)),
_M_cm(std::ios_base::openmode(0)),
_M_owns_eb(false),
_M_owns_ib(false),
_M_always_noconv(false)
{
if (std::has_facet<std::codecvt<char_type, char, state_type> >(this->getloc()))
{
_M_cv = &std::use_facet<std::codecvt<char_type, char, state_type> >(this->getloc());
_M_always_noconv = _M_cv->always_noconv();
}
setbuf(0, 4096);
}
///////////////////////////////////////////////////////////////////////////////
template <class