+2001-12-28 Paolo Carlini <pcarlini@unitus.it>
+ Nathan Myers <ncm@cantrip.org>
+
+ * include/bits/basic_string.h (insert(__pos, __s, __n)):
+ Optimize by avoiding temporaries and working in-place when possible.
+ (insert(__pos1, __str)): Call insert(__pos1, __str, __pos2, __n).
+ (insert(__pos1, __str, __pos2, __n)): Call insert(__pos, __s, __n).
+ * testsuite/21_strings/insert.cc (test02): New testcases.
+
2001-12-27 Phil Edwards <pme@gcc.gnu.org>
* testsuite/testsuite_hooks.h (gnu_counting_struct): Add.
basic_string&
insert(size_type __pos1, const basic_string& __str)
- {
- iterator __p = _M_check(__pos1);
- this->replace(__p, __p, __str._M_ibegin(), __str._M_iend());
- return *this;
- }
+ { return this->insert(__pos1, __str, 0, __str.size()); }
basic_string&
insert(size_type __pos1, const basic_string& __str,
size_type __pos2, size_type __n)
- {
- iterator __p = _M_check(__pos1);
- this->replace(__p, __p, __str._M_check(__pos2),
- __str._M_fold(__pos2, __n));
- return *this;
+ {
+ const size_type __strsize = __str.size();
+ if (__pos2 > __strsize)
+ __throw_out_of_range("basic_string::insert");
+ const bool __testn = __n < __strsize - __pos2;
+ const size_type __newsize = __testn ? __n : __strsize - __pos2;
+ return this->insert(__pos1, __str._M_data() + __pos2, __newsize);
}
basic_string&
insert(size_type __pos, const _CharT* __s, size_type __n)
- {
- iterator __p = _M_check(__pos);
- this->replace(__p, __p, __s, __s + __n);
- return *this;
- }
+ {
+ const size_type __size = this->size();
+ if (__pos > __size)
+ __throw_out_of_range("basic_string::insert");
+ if (__n + __size > this->max_size())
+ __throw_length_error("basic_string::insert");
+ if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
+ || less<const _CharT*>()(_M_data() + __size, __s))
+ return _M_replace_safe(_M_ibegin() + __pos, _M_ibegin() + __pos,
+ __s, __s + __n);
+ else
+ {
+ // Work in-place. If _M_mutate reallocates the string, __s
+ // does not point anymore to valid data, therefore we save its
+ // offset, then we restore it.
+ const size_type __off = __s - _M_data();
+ _M_mutate(__pos, 0, __n);
+ __s = _M_data() + __off;
+ _CharT* __p = _M_data() + __pos;
+ if (__s + __n <= __p)
+ traits_type::copy(__p, __s, __n);
+ else if (__s >= __p)
+ traits_type::copy(__p, __s + __n, __n);
+ else
+ {
+ traits_type::copy(__p, __s, __p - __s);
+ traits_type::copy(__p + (__p - __s), __p + __n, __n - (__p - __s));
+ }
+ return *this;
+ }
+ }
basic_string&
insert(size_type __pos, const _CharT* __s)
return test;
}
+// Once more
+// string& insert(size_type __p, const char* s, size_type n);
+// string& insert(size_type __p, const char* s);
+// but now s points inside the _Rep
+int test02(void)
+{
+ bool test = true;
+
+ std::string str01;
+ const char* title = "Everything was beautiful, and nothing hurt";
+ // Increasing size: str01 is reallocated every time.
+ str01 = title;
+ str01.insert(0, str01.c_str() + str01.size() - 4, 4);
+ VERIFY( str01 == "hurtEverything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(0, str01.c_str(), 5);
+ VERIFY( str01 == "EveryEverything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(10, str01.c_str() + 4, 6);
+ VERIFY( str01 == "Everythingything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(15, str01.c_str(), 10);
+ VERIFY( str01 == "Everything was Everythingbeautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(15, str01.c_str() + 11, 13);
+ VERIFY( str01 == "Everything was was beautifulbeautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(0, str01.c_str());
+ VERIFY( str01 == "Everything was beautiful, and nothing hurt"
+ "Everything was beautiful, and nothing hurt");
+ // Again: no reallocations.
+ str01 = title;
+ str01.insert(0, str01.c_str() + str01.size() - 4, 4);
+ VERIFY( str01 == "hurtEverything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(0, str01.c_str(), 5);
+ VERIFY( str01 == "EveryEverything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(10, str01.c_str() + 4, 6);
+ VERIFY( str01 == "Everythingything was beautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(15, str01.c_str(), 10);
+ VERIFY( str01 == "Everything was Everythingbeautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(15, str01.c_str() + 11, 13);
+ VERIFY( str01 == "Everything was was beautifulbeautiful, and nothing hurt" );
+ str01 = title;
+ str01.insert(0, str01.c_str());
+ VERIFY( str01 == "Everything was beautiful, and nothing hurt"
+ "Everything was beautiful, and nothing hurt");
+
+#ifdef DEBUG_ASSERT
+ assert(test);
+#endif
+ return test;
+}
+
int main()
{
__set_testsuite_memlimit();
test01();
+ test02();
return 0;
}