[libcxx-commits] [libcxx] [libc++][NFC] Simplify string a bit (PR #127135)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Feb 14 06:40:44 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Peng Liu (winner245)
<details>
<summary>Changes</summary>
This PR refactors `basic_string` a bit to simplify its implementation in the following ways:
- Instead of manually checking whether a string is long or short, followed by calling the specific functions (e.g., `__get_short_size()`, `__get_long_size()`), we call the general functions (`size()`) to hide the conditional checks and make the code more concise.
- Once a string is known to be long or short, we directly call the specific functions instead of the general versions to get rid of unnecessary internal conditional checks. For example, if the string is a long string, we would directly call `{__set, __get}_long_pointer` instead of `{__set, __get}_pointer()`.
- When the string size is calculated multiple times using `traits_type::length(__s)`, a variable is introduced to store its length, ensuring the calculation is performed only once.
- Variables that are defined in both the `if` and `else` branches are now declared in a common scope to reduce redundancy.
---
Full diff: https://github.com/llvm/llvm-project/pull/127135.diff
1 Files Affected:
- (modified) libcxx/include/string (+31-47)
``````````diff
diff --git a/libcxx/include/string b/libcxx/include/string
index b280f5f458459..41cc082d94815 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2335,7 +2335,7 @@ private:
if (!__str.__is_long()) {
if (__is_long()) {
__annotate_delete();
- __alloc_traits::deallocate(__alloc_, __get_long_pointer(), capacity() + 1);
+ __alloc_traits::deallocate(__alloc_, __get_long_pointer(), __get_long_cap());
__rep_ = __rep();
}
__alloc_ = __str.__alloc_;
@@ -2350,7 +2350,7 @@ private:
__alloc_ = std::move(__a);
__set_long_pointer(__allocation.ptr);
__set_long_cap(__allocation.count);
- __set_long_size(__str.size());
+ __set_long_size(__str.__get_long_size());
}
}
}
@@ -2470,8 +2470,8 @@ template <class _CharT,
class _Traits,
class _Allocator = allocator<_CharT>,
class = enable_if_t<__is_allocator<_Allocator>::value> >
-explicit basic_string(basic_string_view<_CharT, _Traits>,
- const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
+explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
+ -> basic_string<_CharT, _Traits, _Allocator>;
template <class _CharT,
class _Traits,
@@ -2758,20 +2758,19 @@ template <class _CharT, class _Traits, class _Allocator>
template <bool __is_short>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) {
- size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
- if (__n < __cap) {
- size_type __old_size = __is_short ? __get_short_size() : __get_long_size();
+ size_type __cap = capacity();
+ size_type __old_size = size();
+ if (__n <= __cap) {
if (__n > __old_size)
__annotate_increase(__n - __old_size);
- pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
- __is_short ? __set_short_size(__n) : __set_long_size(__n);
+ pointer __p =
+ __is_short ? (__set_short_size(__n), __get_short_pointer()) : (__set_long_size(__n), __get_long_pointer());
traits_type::copy(std::__to_address(__p), __s, __n);
traits_type::assign(__p[__n], value_type());
if (__old_size > __n)
__annotate_shrink(__old_size);
} else {
- size_type __sz = __is_short ? __get_short_size() : __get_long_size();
- __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
+ __grow_by_and_replace(__cap, __n - __cap, __old_size, 0, __old_size, __n, __s);
}
return *this;
}
@@ -2779,17 +2778,16 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s, size_type __n) {
- size_type __cap = capacity();
+ size_type __cap = capacity();
+ size_type __old_size = size();
if (__cap >= __n) {
- size_type __old_size = size();
if (__n > __old_size)
__annotate_increase(__n - __old_size);
value_type* __p = std::__to_address(__get_pointer());
traits_type::move(__p, __s, __n);
return __null_terminate_at(__p, __n);
} else {
- size_type __sz = size();
- __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s);
+ __grow_by_and_replace(__cap, __n - __cap, __old_size, 0, __old_size, __n, __s);
return *this;
}
}
@@ -2807,8 +2805,7 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
size_type __cap = capacity();
size_type __old_size = size();
if (__cap < __n) {
- size_type __sz = size();
- __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
+ __grow_by_without_replace(__cap, __n - __cap, __old_size, 0, __old_size);
__annotate_increase(__n);
} else if (__n > __old_size)
__annotate_increase(__n - __old_size);
@@ -2820,17 +2817,10 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) {
- pointer __p;
size_type __old_size = size();
if (__old_size == 0)
__annotate_increase(1);
- if (__is_long()) {
- __p = __get_long_pointer();
- __set_long_size(1);
- } else {
- __p = __get_short_pointer();
- __set_short_size(1);
- }
+ pointer __p = __is_long() ? (__set_long_size(1), __get_long_pointer()) : (__set_short_size(1), __get_short_pointer());
traits_type::assign(*__p, __c);
traits_type::assign(*++__p, value_type());
if (__old_size > 1)
@@ -2846,8 +2836,8 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
if (!__is_long()) {
if (!__str.__is_long()) {
size_type __old_size = __get_short_size();
- if (__get_short_size() < __str.__get_short_size())
- __annotate_increase(__str.__get_short_size() - __get_short_size());
+ if (__old_size < __str.__get_short_size())
+ __annotate_increase(__str.__get_short_size() - __old_size);
__rep_ = __str.__rep_;
if (__old_size > __get_short_size())
__annotate_shrink(__old_size);
@@ -3014,9 +3004,9 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) {
_LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr");
+ size_type __n = traits_type::length(__s);
return __builtin_constant_p(*__s)
- ? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s))
- : __assign_external(__s, traits_type::length(__s)))
+ ? (__fits_in_sso(__n) ? __assign_short(__s, __n) : __assign_external(__s, __n))
: __assign_external(__s);
}
// append
@@ -3089,18 +3079,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu
}
if (__sz == __cap) {
__grow_by_without_replace(__cap, 1, __sz, __sz, 0);
- __annotate_increase(1);
__is_short = false; // the string is always long after __grow_by
- } else
- __annotate_increase(1);
- pointer __p = __get_pointer();
- if (__is_short) {
- __p = __get_short_pointer() + __sz;
- __set_short_size(__sz + 1);
- } else {
- __p = __get_long_pointer() + __sz;
- __set_long_size(__sz + 1);
}
+ __annotate_increase(1);
+ pointer __p = __is_short ? (__set_short_size(__sz + 1), __get_short_pointer() + __sz)
+ : (__set_long_size(__sz + 1), __get_long_pointer() + __sz);
traits_type::assign(*__p, __c);
traits_type::assign(*++__p, value_type());
}
@@ -3477,11 +3460,13 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
- size_type __old_size = size();
+ size_type __old_size;
if (__is_long()) {
+ __old_size = __get_long_size();
traits_type::assign(*__get_long_pointer(), value_type());
__set_long_size(0);
} else {
+ __old_size = __get_short_size();
traits_type::assign(*__get_short_pointer(), value_type());
__set_short_size(0);
}
@@ -3539,11 +3524,12 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
_LIBCPP_ASSERT_INTERNAL(__is_long(), "Trying to shrink small string");
// We're a long string and we're shrinking into the small buffer.
+ auto __ptr = __get_long_pointer();
+ auto __size = __get_long_size();
+ auto __cap = __get_long_cap();
+
if (__fits_in_sso(__target_capacity)) {
__annotation_guard __g(*this);
- auto __ptr = __get_long_pointer();
- auto __size = __get_long_size();
- auto __cap = __get_long_cap();
traits_type::copy(std::__to_address(__get_short_pointer()), std::__to_address(__ptr), __size + 1);
__set_short_size(__size);
__alloc_traits::deallocate(__alloc_, __ptr, __cap);
@@ -3554,21 +3540,19 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
try {
# endif // _LIBCPP_HAS_EXCEPTIONS
__annotation_guard __g(*this);
- auto __size = size();
auto __allocation = std::__allocate_at_least(__alloc_, __target_capacity + 1);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
- if (__allocation.count - 1 > capacity()) {
+ if (__allocation.count > __cap) {
__alloc_traits::deallocate(__alloc_, __allocation.ptr, __allocation.count);
return;
}
__begin_lifetime(__allocation.ptr, __allocation.count);
- auto __ptr = __get_long_pointer();
traits_type::copy(std::__to_address(__allocation.ptr), std::__to_address(__ptr), __size + 1);
- __alloc_traits::deallocate(__alloc_, __ptr, __get_long_cap());
+ __alloc_traits::deallocate(__alloc_, __ptr, __cap);
__set_long_cap(__allocation.count);
__set_long_pointer(__allocation.ptr);
# if _LIBCPP_HAS_EXCEPTIONS
``````````
</details>
https://github.com/llvm/llvm-project/pull/127135
More information about the libcxx-commits
mailing list