re PR libstdc++/22515 (operator>>(istream, string/CharT*) can be faster)

2005-07-24  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/22515
	* include/bits/basic_string.h: Declare the specialization
	operator>>(basic_istream<char>&, basic_string<char>&).
	* include/std/std_istream.h: Declate the specialization
	operator>>(basic_istream<char>&, char*).
	* include/std/std_streambuf.h (basic_streambuf): Add friend
	declarations for the above.
	* src/istream.cc: Define the above.
	* testsuite/27_io/basic_istream/extractors_character/char/4.cc: New.
	* testsuite/27_io/basic_istream/extractors_character/wchar_t/4.cc:
	Likewise.
	* testsuite/performance/27_io/ifstream_extract_chars.cc: Likewise.

From-SVN: r102353
This commit is contained in:
Paolo Carlini 2005-07-25 08:47:33 +00:00 committed by Paolo Carlini
parent 0dc42b03d3
commit ceed88b131
8 changed files with 459 additions and 4 deletions

View file

@ -1,3 +1,18 @@
2005-07-24 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/22515
* include/bits/basic_string.h: Declare the specialization
operator>>(basic_istream<char>&, basic_string<char>&).
* include/std/std_istream.h: Declate the specialization
operator>>(basic_istream<char>&, char*).
* include/std/std_streambuf.h (basic_streambuf): Add friend
declarations for the above.
* src/istream.cc: Define the above.
* testsuite/27_io/basic_istream/extractors_character/char/4.cc: New.
* testsuite/27_io/basic_istream/extractors_character/wchar_t/4.cc:
Likewise.
* testsuite/performance/27_io/ifstream_extract_chars.cc: Likewise.
2005-07-20 Paolo Carlini <pcarlini@suse.de>
* include/bits/streambuf.tcc (xsgetn, xsputn): Use streamsize

View file

@ -2373,6 +2373,10 @@ namespace std
operator>>(basic_istream<_CharT, _Traits>& __is,
basic_string<_CharT, _Traits, _Alloc>& __str);
template<>
basic_istream<char>&
operator>>(basic_istream<char>& __is, basic_string<char>& __str);
/**
* @brief Write string to a stream.
* @param os Output stream.

View file

@ -1,6 +1,6 @@
// Input streams -*- C++ -*-
// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004
// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -723,7 +723,12 @@ namespace std
template<typename _CharT, typename _Traits>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s);
// Explicit specialization declaration, defined in src/istream.cc.
template<>
basic_istream<char>&
operator>>(basic_istream<char>& __in, char* __s);
template<class _Traits>
basic_istream<char, _Traits>&
operator>>(basic_istream<char, _Traits>& __in, unsigned char* __s)

View file

@ -1,6 +1,6 @@
// Stream buffer classes -*- C++ -*-
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@ -153,7 +153,16 @@ namespace std
friend streamsize
__copy_streambufs<>(__streambuf_type* __sbin,
__streambuf_type* __sbout);
template<typename _CharT2, typename _Traits2>
friend basic_istream<_CharT2, _Traits2>&
operator>>(basic_istream<_CharT2, _Traits2>&, _CharT2*);
template<typename _CharT2, typename _Traits2, typename _Alloc>
friend basic_istream<_CharT2, _Traits2>&
operator>>(basic_istream<_CharT2, _Traits2>&,
basic_string<_CharT2, _Traits2, _Alloc>&);
template<typename _CharT2, typename _Traits2, typename _Alloc>
friend basic_istream<_CharT2, _Traits2>&
getline(basic_istream<_CharT2, _Traits2>&,

View file

@ -183,6 +183,157 @@ namespace std
return *this;
}
template<>
basic_istream<char>&
operator>>(basic_istream<char>& __in, char* __s)
{
typedef basic_istream<char> __istream_type;
typedef __istream_type::int_type __int_type;
typedef __istream_type::char_type __char_type;
typedef __istream_type::traits_type __traits_type;
typedef __istream_type::__streambuf_type __streambuf_type;
typedef __istream_type::__ctype_type __ctype_type;
streamsize __extracted = 0;
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
__istream_type::sentry __cerb(__in, false);
if (__cerb)
{
try
{
// Figure out how many characters to extract.
streamsize __num = __in.width();
if (__num <= 0)
__num = numeric_limits<streamsize>::max();
const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
const __int_type __eof = __traits_type::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (__extracted < __num - 1
&& !__traits_type::eq_int_type(__c, __eof)
&& !__ct.is(ctype_base::space,
__traits_type::to_char_type(__c)))
{
streamsize __size = std::min(streamsize(__sb->egptr()
- __sb->gptr()),
streamsize(__num - __extracted
- 1));
if (__size > 1)
{
__size = (__ct.scan_is(ctype_base::space,
__sb->gptr() + 1,
__sb->gptr() + __size)
- __sb->gptr());
__traits_type::copy(__s, __sb->gptr(), __size);
__s += __size;
__sb->gbump(__size);
__extracted += __size;
__c = __sb->sgetc();
}
else
{
*__s++ = __traits_type::to_char_type(__c);
++__extracted;
__c = __sb->snextc();
}
}
if (__traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 68. Extractors for char* should store null at end
*__s = __char_type();
__in.width(0);
}
catch(...)
{ __in._M_setstate(ios_base::badbit); }
}
if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
return __in;
}
template<>
basic_istream<char>&
operator>>(basic_istream<char>& __in, basic_string<char>& __str)
{
typedef basic_istream<char> __istream_type;
typedef __istream_type::int_type __int_type;
typedef __istream_type::char_type __char_type;
typedef __istream_type::traits_type __traits_type;
typedef __istream_type::__streambuf_type __streambuf_type;
typedef __istream_type::__ctype_type __ctype_type;
typedef basic_string<char> __string_type;
typedef __string_type::size_type __size_type;
__size_type __extracted = 0;
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
__istream_type::sentry __cerb(__in, false);
if (__cerb)
{
try
{
__str.erase();
const streamsize __w = __in.width();
const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
: __str.max_size();
const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
const __int_type __eof = __traits_type::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (__extracted < __n
&& !__traits_type::eq_int_type(__c, __eof)
&& !__ct.is(ctype_base::space,
__traits_type::to_char_type(__c)))
{
streamsize __size = std::min(streamsize(__sb->egptr()
- __sb->gptr()),
streamsize(__n - __extracted));
if (__size > 1)
{
__size = (__ct.scan_is(ctype_base::space,
__sb->gptr() + 1,
__sb->gptr() + __size)
- __sb->gptr());
__str.append(__sb->gptr(), __size);
__sb->gbump(__size);
__extracted += __size;
__c = __sb->sgetc();
}
else
{
__str += __traits_type::to_char_type(__c);
++__extracted;
__c = __sb->snextc();
}
}
if (__traits_type::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
__in.width(0);
}
catch(...)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 91. Description of operator>> and getline() for string<>
// might cause endless loop
__in._M_setstate(ios_base::badbit);
}
}
if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
return __in;
}
template<>
basic_istream<char>&
getline(basic_istream<char>& __in, basic_string<char>& __str,

View file

@ -0,0 +1,90 @@
// 2005-07-22 Paolo Carlini <pcarlini@suse.de>
// Copyright (C) 2005 Free Software Foundation
//
// 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.6.1.2.3 basic_istream::operator>>
#include <istream>
#include <string>
#include <fstream>
#include <testsuite_hooks.h>
using namespace std;
string prepare(string::size_type len, unsigned nchunks)
{
string ret;
for (unsigned i = 0; i < nchunks; ++i)
{
for (string::size_type j = 0; j < len; ++j)
ret.push_back('a' + rand() % 26);
len *= 2;
ret.push_back(' ');
}
return ret;
}
void check(istream& stream, const string& str, unsigned nchunks)
{
bool test __attribute__((unused)) = true;
char* chunk = new char[str.size()];
memset(chunk, 'X', str.size());
string::size_type index = 0, index_new = 0;
unsigned n = 0;
while (stream >> chunk)
{
index_new = str.find(' ', index);
VERIFY( !str.compare(index, index_new - index, chunk) );
index = index_new + 1;
++n;
memset(chunk, 'X', str.size());
}
VERIFY( stream.eof() );
VERIFY( n == nchunks );
delete[] chunk;
}
// istream& operator>>(istream&, charT*)
void test01()
{
const char filename[] = "inserters_extractors-4.txt";
const unsigned nchunks = 10;
const string data = prepare(666, nchunks);
ofstream ofstrm;
ofstrm.open(filename);
ofstrm.write(data.data(), data.size());
ofstrm.close();
ifstream ifstrm;
ifstrm.open(filename);
check(ifstrm, data, nchunks);
ifstrm.close();
}
int main()
{
test01();
return 0;
}

View file

@ -0,0 +1,90 @@
// 2005-07-22 Paolo Carlini <pcarlini@suse.de>
// Copyright (C) 2005 Free Software Foundation
//
// 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.6.1.2.3 basic_istream::operator>>
#include <istream>
#include <string>
#include <fstream>
#include <testsuite_hooks.h>
using namespace std;
wstring prepare(wstring::size_type len, unsigned nchunks)
{
wstring ret;
for (unsigned i = 0; i < nchunks; ++i)
{
for (wstring::size_type j = 0; j < len; ++j)
ret.push_back(L'a' + rand() % 26);
len *= 2;
ret.push_back(L' ');
}
return ret;
}
void check(wistream& stream, const wstring& str, unsigned nchunks)
{
bool test __attribute__((unused)) = true;
wchar_t* chunk = new wchar_t[str.size()];
wmemset(chunk, L'X', str.size());
wstring::size_type index = 0, index_new = 0;
unsigned n = 0;
while (stream >> chunk)
{
index_new = str.find(' ', index);
VERIFY( !str.compare(index, index_new - index, chunk) );
index = index_new + 1;
++n;
wmemset(chunk, L'X', str.size());
}
VERIFY( stream.eof() );
VERIFY( n == nchunks );
delete[] chunk;
}
// istream& operator>>(istream&, charT*)
void test01()
{
const char filename[] = "inserters_extractors-4.txt";
const unsigned nchunks = 10;
const wstring data = prepare(666, nchunks);
wofstream ofstrm;
ofstrm.open(filename);
ofstrm.write(data.data(), data.size());
ofstrm.close();
wifstream ifstrm;
ifstrm.open(filename);
check(ifstrm, data, nchunks);
ifstrm.close();
}
int main()
{
test01();
return 0;
}

View file

@ -0,0 +1,91 @@
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <cstdio>
#include <fstream>
#include <string>
#include <testsuite_performance.h>
// libstdc++/22515
int main()
{
using namespace std;
using namespace __gnu_test;
time_counter time;
resource_counter resource;
const char filename[] = "tmp_perf_chars.txt";
const unsigned lines = 200000;
const unsigned line_length = 200;
char* line = new char[line_length + 2];
// Construct data.
{
memset(line, 'x', line_length);
line[line_length] = '\n';
line[line_length + 1] = '\0';
ofstream out(filename);
for (unsigned i = 0; i < lines; ++i)
out << line;
}
// operator>>(basic_istream<char>& __in, basic_string<char>& __str)
{
start_counters(time, resource);
for (int iter = 0; iter < 25; ++iter)
{
ifstream file(filename);
string string_line;
while (file >> string_line);
}
stop_counters(time, resource);
report_performance(__FILE__, "string&", time, resource);
clear_counters(time, resource);
}
// operator>>(basic_istream<char>& __in, char* __s)
{
start_counters(time, resource);
for (int iter = 0; iter < 25; ++iter)
{
ifstream file(filename);
while (file >> line);
}
stop_counters(time, resource);
report_performance(__FILE__, "char*", time, resource);
clear_counters(time, resource);
}
delete[] line;
unlink(filename);
return 0;
}