diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -496,6 +496,10 @@ #define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS #endif +#if __has_builtin(__builtin_constant_p) +#define _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P +#endif + #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) // Literal operators ""d and ""y are supported starting with LLVM Clang 8 and AppleClang 10.0.1 @@ -539,6 +543,10 @@ #define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS #endif +#if _GNUC_VER >= 500 +#define _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P +#endif + #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) #define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ @@ -1524,6 +1532,13 @@ # define _LIBCPP_FOPEN_CLOEXEC_MODE #endif + +#ifdef _LIBCPP_COMPILER_HAS_BUILTIN_CONSTANT_P +#define _LIBCPP_BUILTIN_CONSTANT_P(x) __builtin_constant_p(x) +#else +#define _LIBCPP_BUILTIN_CONSTANT_P(x) false +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG diff --git a/libcxx/include/string b/libcxx/include/string --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1571,6 +1571,12 @@ size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); + _LIBCPP_INLINE_VISIBILITY + basic_string& __assign_inline(const value_type* __s, size_type __n); + + basic_string& __assign_external(const value_type* __s, size_type __n); + basic_string& __assign_external(const value_type* __s); + _LIBCPP_INLINE_VISIBILITY void __erase_to_end(size_type __pos); @@ -2198,26 +2204,59 @@ // assign +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_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_inline(const value_type* __s, size_type __n) +{ + value_type* __p; + if (!__is_long()) { + __p = __get_short_pointer(); + __set_short_size(__n); + } else { + __p = __get_long_pointer(); + __set_long_size(__n); + } + traits_type::move(__p, __s, __n); + traits_type::assign(__p[__n], value_type()); + 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); + if (_LIBCPP_BUILTIN_CONSTANT_P(__n) && __n < __min_cap) { + return __assign_inline(__s, __n); + return *this; + } else { + return __assign_external(__s, __n); } - return *this; } template @@ -2404,7 +2443,12 @@ 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)); + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr"); + if (_LIBCPP_BUILTIN_CONSTANT_P(__s[0]) && traits_type::length(__s) < __min_cap) { + return __assign_inline(__s, traits_type::length(__s)); + } else { + return __assign_external(__s); + } } // append