diff --git a/libcxx/include/__string b/libcxx/include/__string --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -152,7 +152,8 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \ + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \ + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \ @@ -176,7 +177,6 @@ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ @@ -184,6 +184,8 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \ + _Func(_LIBCPP_FUNC_VIS _CharType* basic_string<_CharType>::__resize(size_type)) \ + _Func(_LIBCPP_FUNC_VIS _CharType* basic_string<_CharType>::__resize(size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) diff --git a/libcxx/include/string b/libcxx/include/string --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1541,6 +1541,12 @@ if (__guess == __min_cap) ++__guess; return __guess; } + static _LIBCPP_INLINE_VISIBILITY size_type + __recommend_cap(size_type __cap) _NOEXCEPT { + return __align_it < sizeof(value_type) < __alignment + ? __alignment / sizeof(value_type) + : 1 > (__cap); + } inline void __init(const value_type* __s, size_type __sz, size_type __reserve); @@ -1662,6 +1668,35 @@ _NOEXCEPT {} + basic_string& __assign_external(const value_type* __s); + basic_string& __assign_external(const value_type* __s, size_type __n); + + template + value_type* __resize(size_type __n); + + inline value_type* __resize(size_type __n) { + return __is_long() ? __resize(__n) : __resize(__n); + } + + inline value_type* __resize_small(size_type __n) _NOEXCEPT { + pointer __p = __is_long() + ? (__set_long_size(__n), __get_long_pointer()) + : (__set_short_size(__n), __get_short_pointer()); + traits_type::assign(__p[__n], value_type()); + return _VSTD::__to_address(__p); + } + + inline basic_string& __assign_small_length(const value_type* __s, + size_type __n) { + value_type* p = (__n < __min_cap) ? __resize_small(__n) : __resize(__n); + if (__builtin_constant_p(*__s)) { + traits_type::copy(p, __s, __n); + } else { + traits_type::move(p, __s, __n); + } + return *this; + } + _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type); @@ -2221,6 +2256,38 @@ traits_type::assign(__p[__old_sz], value_type()); } +template +template +_CharT* basic_string<_CharT, _Traits, _Allocator>::__resize(size_type __n) { + size_type __old_cap = __is_short ? __min_cap : __get_long_cap(); + pointer __old_p = __is_short ? __get_short_pointer() : __get_long_pointer(); + if (__n < __old_cap) { + __is_short ? __set_short_size(__n) : __set_long_size(__n); + return _VSTD::__to_address(__old_p); + } + + const size_type __ms = max_size(); + if (__n > __ms) this->__throw_length_error(); + + size_type __new_cap; + if (__is_short) { + __new_cap = __recommend_cap(_VSTD::max(__n + 1, 32)); + } else { + __new_cap = (__old_cap < __ms / 2 - __alignment) + ? __recommend_cap(_VSTD::max(__n + 1, 2 * __old_cap)) + : __ms; + } + pointer __p = __alloc_traits::allocate(__alloc(), __new_cap); + __invalidate_all_iterators(); + __set_long_pointer(__p); + __is_short ? __set_short_size(__n) : __set_long_size(__n); + __set_long_cap(__new_cap); + if (!__is_short) { + __alloc_traits::deallocate(__alloc(), __old_p, __old_cap); + } + return __p; +} + template void basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, @@ -2270,26 +2337,32 @@ return *this; } +template +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::__assign_external( + const value_type* __s, size_type __n) { + size_type __cap = capacity(); + if (__cap >= __n) { + value_type* __p = _VSTD::__to_address(__get_pointer()); + traits_type::move(__p, __s, __n); + traits_type::assign(__p[__n], value_type()); + __set_size(__n); + __invalidate_iterators_past(__n); + } else { + size_type __sz = size(); + __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); + } + return *this; +} + template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr"); - size_type __cap = capacity(); - if (__cap >= __n) - { - value_type* __p = _VSTD::__to_address(__get_pointer()); - traits_type::move(__p, __s, __n); - traits_type::assign(__p[__n], value_type()); - __set_size(__n); - __invalidate_iterators_past(__n); - } - else - { - size_type __sz = size(); - __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); - } - return *this; + return (__builtin_constant_p(__n) && __n <= 128) + ? __assign_small_length(__s, __n) + : __assign_external(__s, __n); } template @@ -2474,14 +2547,21 @@ } +template +basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { + return __assign_external(__s, traits_type::length(__s)); +} + template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { _LIBCPP_ASSERT(__s != nullptr, "string::assign received nullptr"); - return assign(__s, traits_type::length(__s)); + return (__builtin_constant_p(*__s) && traits_type::length(__s) <= 128) + ? __assign_small_length(__s, traits_type::length(__s)) + : __assign_external(__s); } - // append template