From e9be710daf3d1135f732632d09007920e1d0ff81 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 15 Apr 2015 13:26:32 -0400
Subject: [PATCH] Strip down the Windows ll[io]fstream implementations to
 constructors and open() methods. The only remaining value added by
 ll[io]fstream over std::[io]stream is proper handling of non-ASCII pathnames,
 which can be done by deriving from std::[io]stream, converting pathname
 strings and passing them to the corresponding base-class methods. This is
 only necessary on Windows. On Posix, ll[io]fstream are already typedefs for
 std::[io]fstream. This change removes a significant volume of cruft from
 llfile.{h,cpp}.

---
 indra/llcommon/llfile.cpp | 537 +-------------------------------------
 indra/llcommon/llfile.h   | 212 +--------------
 2 files changed, 25 insertions(+), 724 deletions(-)

diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 295c97eac89..873a7bce25f 100755
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -421,551 +421,42 @@ LLFILE *	LLFile::_Fiopen(const std::string& filename,
 
 #endif /* LL_WINDOWS */
 
-/************** llstdio file buffer ********************************/
-
-
-#if !LL_WINDOWS
-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(),
-	std::istream(&_M_filebuf)
-{
-}
+llifstream::llifstream() {}
 
 // explicit
-llifstream::llifstream(const std::string& _Filename, 
-                       ios_base::openmode _Mode) :
-    _M_filebuf(),
-	std::istream(&_M_filebuf)
+llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode):
+    std::ifstream(utf8str_to_utf16str( _Filename ).c_str(),
+                  _Mode | ios_base::in)
 {
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
 }
 
-// explicit
-llifstream::llifstream(const char* _Filename, 
-                       ios_base::openmode _Mode) :
-    _M_filebuf(),
-	std::istream(&_M_filebuf)
+void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode)
 {
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
-}
-
-bool llifstream::is_open() const
-{	// test if C stream has been opened
-	return _M_filebuf.is_open();
-}
-
-void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
-{	// open a C stream with specified mode
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::in) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
-	else
-	{
-		_Myios::clear();
-	}
-}
-
-void llifstream::close()
-{	// close the C stream
-	if (_M_filebuf.close() == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
+    std::ifstream::open(utf8str_to_utf16str(_Filename).c_str(),
+                        _Mode | ios_base::in);
 }
 
 
 /************** output file stream ********************************/
 
 
-llofstream::llofstream() :
-    _M_filebuf(),
-	std::ostream(&_M_filebuf)
-{
-}
+llofstream::llofstream() {}
 
 // explicit
-llofstream::llofstream(const std::string& _Filename,
-                       ios_base::openmode _Mode) :
-    _M_filebuf(),
-	std::ostream(&_M_filebuf)
+llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode):
+    std::ofstream(utf8str_to_utf16str( _Filename ).c_str(),
+                  _Mode | ios_base::out)
 {
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
 }
 
-// explicit
-llofstream::llofstream(const char* _Filename,
-                       ios_base::openmode _Mode) :
-    _M_filebuf(),
-	std::ostream(&_M_filebuf)
+void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode)
 {
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
-}
-
-bool llofstream::is_open() const
-{	// test if C stream has been opened
-	return _M_filebuf.is_open();
-}
-
-void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
-{	// open a C stream with specified mode
-	llutf16string wideName = utf8str_to_utf16str( _Filename );
-	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
-	else
-	{
-		_Myios::clear();
-	}
-}
-
-void llofstream::close()
-{	// close the C stream
-	if (_M_filebuf.close() == 0)
-	{
-		_Myios::setstate(ios_base::failbit);
-	}
+    std::ofstream::open(utf8str_to_utf16str( _Filename ).c_str(),
+                        _Mode | ios_base::out);
 }
 
 /************** helper functions ********************************/
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 347c9867aa6..423f1f49653 100755
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -86,123 +86,16 @@ class LL_COMMON_API LLFile
 	static  const char * tmpdir();
 };
 
-/**
- *  @brief Provides a layer of compatibility for C/POSIX.
- *
- *  This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and 
- *  VC's basic_filebuf implementation.
- *  This file buffer provides extensions for working with standard C FILE*'s 
- *  and POSIX file descriptors for platforms that support this.
-*/
-namespace
-{
-#if LL_WINDOWS
-typedef std::filebuf						_Myfb;
-#else
-typedef  __gnu_cxx::stdio_filebuf< char >	_Myfb;
-typedef std::__c_file						_Filet;
-#endif /* LL_WINDOWS */
-}
-
-class LL_COMMON_API llstdio_filebuf : public _Myfb
-{
-public:
-	/**
-	 * deferred initialization / destruction
-	*/
-	llstdio_filebuf() : _Myfb() {}
-	virtual ~llstdio_filebuf() {} 
-
-	/**
-	 *  @param  f  An open @c FILE*.
-	 *  @param  mode  Same meaning as in a standard filebuf.
-	 *  @param  size  Optimal or preferred size of internal buffer, in chars.
-	 *                Defaults to system's @c BUFSIZ.
-	 *
-	 *  This constructor associates a file stream buffer with an open
-	 *  C @c FILE*.  The @c FILE* will not be automatically closed when the
-	 *  stdio_filebuf is closed/destroyed.
-	*/
-	llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode,
-		    //size_t __size = static_cast<size_t>(BUFSIZ)) :
-		    size_t __size = static_cast<size_t>(1)) :
-#if LL_WINDOWS
-		_Myfb(__f) {}
-#else
-		_Myfb(__f, __mode, __size) {}
-#endif
-
-	/**
-	 *  @brief  Opens an external file.
-	 *  @param  s  The name of the file.
-	 *  @param  mode  The open mode flags.
-	 *  @return  @c this on success, NULL on failure
-	 *
-	 *  If a file is already open, this function immediately fails.
-	 *  Otherwise it tries to open the file named @a s using the flags
-	 *  given in @a mode.
-	*/
-	//llstdio_filebuf* open(const char *_Filename,
-	//		std::ios_base::openmode _Mode);
-
-	/**
-	 *  @param  fd  An open file descriptor.
-	 *  @param  mode  Same meaning as in a standard filebuf.
-	 *  @param  size  Optimal or preferred size of internal buffer, in chars.
-	 *
-	 *  This constructor associates a file stream buffer with an open
-	 *  POSIX file descriptor. The file descriptor will be automatically
-	 *  closed when the stdio_filebuf is closed/destroyed.
-	*/
-#if !LL_WINDOWS
-	llstdio_filebuf(int __fd, std::ios_base::openmode __mode,
-		//size_t __size = static_cast<size_t>(BUFSIZ)) :
-		size_t __size = static_cast<size_t>(1)) :
-		_Myfb(__fd, __mode, __size) {}
-#endif
-
-// *TODO: Seek the underlying c stream for better cross-platform compatibility?
-#if !LL_WINDOWS
-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
-};
-
 #if LL_WINDOWS
 /**
  *  @brief  Controlling input for files.
  *
  *  This class supports reading from named files, using the inherited
- *  functions from std::basic_istream.  To control the associated
- *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
- *  which allows construction using a pre-exisintg file stream buffer. 
- *  We refer to this std::basic_filebuf (or derivative) as @c sb.
+ *  functions from std::ifstream. The only added value is that our constructor
+ *  Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't
+ *  true of Microsoft's std::ifstream.
  */
-class LL_COMMON_API llifstream	:	public	std::istream
+class LL_COMMON_API llifstream	:	public	std::ifstream
 {
 	// input stream associated with a C stream
   public:
@@ -225,32 +118,6 @@ class LL_COMMON_API llifstream	:	public	std::istream
      */
 	explicit llifstream(const std::string& _Filename,
                         ios_base::openmode _Mode = ios_base::in);
-	explicit llifstream(const char* _Filename,
-                        ios_base::openmode _Mode = ios_base::in);
-
-	/**
-	 *  @brief  The destructor does nothing.
-	 *
-	 *  The file is closed by the filebuf object, not the formatting
-	 *  stream.
-     */
-	virtual ~llifstream() {}
-
-	// Members:
-	/**
-	 *  @brief  Accessing the underlying buffer.
-	 *  @return  The current basic_filebuf buffer.
-	 *
-	 *  This hides both signatures of std::basic_ios::rdbuf().
-	*/
-	llstdio_filebuf* rdbuf() const
-	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
-
-	/**
-	 *  @brief  Wrapper to test for an open file.
-	 *  @return  @c rdbuf()->is_open()
-     */
-	bool is_open() const;
 
 	/**
 	 *  @brief  Opens an external file.
@@ -261,34 +128,19 @@ class LL_COMMON_API llifstream	:	public	std::istream
 	 *  fails, @c failbit is set in the stream's error state.
      */
 	void open(const std::string& _Filename,
-              ios_base::openmode _Mode = ios_base::in)
-	{ open(_Filename.c_str(), _Mode); }
-	void open(const char* _Filename,
               ios_base::openmode _Mode = ios_base::in);
-
-	/**
-	 *  @brief  Close the file.
-	 *
-	 *  Calls @c llstdio_filebuf::close().  If that function
-	 *  fails, @c failbit is set in the stream's error state.
-     */
-	void close();
-
-  private:
-	llstdio_filebuf _M_filebuf;
 };
 
 
 /**
  *  @brief  Controlling output for files.
  *
- *  This class supports writing to named files, using the inherited
- *  functions from std::basic_ostream.  To control the associated
- *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative)
- *  which allows construction using a pre-exisintg file stream buffer. 
- *  We refer to this std::basic_filebuf (or derivative) as @c sb.
+ *  This class supports writing to named files, using the inherited functions
+ *  from std::ofstream. The only added value is that our constructor Does The
+ *  Right Thing when passed a non-ASCII pathname. Sadly, that isn't true of
+ *  Microsoft's std::ofstream.
 */
-class LL_COMMON_API llofstream	:	public	std::ostream
+class LL_COMMON_API llofstream	:	public	std::ofstream
 {
   public:
 	// Constructors:
@@ -306,62 +158,20 @@ class LL_COMMON_API llofstream	:	public	std::ostream
 	 *  @param  Filename  String specifying the filename.
 	 *  @param  Mode  Open file in specified mode (see std::ios_base).
 	 *
-	 *  @c ios_base::out|ios_base::trunc is automatically included in
-	 *  @a mode.
+	 *  @c ios_base::out is automatically included in @a mode.
      */
 	explicit llofstream(const std::string& _Filename,
                         ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
-	explicit llofstream(const char* _Filename,
-                        ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
-
-	/**
-	 *  @brief  The destructor does nothing.
-	 *
-	 *  The file is closed by the filebuf object, not the formatting
-	 *  stream.
-	*/
-	virtual ~llofstream() {}
-
-	// Members:
-	/**
-	 *  @brief  Accessing the underlying buffer.
-	 *  @return  The current basic_filebuf buffer.
-	 *
-	 *  This hides both signatures of std::basic_ios::rdbuf().
-	*/
-	llstdio_filebuf* rdbuf() const
-	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); }
-
-	/**
-	 *  @brief  Wrapper to test for an open file.
-	 *  @return  @c rdbuf()->is_open()
-	*/
-	bool is_open() const;
 
 	/**
 	 *  @brief  Opens an external file.
 	 *  @param  Filename  The name of the file.
 	 *  @param  Node  The open mode flags.
 	 *
-	 *  Calls @c llstdio_filebuf::open(s,mode|out).  If that function
-	 *  fails, @c failbit is set in the stream's error state.
+	 *  @c ios_base::out is automatically included in @a mode.
      */
 	void open(const std::string& _Filename,
-              ios_base::openmode _Mode = ios_base::out|ios_base::trunc)
-	{ open(_Filename.c_str(), _Mode); }
-	void open(const char* _Filename,
               ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
-
-	/**
-	 *  @brief  Close the file.
-	 *
-	 *  Calls @c llstdio_filebuf::close().  If that function
-	 *  fails, @c failbit is set in the stream's error state.
-     */
-	void close();
-
-  private:
-	llstdio_filebuf _M_filebuf;
 };
 
 
-- 
GitLab