This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] New stream buffer for wcin


Hi,

This patch adds a new stream buffer class, wstdiobuf, for use with
wcin. This is a template so it can be easily extended to narrow
characters as well.

Benefits over stdio_filebuf include:
* Fully syncronized with stdin. It is possible to mix operations on
  wcin with wide character operations on stdin.
* sgetc() no longer corrupts the stream (libstdc++/9520).
* Much faster than both buffered and unbuffered stdio_filebuf (for
  3.4 at least).
* Handles multibyte character sets.

Testsuite files are attached, tested on linux on x86.

Petur

2003-02-23  Petur Runolfsson  <peturr02 at ru dot is>

	PR libstdc++/9520
	* include/Makefile.am (ext_headers):
	Add ext/stdiobuf.h.
	* include/ext/stdiobuf.h:  New file.
	* src/ext-inst.cc:  Add stdiobuf instantiation.
	* src/globals.cc:  Change type of buf_wcin to wstdiobuf.
	* src/ios.cc (ios_base::Init::_S_ios_create,
	ios_base::Init::_S_ios_destroy):  Likewise.

Index: include/Makefile.am
===================================================================
RCS file: /home/petur/cvsroot/gcc/libstdc++-v3/include/Makefile.am,v
retrieving revision 1.1.1.1
diff -c -3 -p -r1.1.1.1 Makefile.am
*** include/Makefile.am	15 Feb 2003 18:16:18 -0000	1.1.1.1
--- include/Makefile.am	21 Feb 2003 13:46:18 -0000
*************** ext_headers = \
*** 226,231 ****
--- 226,232 ----
  	${ext_srcdir}/rope \
  	${ext_srcdir}/ropeimpl.h \
  	${ext_srcdir}/slist \
+ 	${ext_srcdir}/stdiobuf.h \
  	${ext_srcdir}/stl_hash_fun.h \
  	${ext_srcdir}/stl_hashtable.h \
  	${ext_srcdir}/stl_rope.h
Index: include/ext/stdiobuf.h
===================================================================
RCS file: include/ext/stdiobuf.h
diff -N include/ext/stdiobuf.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- include/ext/stdiobuf.h	21 Feb 2003 16:07:06 -0000
***************
*** 0 ****
--- 1,131 ----
+ // Syncronized stream buffer for FILEs -*- C++ -*-
+ 
+ // Copyright (C) 2003 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.
+ 
+ /** @file ext/stdiobuf.h
+  *  This file is a GNU extension to the Standard C++ Library.
+  */
+ 
+ #ifndef _EXT_STDIOBUF_H
+ #define _EXT_STDIOBUF_H
+ 
+ #pragma GCC system_header
+ #include <streambuf>
+ #include <cwchar>
+ #include <cstdio>
+ 
+ namespace __gnu_cxx
+ {
+   // Simple wrapper for FILE* that encapsulates differences between
+   // char and wchar_t based functions.
+   template<typename _CharT>
+   class _Stdio_file;
+ 
+ #ifdef _GLIBCPP_USE_WCHAR_T
+   template<>
+   class _Stdio_file<wchar_t>
+   {
+   public:
+     explicit _Stdio_file(std::FILE* __file)
+     : _M_file(__file)
+     { }
+ 
+     std::wint_t sbumpc()
+     { return std::getwc(_M_file); }
+ 
+     std::wint_t sputbackc(std::wint_t __c)
+     { return std::ungetwc(__c, _M_file); }
+ 
+     std::size_t sgetn(wchar_t* __s, std::size_t __n)
+     {
+       std::size_t __ret = 0;
+       while (__ret < __n)
+ 	{
+ 	  std::wint_t __c = std::getwc(_M_file);
+ 	  if (__c == WEOF)
+ 	    break;
+ 	  __s[__ret] = __c;
+ 	  __ret++;
+ 	}
+       return __ret;
+     }
+ 
+   private:
+     std::FILE* _M_file;
+   };
+ #endif
+     
+   // Fully syncronized stream buffer for FILEs
+   // "Syncronized" means:
+   // * sbumpc() is equivalent to get[w]c(f)
+   // * sputbackc(c) is equivalent to unget[w]c(c, f)
+   // * sgetc() is equivalent to unget[w]c(get[w]c(f), f)
+   // There is no traits parameter since this requires that
+   // traits_type::eof() == [W]EOF and int_type == int|wint_t
+   template<typename _CharT>
+   class basic_stdiobuf : public std::basic_streambuf<_CharT>
+   {
+   public:
+     typedef _CharT char_type;
+     typedef typename std::basic_streambuf<_CharT>::traits_type traits_type;
+     typedef typename traits_type::int_type int_type;
+ 
+   private:
+     _Stdio_file<_CharT> _M_stdio_file;
+     
+   public:
+     explicit basic_stdiobuf(std::FILE* __file)
+     : _M_stdio_file(__file)
+     { }
+ 
+     virtual ~basic_stdiobuf()
+     { }
+ 
+   protected:
+     virtual int_type underflow()
+     {
+       int_type __c = _M_stdio_file.sbumpc();
+       return _M_stdio_file.sputbackc(__c);
+     }
+ 
+     virtual int_type uflow()
+     { return _M_stdio_file.sbumpc(); }
+ 
+     virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n)
+     { return _M_stdio_file.sgetn(__s, __n); }
+ 
+     virtual int_type pbackfail(int_type __c = traits_type::eof())
+     { return _M_stdio_file.sputbackc(__c); }
+   };
+ 
+ #ifdef _GLIBCPP_USE_WCHAR_T
+   typedef basic_stdiobuf<wchar_t> wstdiobuf;
+ #endif
+ } // namespace __gnu_cxx
+ 
+ #endif /* _EXT_STDIOBUF_H */
Index: src/ext-inst.cc
===================================================================
RCS file: /home/petur/cvsroot/gcc/libstdc++-v3/src/ext-inst.cc,v
retrieving revision 1.1.1.1
diff -c -3 -p -r1.1.1.1 ext-inst.cc
*** src/ext-inst.cc	15 Feb 2003 18:16:19 -0000	1.1.1.1
--- src/ext-inst.cc	21 Feb 2003 16:22:24 -0000
***************
*** 1,6 ****
  // Explicit instantiation file.
  
! // Copyright (C) 2001, 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
--- 1,6 ----
  // Explicit instantiation file.
  
! // Copyright (C) 2001, 2002, 2003 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
***************
*** 33,38 ****
--- 33,39 ----
  
  #include <ext/rope>
  #include <ext/stdio_filebuf.h>
+ #include <ext/stdiobuf.h>
  
  namespace __gnu_cxx
  {
*************** namespace __gnu_cxx
*** 58,62 ****
--- 59,65 ----
      _S_fetch(_Rope_RopeRep<wchar_t, std::allocator<wchar_t> >*, size_type);
  
    template class stdio_filebuf<wchar_t>;
+ 
+   template class basic_stdiobuf<wchar_t>;
  #endif
  } // namespace __gnu_cxx
Index: src/globals.cc
===================================================================
RCS file: /home/petur/cvsroot/gcc/libstdc++-v3/src/globals.cc,v
retrieving revision 1.1.1.1
diff -c -3 -p -r1.1.1.1 globals.cc
*** src/globals.cc	15 Feb 2003 18:16:19 -0000	1.1.1.1
--- src/globals.cc	21 Feb 2003 16:03:06 -0000
***************
*** 32,37 ****
--- 32,38 ----
  #include <ostream>
  #include <locale>
  #include <ext/stdio_filebuf.h>
+ #include <ext/stdiobuf.h>
  
  // On AIX, and perhaps other systems, library initialization order is
  // not guaranteed.  For example, the static initializers for the main
*************** namespace __gnu_cxx
*** 199,206 ****
    typedef char fake_wfilebuf[sizeof(stdio_filebuf<wchar_t>)]
    __attribute__ ((aligned(__alignof__(stdio_filebuf<wchar_t>))));
    fake_wfilebuf buf_wcout;
-   fake_wfilebuf buf_wcin;
    fake_wfilebuf buf_wcerr;
  #endif
  
    // Globals for once-only runtime initialization of mutex objects.  This
--- 200,210 ----
    typedef char fake_wfilebuf[sizeof(stdio_filebuf<wchar_t>)]
    __attribute__ ((aligned(__alignof__(stdio_filebuf<wchar_t>))));
    fake_wfilebuf buf_wcout;
    fake_wfilebuf buf_wcerr;
+ 
+   typedef char fake_wstdiobuf[sizeof(wstdiobuf)]
+   __attribute__ ((aligned(__alignof__(wstdiobuf))));
+   fake_wstdiobuf buf_wcin;
  #endif
  
    // Globals for once-only runtime initialization of mutex objects.  This
Index: src/ios.cc
===================================================================
RCS file: /home/petur/cvsroot/gcc/libstdc++-v3/src/ios.cc,v
retrieving revision 1.1.1.2
diff -c -3 -p -r1.1.1.2 ios.cc
*** src/ios.cc	22 Feb 2003 15:51:20 -0000	1.1.1.2
--- src/ios.cc	22 Feb 2003 15:55:12 -0000
***************
*** 38,43 ****
--- 38,44 ----
  #include <fstream>
  #include <bits/atomicity.h>
  #include <ext/stdio_filebuf.h>
+ #include <ext/stdiobuf.h>
  #ifdef _GLIBCPP_HAVE_UNISTD_H
  #include <unistd.h>
  #endif
*************** namespace __gnu_cxx
*** 51,57 ****
  
  #ifdef _GLIBCPP_USE_WCHAR_T
    extern stdio_filebuf<wchar_t> buf_wcout;
!   extern stdio_filebuf<wchar_t> buf_wcin;
    extern stdio_filebuf<wchar_t> buf_wcerr;
  #endif
  } // namespace __gnu_cxx
--- 52,58 ----
  
  #ifdef _GLIBCPP_USE_WCHAR_T
    extern stdio_filebuf<wchar_t> buf_wcout;
!   extern wstdiobuf buf_wcin;
    extern stdio_filebuf<wchar_t> buf_wcerr;
  #endif
  } // namespace __gnu_cxx
*************** namespace std 
*** 182,188 ****
      
  #ifdef _GLIBCPP_USE_WCHAR_T
      new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
!     new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
      new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
      new (&wcout) wostream(&buf_wcout);
      new (&wcin) wistream(&buf_wcin);
--- 183,189 ----
      
  #ifdef _GLIBCPP_USE_WCHAR_T
      new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
!     new (&buf_wcin) wstdiobuf(stdin);
      new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
      new (&wcout) wostream(&buf_wcout);
      new (&wcin) wistream(&buf_wcin);
*************** namespace std 
*** 205,211 ****
  
  #ifdef _GLIBCPP_USE_WCHAR_T
      buf_wcout.~stdio_filebuf();
!     buf_wcin.~stdio_filebuf();
      buf_wcerr.~stdio_filebuf();
  #endif
    }
--- 206,212 ----
  
  #ifdef _GLIBCPP_USE_WCHAR_T
      buf_wcout.~stdio_filebuf();
!     buf_wcin.~wstdiobuf();
      buf_wcerr.~stdio_filebuf();
  #endif
    }

Attachment: testsuite.tar.gz
Description: testsuite.tar.gz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]