// fstream standard header #pragma once #ifndef _FSTREAM_ #define _FSTREAM_ #include #pragma pack(push,8) #pragma warning(push,3) #pragma warning(disable: 4127) _STD_BEGIN extern _CRTIMP2 _Filet *__cdecl _Fiopen(const char *, ios_base::openmode); // TEMPLATE FUNCTION _Fgetc template inline bool _Fgetc(_Elem& _Ch, _Filet *_File) { // get an element from a C stream return (fread(&_Ch, sizeof (_Elem), 1, _File) == 1); } template<> inline bool _Fgetc(char& _Byte, _Filet *_File) { // get a char element from a C stream int _Meta; if ((_Meta = fgetc(_File)) == EOF) return (false); else { // got one, convert to char _Byte = (char)_Meta; return (true); } } template<> inline bool _Fgetc(wchar_t& _Wchar, _Filet *_File) { // get a wchar_t element from a C stream wint_t _Meta; if ((_Meta = fgetwc(_File)) == WEOF) return (false); else { // got one, convert to wchar_t _Wchar = (wchar_t)_Meta; return (true); } } // TEMPLATE FUNCTION _Fputc template inline bool _Fputc(_Elem _Ch, _Filet *_File) { // put an element to a C stream return (fwrite(&_Ch, sizeof (_Elem), 1, _File) == 1); } template<> inline bool _Fputc(char _Byte, _Filet *_File) { // put a char element to a C stream return (fputc(_Byte, _File) != EOF); } template<> inline bool _Fputc(wchar_t _Wchar, _Filet *_File) { // put a wchar_t element to a C stream return (fputwc(_Wchar, _File) != WEOF); } // TEMPLATE FUNCTION _Ungetc template inline bool _Ungetc(const _Elem& _Ch, _Filet *_File) { // put back an arbitrary element to a C stream (always fail) return (false); } template<> inline bool _Ungetc(const char& _Byte, _Filet *_File) { // put back a char element to a C stream return (ungetc((unsigned char)_Byte, _File) != EOF); } template<> inline bool _Ungetc(const signed char& _Byte, _Filet *_File) { // put back a signed char element to a C stream return (ungetc((unsigned char)_Byte, _File) != EOF); } template<> inline bool _Ungetc(const unsigned char& _Byte, _Filet *_File) { // put back an unsigned char element to a C stream return (ungetc(_Byte, _File) != EOF); } template<> inline bool _Ungetc(const wchar_t& _Wchar, _Filet *_File) { // put back a wchar_t element to a C stream return (ungetwc(_Wchar, _File) != WEOF); } // TEMPLATE CLASS basic_filebuf template class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer associated with a C stream public: typedef basic_filebuf<_Elem, _Traits> _Myt; typedef basic_streambuf<_Elem, _Traits> _Mysb; typedef codecvt<_Elem, char, typename _Traits::state_type> _Cvt; virtual ~basic_filebuf() { // destroy the object if (_Closef) close(); _DELETE_CRT(_Mystr); } basic_filebuf(_Filet *_File = 0) : _Mysb(), _Mystr(0), _Loc() { // construct from pointer to C stream _Init(_File, _Newfl); } typedef typename _Traits::int_type int_type; typedef typename _Traits::pos_type pos_type; typedef typename _Traits::off_type off_type; basic_filebuf(_Uninitialized) : _Mysb(_Noinit), _Loc(_Noinit) { // construct uninitialized } enum _Initfl { // reasons for a call to _Init _Newfl, _Openfl, _Closefl}; bool is_open() const { // test if C stream has been opened return (_Myfile != 0); } _Myt *open(const char *_Filename, ios_base::openmode _Mode) { // open a C stream with specified mode _Filet *_File; if (_Myfile != 0 || (_File = _Fiopen(_Filename, _Mode)) == 0) return (0); // open failed _Init(_File, _Openfl); _Initcvt((_Cvt *)&_USE(_Mysb::getloc(), _Cvt)); return (this); // open succeeded } _Myt *open(const char *_Filename, ios_base::open_mode _Mode) { // open a C stream with specified mode (old style) return (open(_Filename, (ios_base::openmode)_Mode)); } _Myt *close() { // close the C stream if (_Myfile != 0 && _Endwrite() && fclose(_Myfile) == 0) { // close succeeded, tidy up _Init(0, _Closefl); return (this); } else return (0); } protected: virtual int_type overflow(int_type _Meta = _Traits::eof()) { // put an element to stream if (_Traits::eq_int_type(_Traits::eof(), _Meta)) return (_Traits::not_eof(_Meta)); // EOF, return success code else if (_Mysb::pptr() != 0 && _Mysb::pptr() < _Mysb::epptr()) { // room in buffer, store it *_Mysb::_Pninc() = _Traits::to_char_type(_Meta); return (_Meta); } else if (_Myfile == 0) return (_Traits::eof()); // no open C stream, fail else if (_Pcvt == 0) return (_Fputc(_Traits::to_char_type(_Meta), _Myfile) ? _Meta : _Traits::eof()); // no codecvt facet, put as is else { // put using codecvt facet const int _STRING_INC = 8; const _Elem _Ch = _Traits::to_char_type(_Meta); const _Elem *_Source; char *_Dest; _Mystr->erase(); string _Str(_STRING_INC, '\0'); for (; ; ) switch (_Pcvt->out(_State, &_Ch, &_Ch + 1, _Source, &*_Str.begin(), &*_Str.end(), _Dest)) { // test result of converting one element case codecvt_base::partial: case codecvt_base::ok: { // converted something, try to put it out size_t _Count = _Dest - &*_Str.begin(); if (0 < _Count && _Count != fwrite(&*_Str.begin(), 1, _Count, _Myfile)) return (_Traits::eof()); // write failed _Wrotesome = true; // write succeeded if (_Source != &_Ch) return (_Meta); // converted whole element if (_Count == 0) _Str.append(_STRING_INC, '\0'); // try some more break; } case codecvt_base::noconv: return (_Fputc(_Ch, _Myfile) ? _Meta : _Traits::eof()); // no conversion, put as is default: return (_Traits::eof()); // conversion failed } } } virtual int_type pbackfail(int_type _Meta = _Traits::eof()) { // put an element back to stream if (_Mysb::gptr() != 0 && _Mysb::eback() < _Mysb::gptr() && (_Traits::eq_int_type(_Traits::eof(), _Meta) || _Traits::eq_int_type(_Traits::to_int_type(_Mysb::gptr()[-1]), _Meta))) { // just back up position _Mysb::_Gndec(); return (_Traits::not_eof(_Meta)); } else if (_Myfile == 0 || _Traits::eq_int_type(_Traits::eof(), _Meta)) return (_Traits::eof()); // no open C stream or EOF, fail else if (_Pcvt == 0 && _Ungetc(_Traits::to_char_type(_Meta), _Myfile)) return (_Meta); // no facet and unget succeeded, return else { // putback to _Mychar _Mychar = _Traits::to_char_type(_Meta); _Mysb::setg(&_Mychar, &_Mychar, &_Mychar + 1); return (_Meta); } } virtual int_type underflow() { // get an element from stream, but don't point past it int_type _Meta; if (_Mysb::gptr() != 0 && _Mysb::gptr() < _Mysb::egptr()) return (_Traits::to_int_type(*_Mysb::gptr())); // return buffered else if (_Traits::eq_int_type(_Traits::eof(), _Meta = uflow())) return (_Meta); // uflow failed, return EOF else { // get a char, don't point past it pbackfail(_Meta); return (_Meta); } } virtual int_type uflow() { // get an element from stream, point past it if (_Mysb::gptr() != 0 && _Mysb::gptr() < _Mysb::egptr()) return (_Traits::to_int_type( *_Mysb::_Gninc())); // return buffered else if (_Myfile == 0) return (_Traits::eof()); // no open C stream, fail else if (_Pcvt == 0) { // no codecvt facet, just get it _Elem _Ch = 0; return (_Fgetc(_Ch, _Myfile) ? _Traits::to_int_type(_Ch) : _Traits::eof()); } else for (_State0 = _State, _Mystr->erase(); ; ) { // get using codecvt facet _Elem _Ch, *_Dest; const char *_Source; int _Meta = fgetc(_Myfile); if (_Meta == EOF) return (_Traits::eof()); // partial char? _Mystr->append(1, (char)_Meta); // append byte and convert _State = _State0; switch (_Pcvt->in(_State, &*_Mystr->begin(), &*_Mystr->end(), _Source, &_Ch, &_Ch + 1, _Dest)) { // test result of converting one element case codecvt_base::partial: break; // partial, not done yet case codecvt_base::noconv: if (_Mystr->size() < sizeof (_Elem)) break; // no conversion, but need more chars memcpy(&_Ch, &*_Mystr->begin(), sizeof (_Elem)); // copy raw bytes to element case codecvt_base::ok: // can fall through return (_Traits::to_int_type(_Ch)); // return result default: return (_Traits::eof()); // conversion failed } } } virtual pos_type seekoff(off_type _Off, ios_base::seekdir _Way, ios_base::openmode = (ios_base::openmode)(ios_base::in | ios_base::out)) { // change position by _Off fpos_t _Fileposition; if (_Mysb::gptr() != &_Mychar || _Mysb::egptr() <= _Mysb::gptr() || _Way != ios_base::cur) ; // don't have to worry about putback character else if (_Pcvt == 0) _Off -= (off_type)sizeof (_Elem); // back up over _Elem bytes else { // back up over converted bytes _Off -= (off_type)_Mystr->size(); _Mystr->erase(); _State = _State0; } if (_Myfile == 0 || !_Endwrite() || (_Off != 0 || _Way != ios_base::cur) && fseek(_Myfile, (long)_Off, _Way) != 0 || fgetpos(_Myfile, &_Fileposition) != 0) return (pos_type(_BADOFF)); // report failure if (_Mysb::gptr() == &_Mychar) _Mysb::setg(&_Mychar, &_Mychar, &_Mychar); // discard putback return (pos_type(_State, _Fileposition)); // return new position } virtual pos_type seekpos(pos_type _Pos, ios_base::openmode = (ios_base::openmode)(ios_base::in | ios_base::out)) { // change position to _Pos fpos_t _Fileposition = _Pos.seekpos(); off_type _Off = (off_type)_Pos - _FPOSOFF(_Fileposition); if (_Myfile == 0 || !_Endwrite() || fsetpos(_Myfile, &_Fileposition) != 0 || _Off != 0 && fseek(_Myfile, (long)_Off, SEEK_CUR) != 0 || fgetpos(_Myfile, &_Fileposition) != 0) return (pos_type(_BADOFF)); // report failure if (_Mystr != 0) _State = _Pos.state(), _Mystr->erase(); // restore state if (_Mysb::gptr() == &_Mychar) _Mysb::setg(&_Mychar, &_Mychar, &_Mychar); // discard putback return (pos_type(_State, _Fileposition)); // return new position } virtual _Mysb *setbuf(_Elem *_Buffer, streamsize _Count) { // offer _Buffer to C stream return (_Myfile == 0 || setvbuf(_Myfile, (char *)_Buffer, _Buffer == 0 && _Count == 0 ? _IONBF : _IOFBF, _Count * sizeof (_Elem)) != 0 ? 0 : this); } virtual int sync() { // synchronize C stream with external file return (_Myfile == 0 || _Traits::eq_int_type(_Traits::eof(), overflow()) || 0 <= fflush(_Myfile) ? 0 : -1); } virtual void imbue(const locale& _Loc) { // set locale to argument (capture nontrivial codecvt facet) _Initcvt((_Cvt *)&_USE(_Loc, _Cvt)); } void _Init(_Filet *_File, _Initfl _Which) { // initialize to C stream _File after {new, open, close} static typename _Traits::state_type _Stinit; // initial state _Closef = _Which == _Openfl; _Wrotesome = false; _Mysb::_Init(); // initialize stream buffer base object #ifndef _IORCNT #define _IORCNT _IOCNT /* read and write counts are the same */ #define _IOWCNT _IOCNT #endif if (_File != 0 && sizeof (_Elem) == 1) { // point inside C stream with [first, first + count) buffer _Elem **_Pb = (_Elem **)&_File->_IOBASE; _Elem **_Pn = (_Elem **)&_File->_IOPTR; int *_Nr = (int *)&_File->_IORCNT; int *_Nw = (int *)&_File->_IOWCNT; _Mysb::_Init(_Pb, _Pn, _Nr, _Pb, _Pn, _Nw); } _Myfile = _File; _State = _Stinit; _State0 = _Stinit; _Pcvt = 0; // pointer to codecvt facet } bool _Endwrite() { // put shift to initial conversion state, as needed if (_Pcvt == 0 || !_Wrotesome) return (true); else { // may have to put const int _STRING_INC = 8; char *_Dest; overflow(); string _Str(_STRING_INC, '\0'); for (; ; ) switch (_Pcvt->unshift(_State, &*_Str.begin(), &*_Str.end(), _Dest)) { // test result of homing conversion case codecvt_base::ok: _Wrotesome = false; // homed successfully case codecvt_base::partial: // can fall through { // put any generated bytes size_t _Count = _Dest - &*_Str.begin(); if (0 < _Count && _Count != fwrite(&*_Str.begin(), _Count, 1, _Myfile)) return (false); // write failed if (!_Wrotesome) return (true); _Str.append(_STRING_INC, '\0'); // try some more break; } case codecvt_base::noconv: return (true); // nothing to do default: return (false); // conversion failed } } } void _Initcvt(_Cvt *_Newpcvt) { // initialize codecvt pointer if (_Newpcvt->always_noconv()) _Pcvt = 0; // nothing to do else { // set up for nontrivial codecvt facet _Pcvt = _Newpcvt; _Loc = _ADDFAC(_Loc, _Pcvt); // to keep facet alive _Mysb::_Init(); // reset any buffering if (_Mystr == 0) _Mystr = _NEW_CRT _STRING_CRT; // buy conversion buffer } } private: _Cvt *_Pcvt; // pointer to codecvt facet (may be null) typename _Traits::state_type _State0; // rollback for bad conversion _Elem _Mychar; // putback character, when _Ungetc fails _STRING_CRT *_Mystr; // string to hold partial conversion byte sequences bool _Wrotesome; // true if homing sequence may be needed typename _Traits::state_type _State; // current conversion state bool _Closef; // true if C stream must be closed locale _Loc; // locale object to hold codecvt facet _Filet *_Myfile; // pointer to C stream }; #ifdef _DLL_CPPLIB template class _CRTIMP2 basic_filebuf >; template class _CRTIMP2 basic_filebuf >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_ifstream template class basic_ifstream : public basic_istream<_Elem, _Traits> { // input stream associated with a C stream public: typedef basic_ifstream<_Elem, _Traits> _Myt; typedef basic_filebuf<_Elem, _Traits> _Myfb; typedef basic_ios<_Elem, _Traits> _Myios; basic_ifstream() : basic_istream<_Elem, _Traits>(&_Filebuffer) { // construct unopened } explicit basic_ifstream(const char *_Filename, ios_base::openmode _Mode = ios_base::in) : basic_istream<_Elem, _Traits>(&_Filebuffer) { // construct with named file and specified mode if (_Filebuffer.open(_Filename, _Mode | ios_base::in) == 0) _Myios::setstate(ios_base::failbit); } virtual ~basic_ifstream() { // destroy the object } _Myfb *rdbuf() const { // return pointer to file buffer return ((_Myfb *)&_Filebuffer); } bool is_open() const { // test if C stream has been opened return (_Filebuffer.is_open()); } void open(const char *_Filename, ios_base::openmode _Mode = ios_base::in) { // open a C stream with specified mode if (_Filebuffer.open(_Filename, _Mode | ios_base::in) == 0) _Myios::setstate(ios_base::failbit); } void open(const char *_Filename, ios_base::open_mode _Mode) { // open named file with specified mode (old style) open(_Filename, (ios_base::openmode)_Mode); } void close() { // close the C stream if (_Filebuffer.close() == 0) _Myios::setstate(ios_base::failbit); } private: _Myfb _Filebuffer; // the file buffer }; #ifdef _DLL_CPPLIB template class _CRTIMP2 basic_ifstream >; template class _CRTIMP2 basic_ifstream >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_ofstream template class basic_ofstream : public basic_ostream<_Elem, _Traits> { // output stream associated with a C stream public: typedef basic_ofstream<_Elem, _Traits> _Myt; typedef basic_filebuf<_Elem, _Traits> _Myfb; typedef basic_ios<_Elem, _Traits> _Myios; basic_ofstream() : basic_ostream<_Elem, _Traits>(&_Filebuffer) { // construct unopened } explicit basic_ofstream(const char *_Filename, ios_base::openmode _Mode = ios_base::out) : basic_ostream<_Elem, _Traits>(&_Filebuffer) { // construct with named file and specified mode if (_Filebuffer.open(_Filename, _Mode | ios_base::out) == 0) _Myios::setstate(ios_base::failbit); } virtual ~basic_ofstream() { // destroy the object } _Myfb *rdbuf() const { // return pointer to file buffer return ((_Myfb *)&_Filebuffer); } bool is_open() const { // test if C stream has been opened return (_Filebuffer.is_open()); } void open(const char *_Filename, ios_base::openmode _Mode = ios_base::out) { // open a C stream with specified mode if (_Filebuffer.open(_Filename, _Mode | ios_base::out) == 0) _Myios::setstate(ios_base::failbit); } void open(const char *_Filename, ios_base::open_mode _Mode) { // open a C stream with specified mode (old style) open(_Filename, (ios_base::openmode)_Mode); } void close() { // close the C stream if (_Filebuffer.close() == 0) _Myios::setstate(ios_base::failbit); } private: _Myfb _Filebuffer; // the file buffer }; #ifdef _DLL_CPPLIB template class _CRTIMP2 basic_ofstream >; template class _CRTIMP2 basic_ofstream >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_fstream template class basic_fstream : public basic_iostream<_Elem, _Traits> { // input/output stream associated with a C stream public: typedef basic_ios<_Elem, _Traits> _Myios; typedef _Elem char_type; typedef _Traits traits_type; typedef typename _Traits::int_type int_type; typedef typename _Traits::pos_type pos_type; typedef typename _Traits::off_type off_type; basic_fstream() : basic_iostream<_Elem, _Traits>(&_Filebuffer) { // construct unopened } explicit basic_fstream(const char *_Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out) : basic_iostream<_Elem, _Traits>(&_Filebuffer) { // construct with named file and specified mode if (_Filebuffer.open(_Filename, _Mode) == 0) _Myios::setstate(ios_base::failbit); } virtual ~basic_fstream() { // destroy the object } basic_filebuf<_Elem, _Traits> *rdbuf() const { // return pointer to file buffer return ((basic_filebuf<_Elem, _Traits> *)&_Filebuffer); } bool is_open() const { // test if C stream has been opened return (_Filebuffer.is_open()); } void open(const char *_Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out) { // open a C stream with specified mode if (_Filebuffer.open(_Filename, _Mode) == 0) _Myios::setstate(ios_base::failbit); } void open(const char *_Filename, ios_base::open_mode _Mode) { // open a C stream with specified mode (old style) open(_Filename, (ios_base::openmode)_Mode); } void close() { // close the C stream if (_Filebuffer.close() == 0) _Myios::setstate(ios_base::failbit); } private: basic_filebuf<_Elem, _Traits> _Filebuffer; // the file buffer }; #ifdef _DLL_CPPLIB template class _CRTIMP2 basic_fstream >; template class _CRTIMP2 basic_fstream >; #endif // _DLL_CPPLIB _STD_END #pragma warning(default: 4127) #pragma warning(pop) #pragma pack(pop) #endif /* _FSTREAM_ */ /* * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. V3.10:0009 */