From: Benjamin Kosnik Date: Tue, 30 Apr 2002 19:04:43 +0000 (+0000) Subject: stdio_filebuf.h: New file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5cdd50a59159258c25a53b0a2bcee9c8d6081812;p=gcc.git stdio_filebuf.h: New file. 2002-04-30 Benjamin Kosnik * include/ext/stdio_filebuf.h: New file. * include/ext/enc_filebuf.h: New file. * config/io/basic_file_stdio.h (__basic_file::sys_open): Add fd ctor. * config/io/basic_file_stdio.cc: Same. * include/bits/fstream.tcc (filebuf::_M_allocate_internal_buffer): Remove _M_unbuf hacks. (filebuf::_M_destroy_internal_buffer): Same. (filebuf::filebuf(cfile, openmode, int_type): Remove definition. (filebuf::fd): Remove. * include/std/std_fstream.h (filebuf::_M_unbuf): Remove. (filebuf::filebuf(__c_file*, openmode, int_type)): Remove. (filebuf::fd): Remove. * src/ios.cc (ios_base::_S_ios_create): Change to use specialized filebufs. (ios_base::_S_ios_destroy): Same. * src/misc-inst.cc (file_filebuf): Add instantiation. * include/Makefile.am (ext_headers): Add ext_filebuf.h, stdio_filebuf.h. * include/Makefile.in: Regenerate. From-SVN: r52961 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0b12903d26c..fd02dba763d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2002-04-30 Benjamin Kosnik + + * include/ext/stdio_filebuf.h: New file. + * include/ext/enc_filebuf.h: New file. + * config/io/basic_file_stdio.h (__basic_file::sys_open): Add fd ctor. + * config/io/basic_file_stdio.cc: Same. + * include/bits/fstream.tcc (filebuf::_M_allocate_internal_buffer): + Remove _M_unbuf hacks. + (filebuf::_M_destroy_internal_buffer): Same. + (filebuf::filebuf(cfile, openmode, int_type): Remove definition. + (filebuf::fd): Remove. + * include/std/std_fstream.h (filebuf::_M_unbuf): Remove. + (filebuf::filebuf(__c_file*, openmode, int_type)): Remove. + (filebuf::fd): Remove. + * src/ios.cc (ios_base::_S_ios_create): Change to use specialized + filebufs. + (ios_base::_S_ios_destroy): Same. + * src/misc-inst.cc (file_filebuf): Add instantiation. + * include/Makefile.am (ext_headers): Add ext_filebuf.h, + stdio_filebuf.h. * include/Makefile.in: Regenerate. + 2002-04-30 Benjamin Kosnik PR libstdc++/6511 diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc index 25c93e322dc..93ca6bc5de4 100644 --- a/libstdc++-v3/config/io/basic_file_stdio.cc +++ b/libstdc++-v3/config/io/basic_file_stdio.cc @@ -74,8 +74,31 @@ namespace std __basic_file* __ret = NULL; if (!this->is_open() && __file) { - _M_cfile = __file; - _M_cfile_created = false; + _M_cfile = __file; + _M_cfile_created = false; + __ret = this; + } + return __ret; + } + + __basic_file* + __basic_file::sys_open(int __fd, ios_base::openmode __mode, + bool __del) + { + __basic_file* __ret = NULL; + int __p_mode = 0; + int __rw_mode = 0; + char __c_mode[4]; + + _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode); + if (!this->is_open() && (_M_cfile = fdopen(__fd, __c_mode))) + { + // Iff __del is true, then close will fclose the fd. + _M_cfile_created = __del; + + if (__fd == 0) + setvbuf(_M_cfile, reinterpret_cast(NULL), _IONBF, 0); + __ret = this; } return __ret; @@ -84,7 +107,7 @@ namespace std int __basic_file::sys_getc() { return getc(_M_cfile); } - + int __basic_file::sys_ungetc(int __c) { return ungetc(__c, _M_cfile); } @@ -112,10 +135,12 @@ namespace std } bool - __basic_file::is_open() const { return _M_cfile != 0; } + __basic_file::is_open() const + { return _M_cfile != 0; } int - __basic_file::fd() { return fileno(_M_cfile) ; } + __basic_file::fd() + { return fileno(_M_cfile) ; } __basic_file* __basic_file::close() @@ -157,5 +182,6 @@ namespace std } int - __basic_file::sync() { return fflush(_M_cfile); } + __basic_file::sync() + { return fflush(_M_cfile); } } // namespace std diff --git a/libstdc++-v3/config/io/basic_file_stdio.h b/libstdc++-v3/config/io/basic_file_stdio.h index 137dfec9499..fe6edbb7058 100644 --- a/libstdc++-v3/config/io/basic_file_stdio.h +++ b/libstdc++-v3/config/io/basic_file_stdio.h @@ -70,7 +70,10 @@ namespace std open(const char* __name, ios_base::openmode __mode, int __prot = 0664); __basic_file* - sys_open(__c_file* __file, ios_base::openmode __mode); + sys_open(__c_file* __file, ios_base::openmode); + + __basic_file* + sys_open(int __fd, ios_base::openmode __mode, bool __del); int sys_getc(); diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index cfeb03e181f..38d1f7b90f8 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -143,6 +143,8 @@ ext_srcdir = ${glibcpp_srcdir}/include/ext ext_builddir = ./ext ext_headers = \ ${ext_srcdir}/algorithm \ + ${ext_srcdir}/enc_filebuf.h \ + ${ext_srcdir}/stdio_filebuf.h \ ${ext_srcdir}/functional \ ${ext_srcdir}/hash_map \ ${ext_srcdir}/hash_set \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index c24c6e26fbe..4a2cecd2100 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -272,6 +272,8 @@ ext_srcdir = ${glibcpp_srcdir}/include/ext ext_builddir = ./ext ext_headers = \ ${ext_srcdir}/algorithm \ + ${ext_srcdir}/enc_filebuf.h \ + ${ext_srcdir}/stdio_filebuf.h \ ${ext_srcdir}/functional \ ${ext_srcdir}/hash_map \ ${ext_srcdir}/hash_set \ diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index 910209a1bf1..40b9f32532d 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -48,19 +48,14 @@ namespace std { _M_buf_size = _M_buf_size_opt; - if (_M_buf_size != 1) + // Allocate internal buffer. + try { _M_buf = new char_type[_M_buf_size]; } + catch(...) { - // Allocate internal buffer. - try { _M_buf = new char_type[_M_buf_size]; } - catch(...) - { - delete [] _M_buf; - __throw_exception_again; - } - _M_buf_allocated = true; + delete [] _M_buf; + __throw_exception_again; } - else - _M_buf = _M_unbuf; + _M_buf_allocated = true; } } @@ -78,52 +73,15 @@ namespace std this->setg(NULL, NULL, NULL); this->setp(NULL, NULL); } - else - { - if (_M_buf == _M_unbuf) - { - _M_buf = NULL; - this->setg(NULL, NULL, NULL); - this->setp(NULL, NULL); - } - } } template basic_filebuf<_CharT, _Traits>:: - basic_filebuf() - : __streambuf_type(), _M_file(&_M_lock), _M_state_cur(__state_type()), - _M_state_beg(__state_type()), _M_buf_allocated(false), - _M_last_overflowed(false) + basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), + _M_state_cur(__state_type()), _M_state_beg(__state_type()), + _M_buf_allocated(false), _M_last_overflowed(false) { _M_buf_unified = true; } - template - basic_filebuf<_CharT, _Traits>:: - basic_filebuf(__c_file* __f, ios_base::openmode __mode, int_type __s) - : __streambuf_type(), _M_file(&_M_lock), _M_state_cur(__state_type()), - _M_state_beg(__state_type()), _M_buf_allocated(false), - _M_last_overflowed(false) - { - _M_buf_unified = true; - _M_file.sys_open(__f, __mode); - if (this->is_open()) - { - _M_mode = __mode; - if (__s) - { - _M_buf_size_opt = __s; - _M_allocate_internal_buffer(); - _M_set_indeterminate(); - } - } - } - - template - int - basic_filebuf<_CharT, _Traits>:: - fd() - { return _M_file.fd(); } - template typename basic_filebuf<_CharT, _Traits>::__filebuf_type* basic_filebuf<_CharT, _Traits>:: diff --git a/libstdc++-v3/include/ext/enc_filebuf.h b/libstdc++-v3/include/ext/enc_filebuf.h new file mode 100644 index 00000000000..e1152bd26f9 --- /dev/null +++ b/libstdc++-v3/include/ext/enc_filebuf.h @@ -0,0 +1,61 @@ +// __enc_traits layer for filebuf -*- C++ -*- + +// Copyright (C) 2002 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include +#include + +namespace __gnu_cxx +{ + // Custom traits type with __enc_traits for state type, all other bits + // equivalent to the required char_traits instantiations. + template + struct enc_char_traits: public std::char_traits<_CharT> + { + typedef std::__enc_traits state_type; + }; + + template + class enc_filebuf + : public std::basic_filebuf<_CharT, enc_char_traits<_CharT> > + { + public: + typedef typename enc_char_traits<_CharT>::state_type state_type; + + enc_filebuf(state_type& __state) + : std::basic_filebuf<_CharT, enc_char_traits<_CharT> >() + { + // Set state type to something useful. + // Something more than copyconstructible is needed here, so + // require copyconstructible + assignment operator. + __glibcpp_class_requires(state_type, _SGIAssignableConcept); + _M_state_cur = __state; + _M_state_cur._M_init(); + }; + }; +} // namespace __gnu_cxx diff --git a/libstdc++-v3/include/ext/stdio_filebuf.h b/libstdc++-v3/include/ext/stdio_filebuf.h new file mode 100644 index 00000000000..1b0d5ae72fc --- /dev/null +++ b/libstdc++-v3/include/ext/stdio_filebuf.h @@ -0,0 +1,113 @@ +// File descriptor layer for filebuf -*- C++ -*- + +// Copyright (C) 2002 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#include + +namespace __gnu_cxx +{ + template > + class stdio_filebuf : public std::basic_filebuf<_CharT, _Traits> + { + public: + // Types: + 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; + + protected: + // Stack-based buffer for unbuffered input. + char_type _M_unbuf[4]; + + public: + stdio_filebuf(int __fd, std::ios_base::openmode __mode, bool __del, + int_type __size); + + stdio_filebuf(std::__c_file* __f, std::ios_base::openmode __mode, + int_type __size = static_cast(BUFSIZ)); + + virtual + ~stdio_filebuf(); + + int + fd() + { return _M_file.fd(); } + }; + + template + stdio_filebuf<_CharT, _Traits>::~stdio_filebuf() + { } + + template + stdio_filebuf<_CharT, _Traits>:: + stdio_filebuf(int __fd, std::ios_base::openmode __mode, bool __del, + int_type __size) + { + _M_file.sys_open(__fd, __mode, __del); + if (this->is_open()) + { + _M_mode = __mode; + _M_buf_size_opt = __size; + + if (__size > 0 && __size < 4) + { + _M_buf = _M_unbuf; + _M_buf_size = __size; + } + else + _M_allocate_internal_buffer(); + + _M_set_indeterminate(); + } + } + + template + stdio_filebuf<_CharT, _Traits>:: + stdio_filebuf(std::__c_file* __f, std::ios_base::openmode __mode, + int_type __size) + { + _M_file.sys_open(__f, __mode); + if (this->is_open()) + { + _M_mode = __mode; + _M_buf_size_opt = __size; + + if (__size > 0 && __size < 4) + { + _M_buf = _M_unbuf; + _M_buf_size = __size; + } + else + _M_allocate_internal_buffer(); + + _M_set_indeterminate(); + } + } +} // namespace __gnu_cxx diff --git a/libstdc++-v3/include/std/std_fstream.h b/libstdc++-v3/include/std/std_fstream.h index ce3a48e90bc..fb95965a06a 100644 --- a/libstdc++-v3/include/std/std_fstream.h +++ b/libstdc++-v3/include/std/std_fstream.h @@ -84,12 +84,9 @@ namespace std __state_type _M_state_cur; __state_type _M_state_beg; - // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer.. + // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer. bool _M_buf_allocated; - // Stack-based buffer for unbuffered input. - char_type _M_unbuf[4]; - // XXX Needed? bool _M_last_overflowed; @@ -101,14 +98,6 @@ namespace std // Constructors/destructor: basic_filebuf(); - // Non-standard ctor: - basic_filebuf(__c_file* __f, ios_base::openmode __mode, - int_type __s = static_cast(BUFSIZ)); - - // Non-standard member: - int - fd(); - virtual ~basic_filebuf() { diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc index cf9087f9e08..36d193fb406 100644 --- a/libstdc++-v3/src/globals.cc +++ b/libstdc++-v3/src/globals.cc @@ -31,6 +31,7 @@ #include #include #include +#include // On AIX, and perhaps other systems, library initialization order is // not guaranteed. For example, the static initializers for the main @@ -176,8 +177,8 @@ namespace std fake_ostream cerr; fake_ostream clog; - typedef char fake_filebuf[sizeof(filebuf)] - __attribute__ ((aligned(__alignof__(filebuf)))); + typedef char fake_filebuf[sizeof(__gnu_cxx::stdio_filebuf)] + __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf)))); fake_filebuf buf_cout; fake_filebuf buf_cin; fake_filebuf buf_cerr; @@ -192,8 +193,8 @@ namespace std fake_wostream wcerr; fake_wostream wclog; - typedef char fake_wfilebuf[sizeof(wfilebuf)] - __attribute__ ((aligned(__alignof__(wfilebuf)))); + typedef char fake_wfilebuf[sizeof(__gnu_cxx::stdio_filebuf)] + __attribute__ ((aligned(__alignof__(__gnu_cxx::stdio_filebuf)))); fake_wfilebuf buf_wcout; fake_wfilebuf buf_wcin; fake_wfilebuf buf_wcerr; diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index 8e834fd65b0..c1167f8c15c 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -36,8 +36,8 @@ #include #include #include - #include +#include namespace std { @@ -46,18 +46,21 @@ namespace std extern ostream cout; extern ostream cerr; extern ostream clog; - extern filebuf buf_cout; - extern filebuf buf_cin; - extern filebuf buf_cerr; + + using __gnu_cxx::stdio_filebuf; + extern stdio_filebuf buf_cout; + extern stdio_filebuf buf_cin; + extern stdio_filebuf buf_cerr; #ifdef _GLIBCPP_USE_WCHAR_T extern wistream wcin; extern wostream wcout; extern wostream wcerr; extern wostream wclog; - extern wfilebuf buf_wcout; - extern wfilebuf buf_wcin; - extern wfilebuf buf_wcerr; + + extern stdio_filebuf buf_wcout; + extern stdio_filebuf buf_wcin; + extern stdio_filebuf buf_wcerr; #endif // Definitions for static const data members of __ios_flags. @@ -147,15 +150,15 @@ namespace std void ios_base::Init::_S_ios_create(bool __sync) { - int __out_bufsize = __sync ? 0 : static_cast(BUFSIZ); - int __in_bufsize = __sync ? 1 : static_cast(BUFSIZ); + int __out_size = __sync ? 0 : static_cast(BUFSIZ); + int __in_size = __sync ? 1 : static_cast(BUFSIZ); // NB: The file globals.cc creates the four standard files // with NULL buffers. At this point, we swap out the dummy NULL // [io]stream objects and buffers with the real deal. - new (&buf_cout) filebuf(stdout, ios_base::out, __out_bufsize); - new (&buf_cin) filebuf(stdin, ios_base::in, __in_bufsize); - new (&buf_cerr) filebuf(stderr, ios_base::out, __out_bufsize); + new (&buf_cout) stdio_filebuf(stdout, ios_base::out, __out_size); + new (&buf_cin) stdio_filebuf(stdin, ios_base::in, __in_size); + new (&buf_cerr) stdio_filebuf(stderr, ios_base::out, __out_size); new (&cout) ostream(&buf_cout); new (&cin) istream(&buf_cin); new (&cerr) ostream(&buf_cerr); @@ -164,9 +167,9 @@ namespace std cerr.flags(ios_base::unitbuf); #ifdef _GLIBCPP_USE_WCHAR_T - new (&buf_wcout) wfilebuf(stdout, ios_base::out, __out_bufsize); - new (&buf_wcin) wfilebuf(stdin, ios_base::in, __in_bufsize); - new (&buf_wcerr) wfilebuf(stderr, ios_base::out, __out_bufsize); + new (&buf_wcout) stdio_filebuf(stdout, ios_base::out, __out_size); + new (&buf_wcin) stdio_filebuf(stdin, ios_base::in, __in_size); + new (&buf_wcerr) stdio_filebuf(stderr, ios_base::out, __out_size); new (&wcout) wostream(&buf_wcout); new (&wcin) wistream(&buf_wcin); new (&wcerr) wostream(&buf_wcerr); @@ -182,13 +185,14 @@ namespace std // Explicitly call dtors to free any memory that is dynamically // allocated by filebuf ctor or member functions, but don't // deallocate all memory by calling operator delete. - buf_cout.~filebuf(); - buf_cin.~filebuf(); - buf_cerr.~filebuf(); + buf_cout.~stdio_filebuf(); + buf_cin.~stdio_filebuf(); + buf_cerr.~stdio_filebuf(); + #ifdef _GLIBCPP_USE_WCHAR_T - buf_wcout.~wfilebuf(); - buf_wcin.~wfilebuf(); - buf_wcerr.~wfilebuf(); + buf_wcout.~stdio_filebuf(); + buf_wcin.~stdio_filebuf(); + buf_wcerr.~stdio_filebuf(); #endif } diff --git a/libstdc++-v3/src/misc-inst.cc b/libstdc++-v3/src/misc-inst.cc index a276a732ed3..07a4b1a1aa2 100644 --- a/libstdc++-v3/src/misc-inst.cc +++ b/libstdc++-v3/src/misc-inst.cc @@ -44,6 +44,7 @@ #include #include #include +#include // NB: Unnecessary if the .h headers already include these. #ifndef _GLIBCPP_FULLY_COMPLIANT_HEADERS @@ -264,4 +265,10 @@ namespace std __copy_streambufs(basic_ios&, basic_streambuf*, basic_streambuf*); #endif + + using __gnu_cxx::stdio_filebuf; + template class stdio_filebuf; +#ifdef _GLIBCPP_USE_WCHAR_T + template class stdio_filebuf; +#endif } //std diff --git a/libstdc++-v3/testsuite/27_io/filebuf_members.cc b/libstdc++-v3/testsuite/27_io/filebuf_members.cc index f8153c42e39..9f48229f67a 100644 --- a/libstdc++-v3/testsuite/27_io/filebuf_members.cc +++ b/libstdc++-v3/testsuite/27_io/filebuf_members.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include const char name_01[] = "filebuf_members-1.tst"; @@ -89,7 +90,7 @@ void test_02() FILE* f2 = fopen(name_01, "r"); VERIFY( f2 != NULL ); { - std::filebuf fb(f2, std::ios_base::in, 512); + __gnu_cxx::stdio_filebuf fb(f2, std::ios_base::in, 512); } close_num = fclose(f2); VERIFY( close_num == 0 ); @@ -115,7 +116,7 @@ void test_03() VERIFY( first_fd != -1 ); FILE* first_file = ::fdopen(first_fd, "r"); VERIFY( first_file != NULL ); - std::filebuf fb (first_file, std::ios_base::in); + __gnu_cxx::stdio_filebuf fb(first_file, std::ios_base::in); int second_fd = fb.fd();