+2001-05-07 Benjamin Kosnik <bkoz@redhat.com>
+
+ libstdc++/2523
+ * include/bits/std_fstream.h (basic_filebuf): Change signature.
+ * include/bits/fstream.tcc (basic_filebuf): Change bool argument
+ to int_type, pass in buffer size info.
+ * include/bits/std_streambuf.h (_M_is_indeterminate): Check for
+ unbuffered situation.
+ (underflow): Remove codecvt bits for the time being.
+ * include/bits/istream.tcc (istream::sentry): Avoid sputbackc call.
+ * include/bits/locale_facets.tcc (_M_extract): Cache dereference
+ values from iterators, clean.
+ * src/locale.cc: Ditto.
+ * include/bits/sbuf_iter.h: Format.
+ * src/ios.cc: Explicitly pass in buffer sizes at creation time.
+ * testsuite/27_io/narrow_stream_objects.cc: Add tests.
+ * testsuite/27_io/filebuf.cc: Tweaks.
+ * testsuite/27_io/filebuf_members.cc: Tweaks.
+
2001-05-07 Mark Mitchell <mark@codesourcery.com>
* config/os/solaris/solaris2.7/bits/os_defines.h
template<typename _CharT, typename _Traits>
basic_filebuf<_CharT, _Traits>::
- basic_filebuf(__c_file_type* __f, bool __s, ios_base::openmode __mode)
+ basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, int_type __s)
: __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()),
_M_state_beg(__state_type()), _M_last_overflowed(false)
{
if (this->is_open())
{
_M_mode = __mode;
- if (!__s)
+ if (__s)
{
+ _M_buf_size_opt = __s;
_M_allocate_buffers();
_M_set_indeterminate();
}
{
int_type __ret = traits_type::eof();
bool __testin = _M_mode & ios_base::in;
-
+ bool __testout = _M_mode & ios_base::out;
+
+ // XXX Should re-enable codecvt bits disabled after 2.90.8.
if (__testin)
{
// Check for pback madness, and if so swich back to the
bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
bool __testinit = _M_is_indeterminate();
- bool __testout = _M_mode & ios_base::out;
-
// Sync internal and external buffers.
// NB: __testget -> __testput as _M_buf_unified here.
if (__testget)
if (__testinit || __testget)
{
-#if 1
+ // Assume buffered case, need to refill internal buffers.
streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size);
if (0 < __size)
{
{
// XXX Something is wrong, do error checking.
}
- }
-#else
- // 2000-08-04 bkoz disable
- // Part one: (Re)fill external buf (_M_file->_IO_*) from
- // external byte sequence (whatever physical byte sink or
- // FILE actually is.)
- char_type* __conv_buf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * _M_buf_size));
- streamsize __size = _M_file->xsgetn(__conv_buf, _M_buf_size);
-
- // Part two: (Re)fill internal buf contents from external buf.
- if (0 < __size)
- {
- _M_set_determinate(__size);
-
- char* __conv_cur = __conv_buf;
- _M_state_beg = _M_state_cur;
- __res_type __r = _M_fcvt->in(_M_state_cur,
- __conv_buf,
- __conv_buf + __size,
- const_cast<const char*&>(__conv_cur),
- _M_in_beg, _M_in_end, _M_in_cur);
-
- if (__r == codecvt_base::partial)
- {
- // XXX Retry with larger _M_buf size.
- }
-
- // Set pointers to internal and external buffers
- // correctly. . .
- if (__r != codecvt_base::error)
- {
- if (__testout)
- _M_out_cur = _M_in_cur;
- __ret = traits_type::to_int_type(*_M_in_cur);
- }
-
- // Part three: Sync the current internal buffer
- // position with the (now overshot) external buffer
- // position.
- streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur,
- ios_base::in);
- if (__p == -1)
- {
- // XXX Something is wrong, do error checking.
- }
- }
-#endif
+ }
}
}
_M_last_overflowed = false;
if (!__noskipws && (__in.flags() & ios_base::skipws))
{
const __int_type __eof = traits_type::eof();
- __int_type __c = __int_type(0);
- __streambuf_type* __sb = __in.rdbuf();
const __ctype_type* __ctype = __in._M_get_fctype_ios();
- bool __testsp = true;
- bool __testeof = false;
-
- while (!__testeof && __testsp)
- {
- __c = __sb->sbumpc();
- __testeof = __c == __eof;
- __testsp = __ctype->is(ctype_base::space, __c);
- }
+ __streambuf_type* __sb = __in.rdbuf();
+ __int_type __c = __sb->sgetc();
- if (!__testeof && !__testsp)
- __sb->sputbackc(__c);
+ while (__c != __eof && __ctype->is(ctype_base::space, __c))
+ __c = __sb->snextc();
+
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
//195. Should basic_istream::sentry's constructor ever set eofbit?
- else
+ if (__c == __eof)
__in.setstate(ios_base::eofbit);
#endif
}
switch (__ev)
{
case ios_base::erase_event:
- delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0;
+ delete static_cast<_Format_cache<_CharT>*>(__p);
+ __p = 0;
break;
case ios_base::copyfmt_event:
// If just stored zero, the callback would get registered again.
- try {
- __p = new _Format_cache<_CharT>;
- }
- catch(...) {
- }
+ try
+ { __p = new _Format_cache<_CharT>; }
+ catch(...)
+ { }
break;
case ios_base::imbue_event:
static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
typedef _Traits traits_type;
typedef basic_streambuf<_CharT, _Traits> streambuf_type;
typedef basic_ostream<_CharT, _Traits> ostream_type;
-
+
+ private:
+ streambuf_type* _M_sbuf;
+ bool _M_failed;
+
+ public:
inline
ostreambuf_iterator(ostream_type& __s) throw ()
: _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
bool
failed() const throw()
{ return _M_failed; }
-
- private:
- streambuf_type* _M_sbuf;
- bool _M_failed;
};
template<typename _CharT, typename _Traits>
// 24.5.3 Template class istreambuf_iterator
- template<class _CharT, class _Traits>
+ template<typename _CharT, typename _Traits>
class istreambuf_iterator
: public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
_CharT*, _CharT&>
{
public:
-
// Types:
typedef _CharT char_type;
typedef _Traits traits_type;
// Non-standard Types:
typedef istreambuf_iterator<_CharT, _Traits> __istreambufiter_type;
+ private:
+ // 24.5.3 istreambuf_iterator
+ // p 1
+ // If the end of stream is reached (streambuf_type::sgetc()
+ // returns traits_type::eof()), the iterator becomes equal to
+ // the "end of stream" iterator value.
+ // NB: This implementation assumes the "end of stream" value
+ // is EOF, or -1.
+ streambuf_type* _M_sbuf;
+ int_type _M_c;
+
+ public:
istreambuf_iterator() throw()
: _M_sbuf(NULL), _M_c(-2) { }
return (__thiseof && __beof || (!__thiseof && !__beof));
}
#endif
-
- private:
- // 24.5.3 istreambuf_iterator
- // p 1
- // If the end of stream is reached (streambuf_type::sgetc()
- // returns traits_type::eof()), the iterator becomes equal to
- // the "end of stream" iterator value.
- // NB: This implementation assumes the "end of stream" value
- // is EOF, or -1.
- streambuf_type* _M_sbuf;
- int_type _M_c;
};
template<typename _CharT, typename _Traits>
operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
const istreambuf_iterator<_CharT, _Traits>& __b)
{ return !__a.equal(__b); }
-
} // namespace std
-
#endif
-
-
-
basic_filebuf();
// Non-standard ctor:
- basic_filebuf(__c_file_type* __f, bool __s, ios_base::openmode __mode);
+ basic_filebuf(__c_file_type* __f, ios_base::openmode __mode,
+ int_type __s = static_cast<int_type>(BUFSIZ));
virtual
~basic_filebuf()
this->setg(_M_buf, _M_buf, _M_buf + __off);
if (__testout)
this->setp(_M_buf, _M_buf + __off);
-
}
bool
_M_is_indeterminate(void)
{
bool __ret = false;
- if (_M_mode & ios_base::in)
- __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
- if (_M_mode & ios_base::out)
- __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
+ // Don't return true if unbuffered.
+ if (_M_buf)
+ {
+ if (_M_mode & ios_base::in)
+ __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
+ if (_M_mode & ios_base::out)
+ __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
+ }
return __ret;
}
{
int_type __ret;
if (_M_in_cur && _M_in_cur < _M_in_end)
- __ret = traits_type::to_int_type(*gptr());
+ __ret = traits_type::to_int_type(*(this->gptr()));
else
__ret = this->underflow();
return __ret;
void
ios_base::Init::_S_ios_create(bool __sync)
{
+ int __bufsize = __sync ? 0 : static_cast<int>(BUFSIZ);
// NB: The file std_iostream.h creates the four standard files
- // with NULL buffers. At this point, we swap out these
- new (&cout) ostream(new filebuf(stdout, __sync, ios_base::out));
- new (&cin) istream(new filebuf(stdin, __sync, ios_base::in));
- new (&cerr) ostream(new filebuf(stderr, __sync, ios_base::out));
+ // with NULL buffers. At this point, we swap out the dummy NULL
+ // buffers with the real deal.
+ new (&cout) ostream(new filebuf(stdout, ios_base::out, __bufsize));
+ new (&cin) istream(new filebuf(stdin, ios_base::in, 1));
+ new (&cerr) ostream(new filebuf(stderr, ios_base::out, __bufsize));
new (&clog) ostream(cerr.rdbuf());
cin.tie(&cout);
cerr.flags(ios_base::unitbuf);
#ifdef _GLIBCPP_USE_WCHAR_T
- new (&wcout) wostream( new wfilebuf(stdout, __sync, ios_base::out));
- new (&wcin) wistream(new wfilebuf(stdin, __sync, ios_base::in));
- new (&wcerr) wostream(new wfilebuf(stderr, __sync, ios_base::out));
+ new (&wcout) wostream( new wfilebuf(stdout, ios_base::out, __bufsize));
+ new (&wcin) wistream(new wfilebuf(stdin, ios_base::in, 1));
+ new (&wcerr) wostream(new wfilebuf(stderr, ios_base::out, __bufsize));
new (&wclog) wostream(wcerr.rdbuf());
wcin.tie(&wcout);
wcerr.flags(ios_base::unitbuf);
// Stage 2: extract characters.
__cache_type const* __fmt = __cache_type::_S_get(__io);
- bool __valid = __beg != __end;
+
// Fail quickly if !__valid
- if (!__valid)
+ if (__beg == __end)
{
__err |= (ios_base::eofbit | ios_base::failbit);
return;
// Check first for sign
bool __testsign = false;
if ((__c == __lits[__cache_type::_S_minus])
- || (__c == __lits[__cache_type::_S_plus]))
+ || (__c == __lits[__cache_type::_S_plus]))
{
+ __testsign = true;
__xtrc[__pos++] = __c;
++__beg;
- __testsign = true;
- // whitespace may follow a sign
- while ((__beg != __end) && (isspace(*__beg)))
- ++__beg;
+ __c = * __beg;
+
+ // Whitespace may follow a sign
+ while ((__beg != __end) && (isspace(__c)))
+ {
+ ++__beg;
+ __c = *__beg;
+ }
// There had better be more to come...
if (__beg == __end)
}
}
- bool __testzero = false; // Has there been a leading zero?
-
- // Now check if first character is a zero
- __c = *__beg;
+ // Now check if first character is a zero.
+ bool __testzero = false;
if (__c == __lits[__cache_type::_S_digits])
{
__testzero = true;
++__beg;
+ __c = *__beg;
// We have to check for __beg == __end here. If so,
// a plain '0' (possibly with a sign) can be got rid of now
if (__beg == __end)
{
- __xtrc[__pos++] = __c;
+ __xtrc[__pos++] = __lits[__cache_type::_S_digits];
__xtrc[__pos] = '\0';
__err |= ios_base::eofbit;
return;
if (!__fp && __base != 10 && __base != 8)
{
// Here, __base == 0 or 16
- __c = *__beg;
if ((__c == __lits[__cache_type::_S_x])
|| (__c == __lits[__cache_type::_S_X]))
{
++__beg;
+ __c = *__beg;
__base = 16;
__testzero = false; // "0x" is not a leading zero
}
// Remove any more leading zeros
while (__beg != __end)
{
- if (*__beg == __lits[__cache_type::_S_digits])
+ if (__c == __lits[__cache_type::_S_digits])
{
++__beg;
+ __c = *__beg;
__testzero = true;
}
else
// We may need to know if anything is found here. A leading zero
// (removed by now) would count.
bool __testunits = __testzero;
- while (__valid && __beg != __end)
+ while (__beg != __end)
{
- __valid = false;
- __c = *__beg;
- const char* __p = strchr(__fmt->_S_literals, __c);
+ const char* __p = strchr(__lits, __c);
// NB: strchr returns true for __c == 0x0
- if (__p && __c)
- {
- // Try first for acceptable digit; record it if found
- if ((__p >= &__lits[__cache_type::_S_digits]
- && __p < &__lits[__cache_type::_S_digits + __base])
- || (__p >= &__lits[__cache_type::_S_udigits]
- && __p < &__lits[__cache_type::_S_udigits + __base]))
- {
- __xtrc[__pos++] = __c;
- ++__sep_pos;
- __valid = true;
- __testunits = true;
- }
- }
- else if (__c == __fmt->_M_thousands_sep
- && __fmt->_M_use_grouping)
- {
+ if (__p && __c
+ &&((__p >= &__lits[__cache_type::_S_digits]
+ && __p < &__lits[__cache_type::_S_digits + __base])
+ || (__p >= &__lits[__cache_type::_S_udigits]
+ && __p < &__lits[__cache_type::_S_udigits + __base])))
+ {
+ // Try first for acceptable digit; record it if found.
+ __xtrc[__pos++] = __c;
+ ++__sep_pos;
+ __testunits = true;
+ ++__beg;
+ __c = *__beg;
+ }
+ else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
+ {
// NB: Thousands separator at the beginning of a string
// is a no-no, as is two consecutive thousands
- // separators
+ // separators.
if (__sep_pos)
{
__grp += static_cast<char>(__sep_pos);
__sep_pos = 0;
- __valid = true;
+ ++__beg;
+ __c = *__beg;
}
else
- __err |= ios_base::failbit;
+ {
+ __err |= ios_base::failbit;
+ break;
+ }
}
- if (__valid)
- ++__beg;
+ else
+ // Not a valid input item.
+ break;
}
// Digit grouping is checked. If _M_groupings() doesn't
// That's it for integer types. Remaining code is for floating point
if (__fp && __beg != __end)
{
- __c = *__beg;
// Check first for decimal point. There MUST be one if
// __testunits is false.
bool __testdec = false; // Is there a decimal point
{
__xtrc[__pos++] = '.';
++__beg;
+ __c = *__beg;
+
// Now we get any digits after the decimal point
// There MUST be some if __testunits is false.
while (__beg != __end)
{
- __c = *__beg;
- const char* __p = strchr(__fmt->_S_literals, __c);
+ const char* __p = strchr(__lits, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
{
__xtrc[__pos++] = __c;
++__beg;
+ __c = *__beg;
__testdec = true;
}
else
// Now we may find an exponent
if (__beg != __end)
{
- __c = *__beg;
if ((__c == __lits[__cache_type::_S_ee])
|| (__c == __lits[__cache_type::_S_Ee]))
{
__xtrc[__pos++] = __c;
++__beg;
+ __c = *__beg;
+
// Now there may be a sign
if (__beg != __end)
{
- __c = *__beg;
if ((__c == __lits[__cache_type::_S_minus])
|| (__c == __lits[__cache_type::_S_plus]))
{
__xtrc[__pos++] = __c;
++__beg;
+ __c = *__beg;
// whitespace may follow a sign
- while ((__beg != __end) && (isspace(*__beg)))
- ++__beg;
-
+ while ((__beg != __end) && (isspace(__c)))
+ {
+ ++__beg;
+ __c = *__beg;
+ }
}
}
// And now there must be some digits
}
while (__beg != __end)
{
- __c = *__beg;
- const char* __p = strchr(__fmt->_S_literals, __c);
+ const char* __p = strchr(__lits, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
{
__xtrc[__pos++] = __c;
++__beg;
+ __c = *__beg;
}
else
break;
operator<(const gnu_char_type& __lhs)
{ return character < __lhs.character; }
+ // default ctor
+ gnu_char_type() { }
+
// to_char_type
gnu_char_type(const unsigned long& __l) : character(__l) { }
FILE* f2 = fopen(name_01, "r");
VERIFY( f2 != NULL );
{
- std::filebuf fb(f2, false, std::ios_base::in);
+ std::filebuf fb(f2, std::ios_base::in, 512);
}
close_num = fclose(f2);
VERIFY( close_num == 0 );
// 2000-08-02 bkoz
-// Copyright (C) 2000 Free Software Foundation, Inc.
+// Copyright (C) 2000, 2001 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
return 0;
}
+// libstdc++/2523
+void test02()
+{
+ int i;
+ cin >> i;
+ cout << "i == " << i << endl;
+}
+
+// libstdc++/2523
+void test03()
+{
+ ios_base::sync_with_stdio(false);
+
+ int i;
+ cin >> i;
+ cout << "i == " << i << endl;
+}
int
main()
{
test01();
+
+ // test02();
+ // test03();
return 0;
}