This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFA, PATCH] A new assign(__str, __pos, __n)
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: libstdc++ at gcc dot gnu dot org
- Cc: ncm at cantrip dot org
- Date: Fri, 14 Dec 2001 00:30:22 +0100
- Subject: [RFA, PATCH] A new assign(__str, __pos, __n)
Hi all,
taking into account to my best all the indications Nathan gave in the last days,
I'm currently testing optimized implementations of those basic_string members
which do not have the source data specified in terms of iterators. After the
trivial case of the assign(s) (plus operator+, and co), this is the natural
second step, in my opinion.
As an example I propose a new implementation of assign(__str, __pos, __n). In
order to better test it I have also enriched a bit the testsuite entry for
21_strings/assign.c.
For sure its speed is greater than that of the current implementation (which
ends up calling the general "paranoic" _M_replace which always buffers; here, on
the other hand, we *never* buffer :-) but I don't have numbers, yet.
Cheers,
Paolo.
P.S. The patch is fully functional, reg-tested i686-pc-linux-gnu.
//------------------------------
basic_string&
assign(const basic_string& __str, size_type __pos, size_type __n)
{
if (__pos > __str.size())
__throw_out_of_range("basic_string::assign");
if (__n)
{
if (_M_rep()->_M_is_shared() || _M_rep() != __str._M_rep())
return _M_replace_safe(_M_ibegin(), _M_iend(),
__str._M_check(__pos),
__str._M_fold(__pos, __n));
else
{
// Work in-place.
bool __testn = __n < __str.size() - __pos;
const size_type __newsize = __testn ? __n : __str.size() -
__pos;
// Avoid memmove, if possible.
if (__pos >= __newsize)
traits_type::copy(_M_data(), __str._M_data() + __pos,
__newsize);
else
traits_type::move(_M_data(), __str._M_data() + __pos,
__newsize);
this->resize(__newsize);
return *this;
}
}
else this->resize(0);
return *this;
}
//------------------------------
//////////////////
diff -prN libstdc++-v3-orig/include/bits/basic_string.h
libstdc++-v3/include/bits/basic_string.h
*** libstdc++-v3-orig/include/bits/basic_string.h Mon Dec 10 15:32:28 2001
--- libstdc++-v3/include/bits/basic_string.h Thu Dec 13 23:12:45 2001
*************** namespace std
*** 477,484 ****
basic_string&
assign(const basic_string& __str, size_type __pos, size_type __n)
! {
! return this->assign(__str._M_check(__pos), __str._M_fold(__pos, __n));
}
basic_string&
--- 477,507 ----
basic_string&
assign(const basic_string& __str, size_type __pos, size_type __n)
! {
! if (__pos > __str.size())
! __throw_out_of_range("basic_string::assign");
! if (__n)
! {
! if (_M_rep()->_M_is_shared() || _M_rep() != __str._M_rep())
! return _M_replace_safe(_M_ibegin(), _M_iend(),
! __str._M_check(__pos),
! __str._M_fold(__pos, __n));
! else
! {
! // Work in-place.
! bool __testn = __n < __str.size() - __pos;
! const size_type __newsize = __testn ? __n : __str.size() - __pos;
! // Avoid memmove, if possible.
! if (__pos >= __newsize)
! traits_type::copy(_M_data(), __str._M_data() + __pos, __newsize);
! else
! traits_type::move(_M_data(), __str._M_data() + __pos, __newsize);
! this->resize(__newsize);
! return *this;
! }
! }
! else this->resize(0);
! return *this;
}
basic_string&
diff -prN libstdc++-v3-orig/testsuite/21_strings/assign.cc
libstdc++-v3/testsuite/21_strings/assign.cc
*** libstdc++-v3-orig/testsuite/21_strings/assign.cc Wed Oct 31 09:27:20 2001
--- libstdc++-v3/testsuite/21_strings/assign.cc Fri Dec 14 00:08:40 2001
*************** test01()
*** 39,46 ****
--- 39,75 ----
VERIFY(aux == "Hawaii");
}
+ void
+ test02()
+ {
+ bool test = true;
+
+ using namespace std;
+
+ string one = "Selling England by the pound";
+ string two = one;
+ string three = "Brilliant trees";
+
+ one.assign(one, 8, 100);
+ VERIFY(one == "England by the pound");
+
+ one.assign(one, 8, 0);
+ VERIFY(one == "");
+
+ one.assign(two, 8, 7);
+ VERIFY(one == "England");
+
+ one.assign(three, 10, 100);
+ VERIFY(one == "trees");
+
+ three.assign(one, 0, 3);
+ VERIFY(three == "tre");
+ }
+
int main()
{
test01();
+ test02();
+
return 0;
}