]> gcc.gnu.org Git - gcc.git/commitdiff
re PR libstdc++/12790 (basic_filebuf doesn't handle stateful encodings)
authorPetur Runolfsson <peturr02@ru.is>
Tue, 4 Nov 2003 05:27:41 +0000 (05:27 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Tue, 4 Nov 2003 05:27:41 +0000 (05:27 +0000)
2003-11-03  Petur Runolfsson  <peturr02@ru.is>

PR libstdc++/12790
* include/bits/fstream.tcc: Delete _M_last_overflowed.
(basic_filebuf::basic_filebuf): Initialize _M_state_last.
(basic_filebuf::open, basic_filebuf::close): Assign
_M_state_beg to _M_state_cur and _M_state_last.
(basic_filebuf::close): Call _M_terminate_output to handle
unshift and flushing.
(basic_filebuf::underflow): Assign _M_state_last, throw
exception instead of calling abort when codecvt::max_length()
is bad.
(basic_filebuf::seekoff): Use _M_state_last when calling
codecvt::length(), pass correct state to _M_seek.
(basic_filebuf::seekpos): Pass __pos.state() to _M_seek.
(basic_filebuf::_M_seek): Add __state_type parameter,
set _M_state_cur correctly, store the resulting state in
the return value and use _M_terminate_output to handle
flushing and unshift.
(basic_filebuf::_M_terminate_output): Flush contents of
output buffer, if any, then call codecvt::unshift as
needed and output the result.
(basic_filebuf::sync): Move here, don't modify _M_writing
or _M_reading.

* include/std/std_fstream.h
(basic_filebuf::_M_state_last): Declare it.
(basic_filebuf::_M_last_overflowed): Delete.
(basic_filebuf::_M_seek): Add __state_type parameter.
(basic_filebuf::sync): Declare only.
(basic_filebuf::_M_output_unshift): Delete.
(basic_filebuf::_M_terminate_output): Declare it.

* testsuite/testsuite_character.h:
Define character class and state class plus char_traits and
codecvt specializations for same for testing support for
stateful encodings.

* testsuite/27_io/basic_filebuf/close/12790-1.cc,
* testsuite/27_io/basic_filebuf/close/char/12790-1.cc,
* testsuite/27_io/basic_filebuf/close/char/12790-2.cc,
* testsuite/27_io/basic_filebuf/close/char/12790-3.cc,
* testsuite/27_io/basic_filebuf/close/char/12790-4.cc,
* testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc,
* testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc,
* testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc,
* testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc,
* testsuite/27_io/basic_filebuf/open/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekoff/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekoff/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekoff/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekoff/12790-4.cc,
* testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc,
* testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc,
* testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc,
* testsuite/27_io/basic_filebuf/seekpos/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekpos/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekpos/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc,
* testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc,
* testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc,
* testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc,
* testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc,
* testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc,
* testsuite/27_io/basic_filebuf/sync/char/1.cc,
* testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc:
New tests.

* testsuite/27_io/basic_filebuf/3.cc,
* testsuite/27_io/basic_filebuf/seekoff/10132-2.cc,
* testsuite/27_io/basic_filebuf/seekpos/10132-3.cc,
* testsuite/27_io/basic_fstream/3.cc,
* testsuite/27_io/basic_ifstream/3.cc,
* testsuite/27_io/basic_ofstream/3.cc:
Use streamoff as off_type and fpos<state_type> as pos_type.

* testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc,
* testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc:
Check that sync does *not* set _M_writing to false.

From-SVN: r73245

49 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/std/std_fstream.h
libstdc++-v3/testsuite/27_io/basic_filebuf/3.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/10132-2.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/10132-3.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_fstream/3.cc
libstdc++-v3/testsuite/27_io/basic_ifstream/3.cc
libstdc++-v3/testsuite/27_io/basic_ofstream/3.cc
libstdc++-v3/testsuite/testsuite_character.h [new file with mode: 0644]

index d8242e94701ebc340649b9786569b1c9df376dad..9124c8d0ed32e2fac0ac0a8f6926297a4d0608fa 100644 (file)
@@ -1,3 +1,92 @@
+2003-11-03  Petur Runolfsson  <peturr02@ru.is>
+
+       PR libstdc++/12790
+       * include/bits/fstream.tcc: Delete _M_last_overflowed.
+       (basic_filebuf::basic_filebuf): Initialize _M_state_last.
+       (basic_filebuf::open, basic_filebuf::close): Assign
+       _M_state_beg to _M_state_cur and _M_state_last.
+       (basic_filebuf::close): Call _M_terminate_output to handle
+       unshift and flushing.
+       (basic_filebuf::underflow): Assign _M_state_last, throw
+       exception instead of calling abort when codecvt::max_length()
+       is bad.
+       (basic_filebuf::seekoff): Use _M_state_last when calling
+       codecvt::length(), pass correct state to _M_seek.
+       (basic_filebuf::seekpos): Pass __pos.state() to _M_seek.
+       (basic_filebuf::_M_seek): Add __state_type parameter,
+       set _M_state_cur correctly, store the resulting state in
+       the return value and use _M_terminate_output to handle
+       flushing and unshift.
+       (basic_filebuf::_M_terminate_output): Flush contents of
+       output buffer, if any, then call codecvt::unshift as
+       needed and output the result.
+       (basic_filebuf::sync): Move here, don't modify _M_writing
+       or _M_reading.
+       
+       * include/std/std_fstream.h
+       (basic_filebuf::_M_state_last): Declare it.
+       (basic_filebuf::_M_last_overflowed): Delete.
+       (basic_filebuf::_M_seek): Add __state_type parameter.
+       (basic_filebuf::sync): Declare only.
+       (basic_filebuf::_M_output_unshift): Delete.
+       (basic_filebuf::_M_terminate_output): Declare it.
+       
+       * testsuite/testsuite_character.h:
+       Define character class and state class plus char_traits and
+       codecvt specializations for same for testing support for
+       stateful encodings.
+       
+       * testsuite/27_io/basic_filebuf/close/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/close/char/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/close/char/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/close/char/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/close/char/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/open/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc,
+       * testsuite/27_io/basic_filebuf/sync/char/1.cc,
+       * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc:
+       New tests.
+
+       * testsuite/27_io/basic_filebuf/3.cc,
+       * testsuite/27_io/basic_filebuf/seekoff/10132-2.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/10132-3.cc,
+       * testsuite/27_io/basic_fstream/3.cc,
+       * testsuite/27_io/basic_ifstream/3.cc,
+       * testsuite/27_io/basic_ofstream/3.cc:
+       Use streamoff as off_type and fpos<state_type> as pos_type.
+
+       * testsuite/27_io/basic_filebuf/seekpos/char/1-io.cc,
+       * testsuite/27_io/basic_filebuf/seekpos/char/1-out.cc:
+       Check that sync does *not* set _M_writing to false.
+
 2003-11-03  Anthony Green  <green@redhat.com>
 
        * libmath/stubs.c (sqrtf, sqrtl): Reorder so they appear before
index 29fe0e8d6c6ffe6120c07b1671b977c90e80a7d2..56497412fce56575d0da2ef172788b295397781d 100644 (file)
@@ -74,12 +74,12 @@ namespace std
   template<typename _CharT, typename _Traits>
     basic_filebuf<_CharT, _Traits>::
     basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
-    _M_mode(ios_base::openmode(0)), _M_state_cur(__state_type()),
-    _M_state_beg(__state_type()), _M_buf(NULL), _M_buf_size(BUFSIZ),
+    _M_mode(ios_base::openmode(0)), _M_state_beg(), _M_state_cur(),
+    _M_state_last(), _M_buf(NULL), _M_buf_size(BUFSIZ),
     _M_buf_allocated(false), _M_reading(false), _M_writing(false),
-    _M_last_overflowed(false), _M_pback_cur_save(0), _M_pback_end_save(0),
-    _M_pback_init(false), _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0),
-    _M_ext_next(0), _M_ext_end(0)
+    _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false),
+    _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0),
+    _M_ext_end(0)
     { 
       if (has_facet<__codecvt_type>(this->_M_buf_locale))
        _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
@@ -104,9 +104,12 @@ namespace std
              _M_writing = false;
              _M_set_buffer(-1);
 
+             // Reset to initial state.
+             _M_state_last = _M_state_cur = _M_state_beg;
+
              // 27.8.1.3,4
              if ((__mode & ios_base::ate) 
-                 && this->seekoff(0, ios_base::end, __mode)
+                 && this->seekoff(0, ios_base::end, __mode) 
                  == pos_type(off_type(-1)))
                this->close();
              else
@@ -127,18 +130,8 @@ namespace std
          bool __testfail = false;
          try
            {
-             if (this->pbase() < this->pptr()
-                 && traits_type::eq_int_type(this->overflow(),
-                                             traits_type::eof()))
+             if (!_M_terminate_output())
                __testfail = true;
-#if 0
-             // XXX not done
-             if (_M_last_overflowed)
-               {
-                 _M_output_unshift();
-                 this->overflow();
-               }
-#endif
            }
          catch(...)
            {
@@ -152,6 +145,7 @@ namespace std
          _M_reading = false;
          _M_writing = false;
          _M_set_buffer(-1);
+         _M_state_last = _M_state_cur = _M_state_beg;
          
          if (!_M_file.close())
            __testfail = true;
@@ -159,7 +153,6 @@ namespace std
          if (!__testfail)
            __ret = this;
        }
-      _M_last_overflowed = false;
       return __ret;
     }
 
@@ -180,7 +173,6 @@ namespace std
            __ret += _M_file.showmanyc() / _M_codecvt->max_length();
        }
 
-      _M_last_overflowed = false;      
       return __ret;
     }
   
@@ -252,6 +244,7 @@ namespace std
 
              _M_ext_next = _M_ext_buf;
              _M_ext_end = _M_ext_buf + __remainder;
+             _M_state_last = _M_state_cur;
 
              do
                {
@@ -261,7 +254,10 @@ namespace std
                      // 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)
-                       std::abort();
+                       {
+                         __throw_ios_failure("codecvt::max_length() "
+                                             "is not valid");
+                       }
                      streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
                      if (__elen == 0)
                        __got_eof = true;
@@ -280,8 +276,7 @@ namespace std
                      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);
+                                       reinterpret_cast<char_type*>(_M_ext_buf), __ilen);
                      _M_ext_next = _M_ext_buf + __ilen;
                    }
                  else 
@@ -309,7 +304,6 @@ namespace std
              _M_reading = false;
            }
        }
-      _M_last_overflowed = false;      
       return __ret;
     }
 
@@ -364,7 +358,6 @@ namespace std
              __ret = __i;
            }
        }
-      _M_last_overflowed = false;      
       return __ret;
     }
 
@@ -423,7 +416,6 @@ namespace std
                }
            }
        }
-      _M_last_overflowed = true;       
       return __ret;
     }
   
@@ -521,7 +513,8 @@ namespace std
              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);
+                                      reinterpret_cast<const char*>(__s), 
+                                      __n);
              if (__ret == __buffill + __n)
                {
                  _M_set_buffer(0);
@@ -569,7 +562,6 @@ namespace std
          _M_writing = false;
          _M_set_buffer(-1);
        }
-      _M_last_overflowed = false;      
       return this; 
     }
   
@@ -589,12 +581,18 @@ namespace std
       if (__width < 0)
        __width = 0;
 
-      const bool __testfail = __off != 0 && __width <= 0;      
+      const bool __testfail = __off != 0 && __width <= 0;
       if (this->is_open() && !__testfail) 
        {
          // Ditch any pback buffers to avoid confusion.
          _M_destroy_pback();
 
+         // Correct state at destination. Note that this is the correct
+         // state for the current position during output, because
+         // codecvt::unshift() returns the state to the initial state.
+         // This is also the correct state at the end of the file because
+         // an unshift sequence should have been written at the end.
+         __state_type __state = _M_state_beg;
          off_type __computed_off = __off * __width;
          if (_M_reading && __way == ios_base::cur)
            {
@@ -603,16 +601,20 @@ namespace std
              else
                {
                  // Calculate offset from _M_ext_buf that corresponds
-                 // to gptr().
+                 // to gptr(). Note: uses _M_state_last, which
+                 // corresponds to eback().
                  const int __gptr_off =
-                   _M_codecvt->length(_M_state_cur, _M_ext_buf, _M_ext_next,
+                   _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next,
                                       this->gptr() - this->eback());
                  __computed_off += _M_ext_buf + __gptr_off - _M_ext_end;
+                 
+                 // _M_state_last is modified by codecvt::length() so
+                 // it now corresponds to gptr().
+                 __state = _M_state_last;
                }
            }
-         __ret = _M_seek(__computed_off, __way);
+         __ret = _M_seek(__computed_off, __way, __state);
        }
-      _M_last_overflowed = false;      
       return __ret;
     }
 
@@ -632,41 +634,115 @@ namespace std
          // Ditch any pback buffers to avoid confusion.
          _M_destroy_pback();
 
-         __ret = _M_seek(off_type(__pos), ios_base::beg);
+         __ret = _M_seek(off_type(__pos), ios_base::beg, __pos.state());
        }
-      _M_last_overflowed = false;      
       return __ret;
     }
 
   template<typename _CharT, typename _Traits>
     typename basic_filebuf<_CharT, _Traits>::pos_type
     basic_filebuf<_CharT, _Traits>::
-    _M_seek(off_type __off, ios_base::seekdir __way)
+    _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state)
+    {
+      pos_type __ret = pos_type(off_type(-1));
+      if (_M_terminate_output())
+       {         
+         // Returns pos_type(off_type(-1)) in case of failure.
+         __ret = pos_type(_M_file.seekoff(__off, __way));
+         
+         _M_reading = false;
+         _M_writing = false;
+         _M_ext_next = _M_ext_end = _M_ext_buf;
+         _M_set_buffer(-1);
+         _M_state_cur = __state;
+         __ret.state(_M_state_cur);
+       }
+      return __ret;
+    }
+
+  template<typename _CharT, typename _Traits>
+    bool
+    basic_filebuf<_CharT, _Traits>::
+    _M_terminate_output()
     {
+      bool __testvalid = true;
+
+      // Part one: update the output sequence.
       if (this->pbase() < this->pptr())
        {
-         // Part one: update the output sequence.
-         this->sync();
+         const int_type __tmp = this->overflow();
+         if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+           __testvalid = false;
+       }
              
-         // Part two: output unshift sequence.
-         _M_output_unshift();
+      // Part two: output unshift sequence.
+      if (_M_writing && !__check_facet(_M_codecvt).always_noconv() 
+         && __testvalid)
+       {
+         // Note: this value is arbitrary, since there is no way to
+         // get the length of the unshift sequence from codecvt,
+         // without calling unshift.
+         const size_t __blen = 128;
+
+         char __buf[__blen];
+         codecvt_base::result __r;
+         streamsize __ilen = 0;
+
+         do
+           {
+             char* __next;
+             __r = _M_codecvt->unshift(_M_state_cur, __buf,
+                                       __buf + __blen, __next);
+             if (__r == codecvt_base::error)
+               __testvalid = false;
+             else if (__r == codecvt_base::ok ||
+                      __r == codecvt_base::partial)
+               {
+                 __ilen = __next - __buf;
+                 
+                 if (__ilen > 0)
+                   {
+                     const streamsize __elen = _M_file.xsputn(__buf, __ilen);
+                     if (__elen != __ilen)
+                       __testvalid = false;
+                   }
+               }
+           }
+         while (__r == codecvt_base::partial && __ilen > 0 && __testvalid);
+
+         if (__testvalid)
+           {
+             // This second call to overflow() is required by the standard,
+             // but it's not clear why it's needed, since the output buffer
+             // should be empty by this point (it should have been emptied
+             // in the first call to overflow()).
+             const int_type __tmp = this->overflow();
+             if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+               __testvalid = false;
+           }
        }
-         
-      // Returns pos_type(off_type(-1)) in case of failure.
-      pos_type __ret (_M_file.seekoff(__off, __way));
-         
-      _M_reading = false;
-      _M_writing = false;
-      _M_ext_next = _M_ext_end = _M_ext_buf;
-      _M_set_buffer(-1);
-      return __ret;
+      return __testvalid;
     }
 
   template<typename _CharT, typename _Traits>
-    void 
+    int
     basic_filebuf<_CharT, _Traits>::
-    _M_output_unshift()
-    { }
+    sync()
+    {
+      int __ret = 0;
+
+      // Make sure that the internal buffer resyncs its idea of
+      // the file position with the external file.
+      // NB: _M_file.sync() will be called within.
+      if (this->pbase() < this->pptr())
+       {
+         const int_type __tmp = this->overflow();
+         if (traits_type::eq_int_type(__tmp, traits_type::eof()))
+           __ret = -1;
+       }
+      
+      return __ret;
+    }
 
   template<typename _CharT, typename _Traits>
     void
@@ -703,7 +779,6 @@ namespace std
              // encoding, or that the filebuf be closed. Opinions may differ.
            }
        }
-      _M_last_overflowed = false;      
     }
 
   // Inhibit implicit instantiations for required instantiations,
index dd19cccfcfd537666ad958040b4d8bfa95bfa728..9bfa6774e239e23064df173feceb120b1ddc84fc 100644 (file)
@@ -60,6 +60,11 @@ namespace std
    *  sequences.  Many of its sematics are described in terms of similar
    *  behavior in the Standard C Library's @c FILE streams.
   */
+  // Requirements on traits_type, specific to this class:
+  // traits_type::pos_type must be fpos<traits_type::state_type>
+  // traits_type::off_type must be streamoff
+  // traits_type::state_type must be Assignable and DefaultConstructable,
+  // and traits_type::state_type() must be the initial state for codecvt.
   template<typename _CharT, typename _Traits>
     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
     {
@@ -111,15 +116,33 @@ namespace std
       */
       ios_base::openmode       _M_mode;
 
-      // Current and beginning state type for codecvt.
+      // Beginning state type for codecvt.
       /**
        *  @if maint
        *  @doctodo
        *  @endif
       */
-      __state_type             _M_state_cur;
       __state_type             _M_state_beg;
 
+      // During output, the state that corresponds to pptr(),
+      // during input, the state that corresponds to egptr() and
+      // _M_ext_next.
+      /**
+       *  @if maint
+       *  @doctodo
+       *  @endif
+      */
+      __state_type             _M_state_cur;
+
+      // Not used for output. During input, the state that corresponds
+      // to eback() and _M_ext_buf.
+      /**
+       *  @if maint
+       *  @doctodo
+       *  @endif
+      */
+      __state_type             _M_state_last;
+
       /**
        *  @if maint
        *  Pointer to the beginning of internally-allocated space.
@@ -156,9 +179,6 @@ namespace std
       bool                      _M_reading;
       bool                      _M_writing;
 
-      // XXX Needed?
-      bool                     _M_last_overflowed;
-
       //@{
       /**
        *  @if maint
@@ -386,33 +406,11 @@ namespace std
        *  @endif
       */
       pos_type
-      _M_seek(off_type __off, ios_base::seekdir __way);
+      _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state);
 
       // [documentation is inherited]
       virtual int
-      sync()
-      {
-       int __ret = 0;
-
-       // Make sure that the internal buffer resyncs its idea of
-       // the file position with the external file.
-       // NB: _M_file.sync() will be called within.
-       if (this->pbase() < this->pptr())
-         {
-           const int_type __tmp = this->overflow();
-           if (traits_type::eq_int_type(__tmp, traits_type::eof()))
-             __ret = -1;
-           else
-             {
-               _M_set_buffer(-1);
-               _M_reading = false;
-               _M_writing = false;
-             }
-         }
-
-       _M_last_overflowed = false;
-       return __ret;
-      }
+      sync();
 
       // [documentation is inherited]
       virtual void
@@ -443,13 +441,14 @@ namespace std
       virtual streamsize
       xsputn(const char_type* __s, streamsize __n);
 
+      // Flushes output buffer, then writes unshift sequence.
       /**
        *  @if maint
        *  @doctodo
        *  @endif
       */
-      void
-      _M_output_unshift();
+      bool
+      _M_terminate_output();
 
       /**
        *  @if maint 
index 6cb9e6e8b3f43d18b86ba1346c04b09074e3cbc0..6523af7bb10f87db43903ef9fc6bf62f7daa3747 100644 (file)
@@ -56,9 +56,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/12790-1.cc
new file mode 100644 (file)
index 0000000..a6c2700
--- /dev/null
@@ -0,0 +1,78 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out | ios_base::trunc);
+  fb.sputc(character::from_char('b'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+
+  // Check that close() writes unshift sequence
+  fb.close();
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::ate);
+
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+
+  fb.close();
+
+  fb.open(name, ios_base::in);
+
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-1.cc
new file mode 100644 (file)
index 0000000..cc68efb
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-2.cc
new file mode 100644 (file)
index 0000000..2e16682
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+  fb.in_avail(); // showmanyc() should have no effect on close().
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-3.cc
new file mode 100644 (file)
index 0000000..0e3629a
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return codecvt_base::error;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should fail if codecvt::unshift() fails
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  filebuf* ret = fb.close();
+  VERIFY( cvt->unshift_called );
+  VERIFY( ret == NULL );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/12790-4.cc
new file mode 100644 (file)
index 0000000..c0efd7f
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-1.cc
new file mode 100644 (file)
index 0000000..c0588a3
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-2.cc
new file mode 100644 (file)
index 0000000..edabea9
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+  fb.in_avail(); // showmanyc() should have no effect on close().
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-3.cc
new file mode 100644 (file)
index 0000000..8c7e2c2
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return codecvt_base::error;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should fail if codecvt::unshift() fails
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  wfilebuf* ret = fb.close();
+  VERIFY( cvt->unshift_called );
+  VERIFY( ret == NULL );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/wchar_t/12790-4.cc
new file mode 100644 (file)
index 0000000..f6acb49
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::close() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_close_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.close();
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/open/12790-1.cc
new file mode 100644 (file)
index 0000000..d37972b
--- /dev/null
@@ -0,0 +1,60 @@
+// 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.
+
+// 27.8.1.3 filebuf member functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_open_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(character::from_char('b'));
+  fb.close();
+
+  // Check that reopened basic_filebuf begins in the initial state.
+  fb.open(name, ios_base::in);
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('b')) );
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
index 0d218a60aa6d21f9fe195d9aa8d018a4e632c298..14f0870517f4228077883e8fa74206fa3c8e079f 100644 (file)
@@ -54,9 +54,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-1.cc
new file mode 100644 (file)
index 0000000..79a6251
--- /dev/null
@@ -0,0 +1,82 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.close();
+
+  fb.open(name, ios_base::in);
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+
+  // Check that seekoff calls codecvt::length with the correct state.
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+  VERIFY( pos != traits_type::pos_type(traits_type::off_type(-1)) );
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+  fb.sbumpc();
+  fb.sbumpc();
+  c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+  c = fb.sbumpc();
+  VERIFY( c == traits_type::eof() );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-2.cc
new file mode 100644 (file)
index 0000000..5966e17
--- /dev/null
@@ -0,0 +1,85 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char('a'));
+  fb.close();
+
+  fb.open(name, ios_base::in);
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+
+  // Check that seekoff resets the state when seeking to beginning.
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::beg);
+  VERIFY( pos != traits_type::pos_type(traits_type::off_type(-1)) );
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char(0xff)) );
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+  fb.sbumpc();
+  c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+  c = fb.sbumpc();
+  VERIFY( c == traits_type::eof() );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-3.cc
new file mode 100644 (file)
index 0000000..42a1795
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out | ios_base::trunc);
+  fb.sputc(character::from_char('b'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0xfc));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+
+  fb.close();
+  fb.open(name, ios_base::in);
+
+  fb.sbumpc();
+  fb.sbumpc();
+
+  // Check that seekoff returns the correct state
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+  fb.sbumpc();
+
+  fb.pubseekpos(pos);
+
+  c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/12790-4.cc
new file mode 100644 (file)
index 0000000..d246657
--- /dev/null
@@ -0,0 +1,71 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+  fb.sputc(character::from_char('b'));
+  fb.sputc(character::from_char(0xff));
+
+  // Check that seekoff sets the current state during output
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+
+  fb.pubseekoff(0, ios_base::beg);
+  fb.sbumpc();
+  fb.sbumpc();
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-1.cc
new file mode 100644 (file)
index 0000000..a634023
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-2.cc
new file mode 100644 (file)
index 0000000..006078a
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-3.cc
new file mode 100644 (file)
index 0000000..b56a5e9
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/12790-4.cc
new file mode 100644 (file)
index 0000000..69752b2
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc('a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-1.cc
new file mode 100644 (file)
index 0000000..bf70ecd
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-2.cc
new file mode 100644 (file)
index 0000000..748ae3a
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-3.cc
new file mode 100644 (file)
index 0000000..6db1648
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/12790-4.cc
new file mode 100644 (file)
index 0000000..b6af7fb
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekoff() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  fb.sputc(L'a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekoff(0, ios_base::cur);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/3.cc
new file mode 100644 (file)
index 0000000..3088e5f
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test03()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekoff_3";
+
+  wfilebuf fb;
+
+  fb.open(name, ios_base::out);
+  fb.sputc(0xf001);
+
+  // seekoff should flush the output sequence, which will fail
+  // if the output buffer contains illegal characters.
+  streampos ret = fb.pubseekoff(0, ios_base::cur);
+  VERIFY( ret == streampos(streamoff(-1)) );
+}
+
+int main()
+{
+  test03();
+  return 0;
+}
index fdb817dce2afb62a5b69f744d79b26b9c59c8653..85b80a1329e87e8043cb10b22d67ea378cba79f1 100644 (file)
@@ -54,9 +54,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-1.cc
new file mode 100644 (file)
index 0000000..3201da8
--- /dev/null
@@ -0,0 +1,66 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+
+  // Check that seekpos restores the state correctly
+  fb.pubseekpos(pos);
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-2.cc
new file mode 100644 (file)
index 0000000..b5198e5
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out | ios_base::trunc);
+  fb.sputc(character::from_char('b'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0xfc));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+
+  fb.close();
+  fb.open(name, ios_base::in);
+
+  fb.sbumpc();
+  fb.sbumpc();
+  traits_type::pos_type pos1 = fb.pubseekoff(0, ios_base::cur);
+  fb.sbumpc();
+  fb.sbumpc();
+
+  // Check that seekpos returns the correct state
+  traits_type::pos_type pos2 = fb.pubseekpos(pos1);
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+  fb.sbumpc();
+
+  fb.pubseekpos(pos2);
+  c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/12790-3.cc
new file mode 100644 (file)
index 0000000..1d0535c
--- /dev/null
@@ -0,0 +1,79 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+#include <testsuite_character.h>
+
+// libstdc++/12790
+void test01()
+{
+  using namespace std;
+  using __gnu_test::character;
+  typedef basic_filebuf<character>::traits_type traits_type;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  locale loc(locale::classic(),
+            new codecvt<traits_type::char_type, char,
+            traits_type::state_type>);
+
+  basic_filebuf<character> fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+  fb.sputc(character::from_char('b'));
+  fb.sputc(character::from_char(0xff));
+  fb.sputc(character::from_char('c'));
+  fb.sputc(character::from_char(0xff));
+
+  fb.pubseekoff(0, ios_base::beg);
+  fb.sbumpc();
+  fb.sbumpc();
+  traits_type::pos_type pos = fb.pubseekoff(0, ios_base::cur);
+  fb.sbumpc();
+  fb.sbumpc();
+
+  // Check that seekoff sets the current state for output
+  fb.pubseekpos(pos);
+
+  fb.sputc(character::from_char('a'));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+  fb.sputc(character::from_char(0));
+  
+  fb.pubseekpos(pos);
+
+  traits_type::int_type c = fb.sbumpc();
+  VERIFY( c != traits_type::eof() );
+  VERIFY( traits_type::eq(traits_type::to_char_type(c),
+                         character::from_char('a')) );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
index eea3be8108fbfc5b2f7e465f234ff604fd10f98a..588a1b27ccb7133e8e1fe827be8a712a5c408b99 100644 (file)
@@ -88,7 +88,7 @@ void test05()
     VERIFY( off_1 > off_2 );
     fb.sputn("\nof the wonderful things he does!!\nok", 37);
     fb.pubsync();
-    VERIFY( !fb.write_position() );
+    VERIFY( fb.write_position() );
     VERIFY( !fb.read_position() );
     fb.close();
     VERIFY( !fb.is_open() );
index cc29a27204d889b380b2f2b6f7bdd1428ee8f191..c684786fe00f6ee29a625b3c230e61f86d518447 100644 (file)
@@ -90,7 +90,7 @@ void test05()
     VERIFY( off_1 > off_2 );
     fb.sputn("\nof the wonderful things he does!!\nok", 37);
     fb.pubsync();
-    VERIFY( !fb.write_position() );
+    VERIFY( fb.write_position() );
     VERIFY( !fb.read_position() );
     fb.close();
     VERIFY( !fb.is_open() );
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-1.cc
new file mode 100644 (file)
index 0000000..2c31c8a
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-2.cc
new file mode 100644 (file)
index 0000000..42b1023
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc('a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-3.cc
new file mode 100644 (file)
index 0000000..e168c94
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/char/12790-4.cc
new file mode 100644 (file)
index 0000000..0bf84cb
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<char, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  filebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc('a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/1.cc
new file mode 100644 (file)
index 0000000..c543212
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_1";
+
+  wfilebuf fb;
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc(0xf001);
+
+  streampos ret = fb.pubseekpos(pos);
+  VERIFY( ret == streampos(streamoff(-1)) );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
new file mode 100644 (file)
index 0000000..718589e
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc(L'a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-2.cc
new file mode 100644 (file)
index 0000000..220a48c
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubsetbuf(0, 0);
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc(L'a');
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-3.cc
new file mode 100644 (file)
index 0000000..eaa3cb6
--- /dev/null
@@ -0,0 +1,80 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift(),
+// but only if writing
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( !cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-4.cc
new file mode 100644 (file)
index 0000000..70d36c8
--- /dev/null
@@ -0,0 +1,81 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <locale>
+#include <fstream>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+public:
+  mutable bool unshift_called;
+
+  Cvt()
+  : unshift_called(false)
+  { }
+
+protected:
+  bool
+  do_always_noconv() const throw()
+  { return false; }
+
+  int
+  do_encoding() const throw()
+  { return -1; }
+
+  std::codecvt_base::result
+  do_unshift(std::mbstate_t&, char* to, char*, char*& to_next) const
+  {
+    unshift_called = true;
+    to_next = to;
+    return std::codecvt_base::ok;
+  }
+};
+
+// libstdc++/12790
+// basic_filebuf::seekpos() should call codecvt::unshift()
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_seekpos_12790";
+
+  Cvt* cvt = new Cvt;
+  locale loc(locale::classic(), cvt);
+
+  wfilebuf fb;
+  fb.pubimbue(loc);
+
+  fb.open(name, ios_base::out);
+  streampos pos = fb.pubseekoff(0, ios_base::beg);
+  fb.sputc(L'a');
+  fb.pubsync(); // Does not call unshift()
+
+  VERIFY( !cvt->unshift_called );
+  fb.pubseekpos(pos);
+  VERIFY( cvt->unshift_called );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc
new file mode 100644 (file)
index 0000000..202cc38
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_sync_1";
+
+  filebuf fb;
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+  fb.sputn("abc", 3);
+
+  fb.pubseekoff(0, ios_base::beg);
+  fb.sputc('1');
+
+  // Sync can't be used to switch from write mode to read mode.
+  fb.pubsync();
+
+  filebuf::int_type c = fb.sbumpc();
+  VERIFY( c == filebuf::traits_type::eof() );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc
new file mode 100644 (file)
index 0000000..8ff00ce
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+// 27.8.1.4 Overridden virtual functions
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  bool test __attribute__((unused)) = true;
+  const char* name = "tmp_sync_1";
+
+  wfilebuf fb;
+
+  fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
+  fb.sputn(L"abc", 3);
+
+  fb.pubseekoff(0, ios_base::beg);
+  fb.sputc(L'1');
+
+  // Sync can't be used to switch from write mode to read mode.
+  fb.pubsync();
+
+  wfilebuf::int_type c = fb.sbumpc();
+  VERIFY( c == wfilebuf::traits_type::eof() );
+
+  fb.close();
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
index c71e0e86b94c4034a0f151c6176ec09d81d7e825..484c611cdda36a2beb750d6b80a3ef29fdb14156 100644 (file)
@@ -58,9 +58,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
index 7ffd7b3b9af3d86f5cffc04a58b0c95c0ca67f1c..6649be318ecfc016eea77b579140d2f3348326a8 100644 (file)
@@ -58,9 +58,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
index 3cba2191ced6fa2ee2b18ef86b71baaa2ab197ed..8f264d4a37a4b82a46381c494a550b81bcedacd0 100644 (file)
@@ -58,9 +58,9 @@ struct gnu_char_traits
 {
   typedef gnu_char_type        char_type;
   typedef long                 int_type;
-  typedef long                 pos_type;
-  typedef unsigned long        off_type;
+  typedef std::streamoff       off_type;
   typedef long                 state_type;
+  typedef std::fpos<state_type>        pos_type;
   
   static void 
   assign(char_type& __c1, const char_type& __c2) { }
diff --git a/libstdc++-v3/testsuite/testsuite_character.h b/libstdc++-v3/testsuite/testsuite_character.h
new file mode 100644 (file)
index 0000000..67c35c2
--- /dev/null
@@ -0,0 +1,415 @@
+// -*- C++ -*-
+// Testing character type and state type with char_traits and codecvt
+// specializations for the C++ library testsuite.
+//
+// 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.
+
+#ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
+#define _GLIBCXX_TESTSUITE_CHARACTER_H
+
+#include <string> // for char_traits
+#include <locale> // for codecvt
+#include <climits>
+
+namespace __gnu_test
+{  
+  // Character type
+  struct character
+  {
+    unsigned char val;
+
+    static character from_char(char c)
+    {
+      character ret;
+      ret.val = c;
+      return ret;
+    }
+  };
+
+  // State type.
+  struct conversion_state
+  {
+    unsigned int state;
+  };
+}; // namespace __gnu_test
+
+namespace std
+{
+  // char_traits specialization. Meets the additional requirements for
+  // basic_filebuf.
+  template<>
+    struct char_traits<__gnu_test::character>
+    {
+      typedef __gnu_test::character char_type;
+      typedef unsigned int int_type;
+      typedef __gnu_test::conversion_state state_type;
+      typedef streamoff off_type;
+      typedef fpos<state_type> pos_type;
+
+      static void
+      assign(char_type& c1, const char_type& c2)
+      { c1 = c2; }
+
+      static bool
+      eq(const char_type& c1, const char_type& c2)
+      { return c1.val == c2.val; }
+
+      static bool
+      lt(const char_type& c1, const char_type& c2)
+      { return c1.val < c2.val; }
+
+      static int
+      compare(const char_type* s1, const char_type* s2, size_t n)
+      {
+       for (size_t i = 0; i < n; ++i)
+         {
+           if (lt(s1[i], s2[i]))
+             return -1;
+           else if (lt(s2[i], s1[i]))
+             return 1;
+         }
+       return 0;
+      }
+
+      static size_t
+      length(const char_type* s)
+      {
+       size_t n = 0;
+       while (!eq(s[n], char_type()))
+         ++n;
+       return n;
+      }
+
+      static const char_type*
+      find(const char_type* s, size_t n, const char_type& a)
+      {
+       for (size_t i = 0; i < n; ++i)
+         {
+           if (eq(s[i], a))
+             return s + i;
+         }
+       return NULL;
+      }
+
+      static char_type*
+      move(char_type* s1, const char_type* s2, size_t n)
+      {
+       if (s1 > s2)
+         {
+           for (size_t i = 0; i < n; ++i)
+             assign(s1[n - i - 1], s2[n - i - 1]);
+         }
+       else
+         {
+           for (size_t i = 0; i < n; ++i)
+             assign(s1[i], s2[i]);
+         }
+       return s1;
+      }
+
+      static char_type*
+      copy(char_type* s1, const char_type* s2, size_t n)
+      {
+       for (size_t i = 0; i < n; ++i)
+         assign(s1[i], s2[i]);
+       return s1;
+      }
+
+      static char_type*
+      assign(char_type* s, size_t n, char_type a)
+      {
+       for (size_t i = 0; i < n; ++i)
+         assign(s[i], a);
+       return s;
+      }
+
+      static int_type
+      not_eof(const int_type& c)
+      {
+       if (eq_int_type(c, eof()))
+         return 0;
+       return c;
+      }
+
+      // Note non-trivial conversion to maximize chance of catching bugs
+      static char_type
+      to_char_type(const int_type& c)
+      {
+       char_type ret;
+       ret.val = (c >> 5);
+       return ret;
+      }
+
+      static int_type
+      to_int_type(const char_type& c)
+      {
+       return c.val << 5;
+      }
+
+      static bool
+      eq_int_type(const int_type& c1, const int_type& c2)
+      { return c1 == c2; }
+
+      static int_type eof()
+      { return 0xf; }
+    };
+
+  // codecvt specialization
+  //
+  // The conversion performed by the specialization is not supposed to
+  // be useful, rather it has been designed to demonstrate the
+  // essential features of stateful conversions:
+  // * Number and value of bytes for each internal character depends on the
+  //   state in addition to the character itself.
+  // * Unshift produces an unshift sequence and resets the state. On input
+  //   the unshift sequence causes the state to be reset.
+  //
+  // The conversion for output is as follows:
+  // 1. Calculate the value tmp by xor-ing the state and the internal
+  //    character
+  // 2. Split tmp into either two or three bytes depending on the value of
+  //    state. Output those bytes.
+  // 3. tmp becomes the new value of state.
+  template<>
+    class codecvt<__gnu_test::character, char, __gnu_test::conversion_state>
+      : public locale::facet, public codecvt_base
+    {
+    public:
+      typedef __gnu_test::character intern_type;
+      typedef char extern_type;
+      typedef __gnu_test::conversion_state state_type;
+
+      explicit codecvt(size_t refs = 0)
+      : locale::facet(refs)
+      { }
+
+      result
+      out(state_type& state, const intern_type* from,
+         const intern_type* from_end, const intern_type*& from_next,
+         extern_type* to, extern_type* to_limit, extern_type*& to_next) const
+      {
+       return do_out(state, from, from_end, from_next,
+                     to, to_limit, to_next);
+      }
+
+      result
+      unshift(state_type& state, extern_type* to, extern_type* to_limit,
+             extern_type*& to_next) const
+      { return do_unshift(state, to, to_limit, to_next); }
+
+      result
+      in(state_type& state, const extern_type* from,
+        const extern_type* from_end, const extern_type*& from_next,
+        intern_type* to, intern_type* to_limit, intern_type*& to_next) const
+      {
+       return do_in(state, from, from_end, from_next,
+                    to, to_limit, to_next);
+      }
+
+      int
+      encoding() const throw()
+      { return do_encoding(); }
+
+      bool
+      always_noconv() const throw()
+      { return do_always_noconv(); }
+      
+      int
+      length(state_type& state, const extern_type* from,
+            const extern_type* end, size_t max) const
+      { return do_length(state, from, end, max); }
+      
+      int
+      max_length() const throw()
+      { return do_max_length(); }
+
+      static locale::id id;
+
+    protected:
+      ~codecvt()
+      { }
+
+      virtual result
+      do_out(state_type& state, const intern_type* from,
+            const intern_type* from_end, const intern_type*& from_next,
+            extern_type* to, extern_type* to_limit,
+            extern_type*& to_next) const
+      {
+       while (from < from_end && to < to_limit)
+         {
+           unsigned char tmp = (state.state ^ from->val);
+           if (state.state & 0x8)
+             {
+               if (to >= to_limit - 2)
+                 break;
+               *to++ = (tmp & 0x7);
+               *to++ = ((tmp >> 3) & 0x7);
+               *to++ = ((tmp >> 6) & 0x3);
+             }
+           else
+             {
+               if (to >= to_limit - 1)
+                 break;
+               *to++ = (tmp & 0xf);
+               *to++ = ((tmp >> 4) & 0xf);
+             }
+           state.state = tmp;
+           ++from;
+         }
+
+       from_next = from;
+       to_next = to;
+       return (from < from_end) ? partial : ok;
+      }
+
+      virtual result
+      do_in(state_type& state, const extern_type* from,
+           const extern_type* from_end, const extern_type*& from_next,
+           intern_type* to, intern_type* to_limit,
+           intern_type*& to_next) const
+      {
+       while (from < from_end && to < to_limit)
+         {
+           unsigned char c = *from;
+           if (c & 0xc0)
+             {
+               // Unshift sequence
+               state.state &= c;
+               ++from;
+               continue;
+             }
+
+           unsigned char tmp;
+           if (state.state & 0x8)
+             {
+               if (from >= from_end - 2)
+                 break;
+               tmp = (*from++ & 0x7);
+               tmp |= ((*from++ << 3) & 0x38);
+               tmp |= ((*from++ << 6) & 0xc0);
+             }
+           else
+             {
+               if (from >= from_end - 1)
+                 break;
+               tmp = (*from++ & 0xf);
+               tmp |= ((*from++ << 4) & 0xf0);
+             }
+           to->val = (tmp ^ state.state);
+           state.state = tmp;
+           ++to;
+         }
+
+       from_next = from;
+       to_next = to;
+       return (from < from_end) ? partial : ok;
+      }
+
+      virtual result
+      do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
+                extern_type*& to_next) const
+      {
+       for (unsigned int i = 0; i < CHAR_BIT; ++i)
+         {
+           unsigned int mask = (1 << i);
+           if (state.state & mask)
+             {
+               if (to == to_limit)
+                 {
+                   to_next = to;
+                   return partial;
+                 }
+
+               state.state &= ~mask;
+               *to++ = static_cast<unsigned char>(~mask);
+             }
+         }
+
+       to_next = to;
+       return state.state == 0 ? ok : error;
+      }
+
+      virtual int
+      do_encoding() const throw()
+      { return -1; }
+
+      virtual bool
+      do_always_noconv() const throw()
+      { return false; }
+
+      virtual int
+      do_length(state_type& state, const extern_type* from,
+               const extern_type* end, size_t max) const
+      {
+       const extern_type* beg = from;
+       while (from < end && max)
+         {
+           unsigned char c = *from;
+           if (c & 0xc0)
+             {
+               // Unshift sequence
+               state.state &= c;
+               ++from;
+               continue;
+             }
+
+           unsigned char tmp;
+           if (state.state & 0x8)
+             {
+               if (from >= end - 2)
+                 break;
+               tmp = (*from++ & 0x7);
+               tmp |= ((*from++ << 3) & 0x38);
+               tmp |= ((*from++ << 6) & 0xc0);
+             }
+           else
+             {
+               if (from >= end - 1)
+                 break;
+               tmp = (*from++ & 0xf);
+               tmp |= ((*from++ << 4) & 0xf0);
+             }
+           state.state = tmp;
+           --max;
+         }
+       return from - beg;
+      }
+
+      // Maximum 8 bytes unshift sequence followed by max 3 bytes for
+      // one character.
+      virtual int
+      do_max_length() const throw()
+      { return 11; }
+    };
+
+  locale::id
+  codecvt<__gnu_test::character, char, __gnu_test::conversion_state>::id;
+} // namespace std
+
+#endif // _GLIBCXX_TESTSUITE_CHARACTER_H
+
This page took 0.160773 seconds and 5 git commands to generate.