Skip to content

Commit e30a5d6

Browse files
authored
[libc++][NFC] Simplify string a bit (#127135)
This PR refactors `basic_string` a bit to simplify its implementation in the following ways: - Instead of manually checking whether a string is short or long, 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 determined to be short or long, we directly call the specific functions instead of the general versions to get rid of unnecessary internal conditional checks. For example, for a long string, we would directly call `{__set, __get}_long_pointer` instead of `{__set, __get}_pointer()`. - Variables that are defined in both the `if` and `else` branches are now declared in a common scope to reduce redundancy. - When the string size is calculated multiple times using `traits_type::length(__s)`, a variable is introduced to store its length. While modern compilers can optimize this with constant folding, explicitly storing the length improves code readability and makes the logic clearer. - Fixed synopsis with missing default arguments.
1 parent 2091547 commit e30a5d6

File tree

1 file changed

+53
-45
lines changed

1 file changed

+53
-45
lines changed

libcxx/include/string

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,9 @@ public:
235235
template <class T>
236236
basic_string& insert(size_type pos1, const T& t); // constexpr since C++20
237237
basic_string& insert(size_type pos1, const basic_string& str,
238-
size_type pos2, size_type n); // constexpr since C++20
238+
size_type pos2, size_type n2=npos); // constexpr since C++20
239239
template <class T>
240-
basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20
240+
basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n=npos); // C++17, constexpr since C++20
241241
basic_string& insert(size_type pos, const value_type* s, size_type n=npos); // C++14, constexpr since C++20
242242
basic_string& insert(size_type pos, const value_type* s); // constexpr since C++20
243243
basic_string& insert(size_type pos, size_type n, value_type c); // constexpr since C++20
@@ -260,7 +260,7 @@ public:
260260
size_type pos2, size_type n2=npos); // C++14, constexpr since C++20
261261
template <class T>
262262
basic_string& replace(size_type pos1, size_type n1, const T& t,
263-
size_type pos2, size_type n); // C++17, constexpr since C++20
263+
size_type pos2, size_type n2=npos); // C++17, constexpr since C++20
264264
basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2); // constexpr since C++20
265265
basic_string& replace(size_type pos, size_type n1, const value_type* s); // constexpr since C++20
266266
basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); // constexpr since C++20
@@ -2307,7 +2307,7 @@ private:
23072307
if (!__str.__is_long()) {
23082308
if (__is_long()) {
23092309
__annotate_delete();
2310-
__alloc_traits::deallocate(__alloc_, __get_long_pointer(), capacity() + 1);
2310+
__alloc_traits::deallocate(__alloc_, __get_long_pointer(), __get_long_cap());
23112311
__rep_ = __rep();
23122312
}
23132313
__alloc_ = __str.__alloc_;
@@ -2322,7 +2322,7 @@ private:
23222322
__alloc_ = std::move(__a);
23232323
__set_long_pointer(__allocation.ptr);
23242324
__set_long_cap(__allocation.count);
2325-
__set_long_size(__str.size());
2325+
__set_long_size(__str.__get_long_size());
23262326
}
23272327
}
23282328
}
@@ -2364,8 +2364,14 @@ private:
23642364
size_type __old_size = size();
23652365
if (__n > __old_size)
23662366
__annotate_increase(__n - __old_size);
2367-
pointer __p =
2368-
__is_long() ? (__set_long_size(__n), __get_long_pointer()) : (__set_short_size(__n), __get_short_pointer());
2367+
pointer __p;
2368+
if (__is_long()) {
2369+
__set_long_size(__n);
2370+
__p = __get_long_pointer();
2371+
} else {
2372+
__set_short_size(__n);
2373+
__p = __get_short_pointer();
2374+
}
23692375
traits_type::move(std::__to_address(__p), __s, __n);
23702376
traits_type::assign(__p[__n], value_type());
23712377
if (__old_size > __n)
@@ -2441,8 +2447,8 @@ template <class _CharT,
24412447
class _Traits,
24422448
class _Allocator = allocator<_CharT>,
24432449
class = enable_if_t<__is_allocator<_Allocator>::value> >
2444-
explicit basic_string(basic_string_view<_CharT, _Traits>,
2445-
const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
2450+
explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
2451+
-> basic_string<_CharT, _Traits, _Allocator>;
24462452

24472453
template <class _CharT,
24482454
class _Traits,
@@ -2705,38 +2711,42 @@ template <class _CharT, class _Traits, class _Allocator>
27052711
template <bool __is_short>
27062712
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
27072713
basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) {
2708-
size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
2714+
const auto __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
2715+
const auto __size = __is_short ? __get_short_size() : __get_long_size();
27092716
if (__n < __cap) {
2710-
size_type __old_size = __is_short ? __get_short_size() : __get_long_size();
2711-
if (__n > __old_size)
2712-
__annotate_increase(__n - __old_size);
2713-
pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
2714-
__is_short ? __set_short_size(__n) : __set_long_size(__n);
2717+
if (__n > __size)
2718+
__annotate_increase(__n - __size);
2719+
pointer __p;
2720+
if (__is_short) {
2721+
__p = __get_short_pointer();
2722+
__set_short_size(__n);
2723+
} else {
2724+
__p = __get_long_pointer();
2725+
__set_long_size(__n);
2726+
}
27152727
traits_type::copy(std::__to_address(__p), __s, __n);
27162728
traits_type::assign(__p[__n], value_type());
2717-
if (__old_size > __n)
2718-
__annotate_shrink(__old_size);
2729+
if (__size > __n)
2730+
__annotate_shrink(__size);
27192731
} else {
2720-
size_type __sz = __is_short ? __get_short_size() : __get_long_size();
2721-
__grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
2732+
__grow_by_and_replace(__cap - 1, __n - __cap + 1, __size, 0, __size, __n, __s);
27222733
}
27232734
return *this;
27242735
}
27252736

27262737
template <class _CharT, class _Traits, class _Allocator>
27272738
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
27282739
basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s, size_type __n) {
2729-
size_type __cap = capacity();
2740+
const auto __cap = capacity();
2741+
const auto __size = size();
27302742
if (__cap >= __n) {
2731-
size_type __old_size = size();
2732-
if (__n > __old_size)
2733-
__annotate_increase(__n - __old_size);
2743+
if (__n > __size)
2744+
__annotate_increase(__n - __size);
27342745
value_type* __p = std::__to_address(__get_pointer());
27352746
traits_type::move(__p, __s, __n);
27362747
return __null_terminate_at(__p, __n);
27372748
} else {
2738-
size_type __sz = size();
2739-
__grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s);
2749+
__grow_by_and_replace(__cap, __n - __cap, __size, 0, __size, __n, __s);
27402750
return *this;
27412751
}
27422752
}
@@ -2754,8 +2764,7 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
27542764
size_type __cap = capacity();
27552765
size_type __old_size = size();
27562766
if (__cap < __n) {
2757-
size_type __sz = size();
2758-
__grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
2767+
__grow_by_without_replace(__cap, __n - __cap, __old_size, 0, __old_size);
27592768
__annotate_increase(__n);
27602769
} else if (__n > __old_size)
27612770
__annotate_increase(__n - __old_size);
@@ -2767,10 +2776,10 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
27672776
template <class _CharT, class _Traits, class _Allocator>
27682777
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
27692778
basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) {
2770-
pointer __p;
27712779
size_type __old_size = size();
27722780
if (__old_size == 0)
27732781
__annotate_increase(1);
2782+
pointer __p;
27742783
if (__is_long()) {
27752784
__p = __get_long_pointer();
27762785
__set_long_size(1);
@@ -2793,8 +2802,8 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
27932802
if (!__is_long()) {
27942803
if (!__str.__is_long()) {
27952804
size_type __old_size = __get_short_size();
2796-
if (__get_short_size() < __str.__get_short_size())
2797-
__annotate_increase(__str.__get_short_size() - __get_short_size());
2805+
if (__old_size < __str.__get_short_size())
2806+
__annotate_increase(__str.__get_short_size() - __old_size);
27982807
__rep_ = __str.__rep_;
27992808
if (__old_size > __get_short_size())
28002809
__annotate_shrink(__old_size);
@@ -2961,10 +2970,9 @@ template <class _CharT, class _Traits, class _Allocator>
29612970
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
29622971
basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) {
29632972
_LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr");
2964-
return __builtin_constant_p(*__s)
2965-
? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s))
2966-
: __assign_external(__s, traits_type::length(__s)))
2967-
: __assign_external(__s);
2973+
if (auto __len = traits_type::length(__s); __builtin_constant_p(__len) && __fits_in_sso(__len))
2974+
return __assign_short(__s, __len);
2975+
return __assign_external(__s);
29682976
}
29692977
// append
29702978

@@ -3036,11 +3044,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu
30363044
}
30373045
if (__sz == __cap) {
30383046
__grow_by_without_replace(__cap, 1, __sz, __sz, 0);
3039-
__annotate_increase(1);
30403047
__is_short = false; // the string is always long after __grow_by
3041-
} else
3042-
__annotate_increase(1);
3043-
pointer __p = __get_pointer();
3048+
}
3049+
__annotate_increase(1);
3050+
pointer __p;
30443051
if (__is_short) {
30453052
__p = __get_short_pointer() + __sz;
30463053
__set_short_size(__sz + 1);
@@ -3424,11 +3431,13 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
34243431

34253432
template <class _CharT, class _Traits, class _Allocator>
34263433
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
3427-
size_type __old_size = size();
3434+
size_type __old_size;
34283435
if (__is_long()) {
3436+
__old_size = __get_long_size();
34293437
traits_type::assign(*__get_long_pointer(), value_type());
34303438
__set_long_size(0);
34313439
} else {
3440+
__old_size = __get_short_size();
34323441
traits_type::assign(*__get_short_pointer(), value_type());
34333442
__set_short_size(0);
34343443
}
@@ -3486,11 +3495,12 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
34863495
_LIBCPP_ASSERT_INTERNAL(__is_long(), "Trying to shrink small string");
34873496

34883497
// We're a long string and we're shrinking into the small buffer.
3498+
const auto __ptr = __get_long_pointer();
3499+
const auto __size = __get_long_size();
3500+
const auto __cap = __get_long_cap();
3501+
34893502
if (__fits_in_sso(__target_capacity)) {
34903503
__annotation_guard __g(*this);
3491-
auto __ptr = __get_long_pointer();
3492-
auto __size = __get_long_size();
3493-
auto __cap = __get_long_cap();
34943504
traits_type::copy(std::__to_address(__get_short_pointer()), std::__to_address(__ptr), __size + 1);
34953505
__set_short_size(__size);
34963506
__alloc_traits::deallocate(__alloc_, __ptr, __cap);
@@ -3501,7 +3511,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
35013511
try {
35023512
# endif // _LIBCPP_HAS_EXCEPTIONS
35033513
__annotation_guard __g(*this);
3504-
auto __size = size();
35053514
auto __allocation = std::__allocate_at_least(__alloc_, __target_capacity + 1);
35063515

35073516
// The Standard mandates shrink_to_fit() does not increase the capacity.
@@ -3513,9 +3522,8 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
35133522
}
35143523

35153524
__begin_lifetime(__allocation.ptr, __allocation.count);
3516-
auto __ptr = __get_long_pointer();
35173525
traits_type::copy(std::__to_address(__allocation.ptr), std::__to_address(__ptr), __size + 1);
3518-
__alloc_traits::deallocate(__alloc_, __ptr, __get_long_cap());
3526+
__alloc_traits::deallocate(__alloc_, __ptr, __cap);
35193527
__set_long_cap(__allocation.count);
35203528
__set_long_pointer(__allocation.ptr);
35213529
# if _LIBCPP_HAS_EXCEPTIONS

0 commit comments

Comments
 (0)