summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/basic_string.h
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits/basic_string.h')
-rw-r--r--libstdc++-v3/include/bits/basic_string.h182
1 files changed, 182 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 886e7e6b19e..7670bace479 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -51,6 +51,11 @@
# include <string_view>
#endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include <bits/ranges_algobase.h> // ranges::copy
+# include <bits/ranges_util.h> // ranges::subrange
+#endif
+
#if __cplusplus > 202302L
# include <charconv>
#endif
@@ -501,6 +506,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NOEXCEPT
{ _S_copy(__p, __k1, __k2 - __k1); }
+#if __glibcxx_ranges_to_container // C++ >= 23
+ // pre: __n == ranges::distance(__rg). __p+[0,__n) is a valid range.
+ template<typename _Rg>
+ static constexpr void
+ _S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
+ {
+ if constexpr (ranges::contiguous_range<_Rg>
+ && is_same_v<ranges::range_value_t<_Rg>, _CharT>)
+ _S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
+ else
+ for (auto&& __e : __rg)
+ traits_type::assign(*__p++, std::forward<decltype(__e)>(__e));
+ }
+#endif
+
_GLIBCXX20_CONSTEXPR
static int
_S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT
@@ -717,6 +737,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__str._M_set_length(0);
}
+#if __glibcxx_ranges_to_container // C++ >= 23
+ /**
+ * @brief Construct a string from a range.
+ * @since C++23
+ */
+ template<__detail::__container_compatible_range<_CharT> _Rg>
+ constexpr
+ basic_string(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+ : basic_string(__a)
+ {
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+ {
+ const auto __n = static_cast<size_type>(ranges::distance(__rg));
+ reserve(__n);
+ _S_copy_range(_M_data(), std::forward<_Rg>(__rg), __n);
+ _M_set_length(__n);
+ }
+ else
+ {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+ push_back(*__first);
+ }
+ }
+#endif
+
/**
* @brief Construct string from an initializer %list.
* @param __l std::initializer_list of characters.
@@ -1526,6 +1573,58 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
append(size_type __n, _CharT __c)
{ return _M_replace_aux(this->size(), size_type(0), __n, __c); }
+#if __glibcxx_ranges_to_container // C++ >= 23
+ /**
+ * @brief Append a range to the string.
+ * @param __rg A range of values that are convertible to `value_type`.
+ * @since C++23
+ *
+ * The range `__rg` is allowed to overlap with `*this`.
+ */
+ template<__detail::__container_compatible_range<_CharT> _Rg>
+ constexpr basic_string&
+ append_range(_Rg&& __rg)
+ {
+ // N.B. __rg may overlap with *this, so we must copy from __rg before
+ // existing elements or iterators referring to *this are invalidated.
+ // e.g. in s.append_range(views::concat(s, str)), rg overlaps s.
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+ {
+ const auto __len = size_type(ranges::distance(__rg));
+
+ // Don't care if this addition wraps around, we check it below:
+ const size_type __newlen = size() + __len;
+
+ if ((capacity() - size()) >= __len)
+ _S_copy_range(_M_data() + size(), std::forward<_Rg>(__rg),
+ __len);
+ else
+ {
+ _M_check_length(0, __len, "basic_string::append_range");
+ basic_string __s(_M_get_allocator());
+ __s.reserve(__newlen);
+ _S_copy_range(__s._M_data() + size(), std::forward<_Rg>(__rg),
+ __len);
+ _S_copy(__s._M_data(), _M_data(), size());
+ if (!_M_is_local())
+ _M_destroy(_M_allocated_capacity);
+ _M_data(__s._M_data());
+ _M_capacity(__s._M_allocated_capacity);
+ __s._M_data(__s._M_local_data());
+ __s._M_length(0);
+ }
+ _M_set_length(__newlen); // adds null-terminator
+ }
+ else
+ {
+ basic_string __s(from_range, std::forward<_Rg>(__rg),
+ _M_get_allocator());
+ append(__s);
+ }
+ return *this;
+ }
+#endif
+
#if __cplusplus >= 201103L
/**
* @brief Append an initializer_list of characters.
@@ -1785,6 +1884,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ return this->replace(begin(), end(), __first, __last); }
#endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+ /**
+ * @brief Assign a range to the string.
+ * @param __rg A range of values that are convertible to `value_type`.
+ * @since C++23
+ *
+ * The range `__rg` is allowed to overlap with `*this`.
+ */
+ template<__detail::__container_compatible_range<_CharT> _Rg>
+ constexpr basic_string&
+ assign_range(_Rg&& __rg)
+ {
+ basic_string __s(from_range, std::forward<_Rg>(__rg),
+ _M_get_allocator());
+ assign(std::move(__s));
+ return *this;
+ }
+#endif
+
#if __cplusplus >= 201103L
/**
* @brief Set value to an initializer_list of characters.
@@ -1934,6 +2052,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ this->replace(__p, __p, __beg, __end); }
#endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+ /**
+ * @brief Insert a range into the string.
+ * @param __rg A range of values that are convertible to `value_type`.
+ * @since C++23
+ *
+ * The range `__rg` is allowed to overlap with `*this`.
+ */
+ template<__detail::__container_compatible_range<_CharT> _Rg>
+ constexpr iterator
+ insert_range(const_iterator __p, _Rg&& __rg)
+ {
+ auto __pos = __p - cbegin();
+
+ if constexpr (ranges::forward_range<_Rg>)
+ if (ranges::empty(__rg))
+ return begin() + __pos;
+
+
+ if (__p == cend())
+ append_range(std::forward<_Rg>(__rg));
+ else
+ {
+ basic_string __s(from_range, std::forward<_Rg>(__rg),
+ _M_get_allocator());
+ insert(__pos, __s);
+ }
+ return begin() + __pos;
+ }
+#endif
+
#if __cplusplus >= 201103L
/**
* @brief Insert an initializer_list of characters.
@@ -2522,6 +2671,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__k1.base(), __k2 - __k1);
}
+#if __glibcxx_ranges_to_container // C++ >= 23
+ /**
+ * @brief Replace part of the string with a range.
+ * @param __rg A range of values that are convertible to `value_type`.
+ * @since C++23
+ *
+ * The range `__rg` is allowed to overlap with `*this`.
+ */
+ template<__detail::__container_compatible_range<_CharT> _Rg>
+ constexpr basic_string&
+ replace_with_range(const_iterator __i1, const_iterator __i2, _Rg&& __rg)
+ {
+ if (__i1 == cend())
+ append_range(std::forward<_Rg>(__rg));
+ else
+ {
+ basic_string __s(from_range, std::forward<_Rg>(__rg),
+ _M_get_allocator());
+ replace(__i1, __i2, __s);
+ }
+ return *this;
+ }
+#endif
+
#if __cplusplus >= 201103L
/**
* @brief Replace range of characters with initializer_list.
@@ -3599,6 +3772,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
typename basic_string<_CharT, _Traits, _Allocator>::size_type,
const _Allocator& = _Allocator())
-> basic_string<_CharT, _Traits, _Allocator>;
+
+#if __glibcxx_ranges_to_container // C++ >= 23
+ template<ranges::input_range _Rg,
+ typename _Allocator = allocator<ranges::range_value_t<_Rg>>>
+ basic_string(from_range_t, _Rg&&, _Allocator = _Allocator())
+ -> basic_string<ranges::range_value_t<_Rg>,
+ char_traits<ranges::range_value_t<_Rg>>,
+ _Allocator>;
+#endif
_GLIBCXX_END_NAMESPACE_CXX11
#endif