Skip to content
Snippets Groups Projects
Commit 1d19465c authored by Drake Arconis's avatar Drake Arconis
Browse files

Use typedefs of std::ifstream and std::ofstream on mac and linux and minor cleanup

parent 33f16c9b
No related branches found
No related tags found
No related merge requests found
......@@ -421,447 +421,20 @@ LLFILE * LLFile::_Fiopen(const std::string& filename,
#endif /* LL_WINDOWS */
/************** llstdio file buffer ********************************/
// *TODO: Seek the underlying c stream for better cross-platform compatibility?
#if !defined(LL_WINDOWS) && !defined(_LIBCPP_VERSION)
llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c)
{
int_type __ret = traits_type::eof();
const bool __testeof = traits_type::eq_int_type(__c, __ret);
const bool __testout = _M_mode & ios_base::out;
if (__testout && !_M_reading)
{
if (this->pbase() < this->pptr())
{
// If appropriate, append the overflow char.
if (!__testeof)
{
*this->pptr() = traits_type::to_char_type(__c);
this->pbump(1);
}
// Convert pending sequence to external representation,
// and output.
if (_convert_to_external(this->pbase(),
this->pptr() - this->pbase()))
{
_M_set_buffer(0);
__ret = traits_type::not_eof(__c);
}
}
else if (_M_buf_size > 1)
{
// Overflow in 'uncommitted' mode: set _M_writing, set
// the buffer to the initial 'write' mode, and put __c
// into the buffer.
_M_set_buffer(0);
_M_writing = true;
if (!__testeof)
{
*this->pptr() = traits_type::to_char_type(__c);
this->pbump(1);
}
__ret = traits_type::not_eof(__c);
}
else
{
// Unbuffered.
char_type __conv = traits_type::to_char_type(__c);
if (__testeof || _convert_to_external(&__conv, 1))
{
_M_writing = true;
__ret = traits_type::not_eof(__c);
}
}
}
return __ret;
}
bool llstdio_filebuf::_convert_to_external(char_type* __ibuf,
std::streamsize __ilen)
{
// Sizes of external and pending output.
streamsize __elen;
streamsize __plen;
if (__check_facet(_M_codecvt).always_noconv())
{
//__elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
__elen = fwrite(reinterpret_cast<void*>(__ibuf), 1,
__ilen, _M_file.file());
__plen = __ilen;
}
else
{
// Worst-case number of external bytes needed.
// XXX Not done encoding() == -1.
streamsize __blen = __ilen * _M_codecvt->max_length();
char* __buf = static_cast<char*>(__builtin_alloca(__blen));
char* __bend;
const char_type* __iend;
codecvt_base::result __r;
__r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
__iend, __buf, __buf + __blen, __bend);
if (__r == codecvt_base::ok || __r == codecvt_base::partial)
__blen = __bend - __buf;
else if (__r == codecvt_base::noconv)
{
// Same as the always_noconv case above.
__buf = reinterpret_cast<char*>(__ibuf);
__blen = __ilen;
}
else
__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
"conversion error"));
//__elen = _M_file.xsputn(__buf, __blen);
__elen = fwrite(__buf, 1, __blen, _M_file.file());
__plen = __blen;
// Try once more for partial conversions.
if (__r == codecvt_base::partial && __elen == __plen)
{
const char_type* __iresume = __iend;
streamsize __rlen = this->pptr() - __iend;
__r = _M_codecvt->out(_M_state_cur, __iresume,
__iresume + __rlen, __iend, __buf,
__buf + __blen, __bend);
if (__r != codecvt_base::error)
{
__rlen = __bend - __buf;
//__elen = _M_file.xsputn(__buf, __rlen);
__elen = fwrite(__buf, 1, __rlen, _M_file.file());
__plen = __rlen;
}
else
{
__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
"conversion error"));
}
}
}
return __elen == __plen;
}
llstdio_filebuf::int_type llstdio_filebuf::underflow()
{
int_type __ret = traits_type::eof();
const bool __testin = _M_mode & ios_base::in;
if (__testin)
{
if (_M_writing)
{
if (overflow() == traits_type::eof())
return __ret;
//_M_set_buffer(-1);
//_M_writing = false;
}
// Check for pback madness, and if so switch back to the
// normal buffers and jet outta here before expensive
// fileops happen...
_M_destroy_pback();
if (this->gptr() < this->egptr())
return traits_type::to_int_type(*this->gptr());
// Get and convert input sequence.
const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
// Will be set to true if ::fread() returns 0 indicating EOF.
bool __got_eof = false;
// Number of internal characters produced.
streamsize __ilen = 0;
codecvt_base::result __r = codecvt_base::ok;
if (__check_facet(_M_codecvt).always_noconv())
{
//__ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()),
// __buflen);
__ilen = fread(reinterpret_cast<void*>(this->eback()), 1,
__buflen, _M_file.file());
if (__ilen == 0)
__got_eof = true;
}
else
{
// Worst-case number of external bytes.
// XXX Not done encoding() == -1.
const int __enc = _M_codecvt->encoding();
streamsize __blen; // Minimum buffer size.
streamsize __rlen; // Number of chars to read.
if (__enc > 0)
__blen = __rlen = __buflen * __enc;
else
{
__blen = __buflen + _M_codecvt->max_length() - 1;
__rlen = __buflen;
}
const streamsize __remainder = _M_ext_end - _M_ext_next;
__rlen = __rlen > __remainder ? __rlen - __remainder : 0;
// An imbue in 'read' mode implies first converting the external
// chars already present.
if (_M_reading && this->egptr() == this->eback() && __remainder)
__rlen = 0;
// Allocate buffer if necessary and move unconverted
// bytes to front.
if (_M_ext_buf_size < __blen)
{
char* __buf = new char[__blen];
if (__remainder)
__builtin_memcpy(__buf, _M_ext_next, __remainder);
delete [] _M_ext_buf;
_M_ext_buf = __buf;
_M_ext_buf_size = __blen;
}
else if (__remainder)
__builtin_memmove(_M_ext_buf, _M_ext_next, __remainder);
_M_ext_next = _M_ext_buf;
_M_ext_end = _M_ext_buf + __remainder;
_M_state_last = _M_state_cur;
do
{
if (__rlen > 0)
{
// Sanity check!
// This may fail if the return value of
// codecvt::max_length() is bogus.
if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
{
__throw_ios_failure(__N("llstdio_filebuf::underflow "
"codecvt::max_length() "
"is not valid"));
}
//streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
streamsize __elen = fread(_M_ext_end, 1,
__rlen, _M_file.file());
if (__elen == 0)
__got_eof = true;
else if (__elen == -1)
break;
//_M_ext_end += __elen;
}
char_type* __iend = this->eback();
if (_M_ext_next < _M_ext_end)
{
__r = _M_codecvt->in(_M_state_cur, _M_ext_next,
_M_ext_end, _M_ext_next,
this->eback(),
this->eback() + __buflen, __iend);
}
if (__r == codecvt_base::noconv)
{
size_t __avail = _M_ext_end - _M_ext_buf;
__ilen = std::min(__avail, __buflen);
traits_type::copy(this->eback(),
reinterpret_cast<char_type*>
(_M_ext_buf), __ilen);
_M_ext_next = _M_ext_buf + __ilen;
}
else
__ilen = __iend - this->eback();
// _M_codecvt->in may return error while __ilen > 0: this is
// ok, and actually occurs in case of mixed encodings (e.g.,
// XML files).
if (__r == codecvt_base::error)
break;
__rlen = 1;
} while (__ilen == 0 && !__got_eof);
}
if (__ilen > 0)
{
_M_set_buffer(__ilen);
_M_reading = true;
__ret = traits_type::to_int_type(*this->gptr());
}
else if (__got_eof)
{
// If the actual end of file is reached, set 'uncommitted'
// mode, thus allowing an immediate write without an
// intervening seek.
_M_set_buffer(-1);
_M_reading = false;
// However, reaching it while looping on partial means that
// the file has got an incomplete character.
if (__r == codecvt_base::partial)
__throw_ios_failure(__N("llstdio_filebuf::underflow "
"incomplete character in file"));
}
else if (__r == codecvt_base::error)
__throw_ios_failure(__N("llstdio_filebuf::underflow "
"invalid byte sequence in file"));
else
__throw_ios_failure(__N("llstdio_filebuf::underflow "
"error reading the file"));
}
return __ret;
}
std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n)
{
// Clear out pback buffer before going on to the real deal...
streamsize __ret = 0;
if (_M_pback_init)
{
if (__n > 0 && this->gptr() == this->eback())
{
*__s++ = *this->gptr();
this->gbump(1);
__ret = 1;
--__n;
}
_M_destroy_pback();
}
// Optimization in the always_noconv() case, to be generalized in the
// future: when __n > __buflen we read directly instead of using the
// buffer repeatedly.
const bool __testin = _M_mode & ios_base::in;
const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
&& __testin && !_M_writing)
{
// First, copy the chars already present in the buffer.
const streamsize __avail = this->egptr() - this->gptr();
if (__avail != 0)
{
if (__avail == 1)
*__s = *this->gptr();
else
traits_type::copy(__s, this->gptr(), __avail);
__s += __avail;
this->gbump(__avail);
__ret += __avail;
__n -= __avail;
}
// Need to loop in case of short reads (relatively common
// with pipes).
streamsize __len;
for (;;)
{
//__len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n);
__len = fread(reinterpret_cast<void*>(__s), 1,
__n, _M_file.file());
if (__len == -1)
__throw_ios_failure(__N("llstdio_filebuf::xsgetn "
"error reading the file"));
if (__len == 0)
break;
__n -= __len;
__ret += __len;
if (__n == 0)
break;
__s += __len;
}
if (__n == 0)
{
_M_set_buffer(0);
_M_reading = true;
}
else if (__len == 0)
{
// If end of file is reached, set 'uncommitted'
// mode, thus allowing an immediate write without
// an intervening seek.
_M_set_buffer(-1);
_M_reading = false;
}
}
else
__ret += __streambuf_type::xsgetn(__s, __n);
return __ret;
}
std::streamsize llstdio_filebuf::xsputn(const char_type* __s, std::streamsize __n)
{
// Optimization in the always_noconv() case, to be generalized in the
// future: when __n is sufficiently large we write directly instead of
// using the buffer.
streamsize __ret = 0;
const bool __testout = _M_mode & ios_base::out;
if (__check_facet(_M_codecvt).always_noconv()
&& __testout && !_M_reading)
{
// Measurement would reveal the best choice.
const streamsize __chunk = 1ul << 10;
streamsize __bufavail = this->epptr() - this->pptr();
// Don't mistake 'uncommitted' mode buffered with unbuffered.
if (!_M_writing && _M_buf_size > 1)
__bufavail = _M_buf_size - 1;
const streamsize __limit = std::min(__chunk, __bufavail);
if (__n >= __limit)
{
const streamsize __buffill = this->pptr() - this->pbase();
const char* __buf = reinterpret_cast<const char*>(this->pbase());
//__ret = _M_file.xsputn_2(__buf, __buffill,
// reinterpret_cast<const char*>(__s), __n);
if (__buffill)
{
__ret = fwrite(__buf, 1, __buffill, _M_file.file());
}
if (__ret == __buffill)
{
__ret += fwrite(reinterpret_cast<const char*>(__s), 1,
__n, _M_file.file());
}
if (__ret == __buffill + __n)
{
_M_set_buffer(0);
_M_writing = true;
}
if (__ret > __buffill)
__ret -= __buffill;
else
__ret = 0;
}
else
__ret = __streambuf_type::xsputn(__s, __n);
}
else
__ret = __streambuf_type::xsputn(__s, __n);
return __ret;
}
int llstdio_filebuf::sync()
{
return (_M_file.sync() == 0 ? 0 : -1);
}
#endif
#if LL_WINDOWS
/************** input file stream ********************************/
llifstream::llifstream() : _M_filebuf(),
#if defined(LL_WINDOWS) || defined(_LIBCPP_VERSION)
std::istream(&_M_filebuf) {}
#else
std::istream()
llifstream::llifstream() :
_M_filebuf(),
std::istream(&_M_filebuf)
{
this->init(&_M_filebuf);
}
#endif
// explicit
llifstream::llifstream(const std::string& _Filename,
ios_base::openmode _Mode) : _M_filebuf(),
#if LL_WINDOWS
ios_base::openmode _Mode) :
_M_filebuf(),
std::istream(&_M_filebuf)
{
llutf16string wideName = utf8str_to_utf16str( _Filename );
......@@ -870,24 +443,11 @@ llifstream::llifstream(const std::string& _Filename,
_Myios::setstate(ios_base::failbit);
}
}
#elif _LIBCPP_VERSION
std::istream(&_M_filebuf)
{
this->init(&_M_filebuf);
this->open(_Filename.c_str(), _Mode | ios_base::in);
}
#else
std::istream()
{
this->init(&_M_filebuf);
this->open(_Filename.c_str(), _Mode | ios_base::in);
}
#endif
// explicit
llifstream::llifstream(const char* _Filename,
ios_base::openmode _Mode) : _M_filebuf(),
#if LL_WINDOWS
ios_base::openmode _Mode) :
_M_filebuf(),
std::istream(&_M_filebuf)
{
llutf16string wideName = utf8str_to_utf16str( _Filename );
......@@ -896,19 +456,6 @@ llifstream::llifstream(const char* _Filename,
_Myios::setstate(ios_base::failbit);
}
}
#elif _LIBCPP_VERSION
std::istream(&_M_filebuf)
{
this->init(&_M_filebuf);
this->open(_Filename, _Mode | ios_base::in);
}
#else
std::istream()
{
this->init(&_M_filebuf);
this->open(_Filename, _Mode | ios_base::in);
}
#endif
bool llifstream::is_open() const
{ // test if C stream has been opened
......@@ -917,8 +464,6 @@ bool llifstream::is_open() const
void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
{ // open a C stream with specified mode
#if LL_WINDOWS
llutf16string wideName = utf8str_to_utf16str( _Filename );
if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::in) == 0)
{
......@@ -928,27 +473,13 @@ void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
{
_Myios::clear();
}
#else
if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0)
{
this->setstate(ios_base::failbit);
}
else
{
this->clear();
}
#endif
}
void llifstream::close()
{ // close the C stream
if (_M_filebuf.close() == 0)
{
#if LL_WINDOWS
_Myios::setstate(ios_base::failbit);
#else
this->setstate(ios_base::failbit);
#endif
}
}
......@@ -956,20 +487,16 @@ void llifstream::close()
/************** output file stream ********************************/
llofstream::llofstream() : _M_filebuf(),
#if LL_WINDOWS
std::ostream(&_M_filebuf) {}
#else
std::ostream()
llofstream::llofstream() :
_M_filebuf(),
std::ostream(&_M_filebuf)
{
this->init(&_M_filebuf);
}
#endif
// explicit
llofstream::llofstream(const std::string& _Filename,
ios_base::openmode _Mode) : _M_filebuf(),
#if LL_WINDOWS
ios_base::openmode _Mode) :
_M_filebuf(),
std::ostream(&_M_filebuf)
{
llutf16string wideName = utf8str_to_utf16str( _Filename );
......@@ -978,18 +505,11 @@ llofstream::llofstream(const std::string& _Filename,
_Myios::setstate(ios_base::failbit);
}
}
#else
std::ostream()
{
this->init(&_M_filebuf);
this->open(_Filename.c_str(), _Mode | ios_base::out);
}
#endif
// explicit
llofstream::llofstream(const char* _Filename,
ios_base::openmode _Mode) : _M_filebuf(),
#if LL_WINDOWS
ios_base::openmode _Mode) :
_M_filebuf(),
std::ostream(&_M_filebuf)
{
llutf16string wideName = utf8str_to_utf16str( _Filename );
......@@ -998,13 +518,6 @@ llofstream::llofstream(const char* _Filename,
_Myios::setstate(ios_base::failbit);
}
}
#else
std::ostream()
{
this->init(&_M_filebuf);
this->open(_Filename, _Mode | ios_base::out);
}
#endif
bool llofstream::is_open() const
{ // test if C stream has been opened
......@@ -1013,7 +526,6 @@ bool llofstream::is_open() const
void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
{ // open a C stream with specified mode
#if LL_WINDOWS
llutf16string wideName = utf8str_to_utf16str( _Filename );
if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0)
{
......@@ -1023,54 +535,15 @@ void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
{
_Myios::clear();
}
#else
if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0)
{
this->setstate(ios_base::failbit);
}
else
{
this->clear();
}
#endif
}
void llofstream::close()
{ // close the C stream
if (_M_filebuf.close() == 0)
{
#if LL_WINDOWS
_Myios::setstate(ios_base::failbit);
#else
this->setstate(ios_base::failbit);
#endif
}
}
/************** helper functions ********************************/
std::streamsize llifstream_size(llifstream& ifstr)
{
if(!ifstr.is_open()) return 0;
std::streampos pos_old = ifstr.tellg();
ifstr.seekg(0, ios_base::beg);
std::streampos pos_beg = ifstr.tellg();
ifstr.seekg(0, ios_base::end);
std::streampos pos_end = ifstr.tellg();
ifstr.seekg(pos_old, ios_base::beg);
return pos_end - pos_beg;
}
std::streamsize llofstream_size(llofstream& ofstr)
{
if(!ofstr.is_open()) return 0;
std::streampos pos_old = ofstr.tellp();
ofstr.seekp(0, ios_base::beg);
std::streampos pos_beg = ofstr.tellp();
ofstr.seekp(0, ios_base::end);
std::streampos pos_end = ofstr.tellp();
ofstr.seekp(pos_old, ios_base::beg);
return pos_end - pos_beg;
}
#endif // LL_WINDOWS
......@@ -45,9 +45,6 @@ typedef FILE LLFILE;
typedef struct _stat llstat;
#else
typedef struct stat llstat;
#if !defined(LL_DARWIN) || defined(LL_GNUC) // Oof, this is pretty ugly
#include <ext/stdio_filebuf.h>
#endif // has_include
#endif // !LL_WINDOWS
#ifndef S_ISREG
......@@ -87,6 +84,11 @@ public:
static const char * tmpdir();
};
#if !defined(LL_WINDOWS)
typedef std::ifstream llifstream;
typedef std::ofstream llofstream;
#else
/**
* @brief Provides a layer of compatibility for C/POSIX.
*
......@@ -97,13 +99,7 @@ public:
*/
namespace
{
#if LL_WINDOWS
typedef std::filebuf _Myfb;
#elif _LIBCPP_VERSION
typedef std::basic_filebuf< char > _Myfb;
#else
typedef __gnu_cxx::stdio_filebuf< char > _Myfb;
#endif /* LL_WINDOWS */
}
class LL_COMMON_API llstdio_filebuf : public _Myfb
......@@ -114,36 +110,6 @@ public:
*/
llstdio_filebuf() : _Myfb() {}
virtual ~llstdio_filebuf() {}
// *TODO: Seek the underlying c stream for better cross-platform compatibility?
#if !defined(LL_WINDOWS) && !defined(_LIBCPP_VERSION)
protected:
/** underflow() and uflow() functions are called to get the next
* character from the real input source when the buffer is empty.
* Buffered input uses underflow()
*/
/*virtual*/ int_type underflow();
/* Convert internal byte sequence to external, char-based
* sequence via codecvt.
*/
bool _convert_to_external(char_type*, std::streamsize);
/** The overflow() function is called to transfer characters to the
* real output destination when the buffer is full. A call to
* overflow(c) outputs the contents of the buffer plus the
* character c.
* Consume some sequence of the characters in the pending sequence.
*/
/*virtual*/ int_type overflow(int_type __c = traits_type::eof());
/** sync() flushes the underlying @c FILE* stream.
*/
/*virtual*/ int sync();
std::streamsize xsgetn(char_type*, std::streamsize);
std::streamsize xsputn(const char_type*, std::streamsize);
#endif
};
......@@ -317,16 +283,6 @@ public:
private:
llstdio_filebuf _M_filebuf;
};
/**
* @breif filesize helpers.
*
* The file size helpers are not considered particularly efficient,
* and should only be used for config files and the like -- not in a
* loop.
*/
std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr);
std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr);
#endif
#endif // not LL_LLFILE_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment