Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
inline_string.hpp
Go to the documentation of this file.
1// Copyright 2024, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_STRINGS_INLINE_STRING_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_STRINGS_INLINE_STRING_HPP_
7
8// IWYU pragma: private
9// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
10
11// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
12
13#include "arene/base/algorithm/copy.hpp"
14#include "arene/base/algorithm/fill.hpp"
15#include "arene/base/array/array.hpp"
16#include "arene/base/compare/operators.hpp"
17#include "arene/base/compare/strong_ordering.hpp"
18#include "arene/base/compiler_support/attributes.hpp"
19#include "arene/base/compiler_support/cpp14_inline.hpp"
20#include "arene/base/constraints/constraints.hpp"
21#include "arene/base/contracts/contract.hpp"
22#include "arene/base/detail/exceptions.hpp"
23#include "arene/base/detail/raw_c_string.hpp"
24#include "arene/base/detail/wrapped_iterator.hpp" // IWYU pragma: keep
25#include "arene/base/iterator/distance.hpp"
26#include "arene/base/iterator/reverse_iterator.hpp"
27#include "arene/base/optional/optional.hpp"
28#include "arene/base/stdlib_choice/cstddef.hpp"
29#include "arene/base/stdlib_choice/enable_if.hpp"
30#include "arene/base/stdlib_choice/ignore.hpp"
31#include "arene/base/stdlib_choice/initializer_list.hpp"
32#include "arene/base/stdlib_choice/integral_constant.hpp"
33#include "arene/base/stdlib_choice/iterator_tags.hpp"
34#include "arene/base/stdlib_choice/iterator_traits.hpp"
35#include "arene/base/stdlib_choice/min_value_overload.hpp"
36#include "arene/base/stdlib_choice/numeric_limits.hpp"
37#include "arene/base/stdlib_choice/remove_cv.hpp"
38#include "arene/base/strings/detail/inline_string_std_string_mixin.hpp" // IWYU pragma: keep
39#include "arene/base/strings/null_terminated_string_view.hpp"
40#include "arene/base/strings/string_view.hpp"
41#include "arene/base/type_traits/denotes_range.hpp"
42#include "arene/base/type_traits/iterator_category_traits.hpp"
43#include "arene/base/utility/make_subrange.hpp"
44#include "arene/base/utility/safe_comparisons.hpp"
45// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
46
47// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
48
49namespace arene {
50namespace base {
51
52namespace inline_string_detail {
53
54///
55/// @brief Base class for @c inline_string which detemplatizes functionality not dependent on the buffer size.
56///
57class inline_string_base {
58 public:
59 /// @brief The type used for @c size() and @c length()
60 using size_type = std::size_t;
61
62 protected:
63 /// @brief passkey class for constructing iterators.
64 class iterator_passkey {
65 public:
66 /// @brief The default constructor is explicit to disable construction with just @c {}
67 constexpr explicit iterator_passkey() noexcept = default;
68 };
69
70 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
71 /// @brief Default constructor, protected to prevent slicing
72 constexpr inline_string_base() = default;
73 /// @brief Copy constructor, protected to prevent slicing
74 constexpr inline_string_base(inline_string_base const&) = default;
75 /// @brief Move constructor, protected to prevent slicing
76 constexpr inline_string_base(inline_string_base&&) = default;
77 /// @brief Copy assignment operator, protected to prevent slicing
78 constexpr auto operator=(inline_string_base const&) -> inline_string_base& = default;
79 /// @brief Move assignment operator, protected to prevent slicing
80 constexpr auto operator=(inline_string_base&&) -> inline_string_base& = default;
81 /// @brief Destructor, protected to prevent slicing
82 ~inline_string_base() = default;
83 // parasoft-end-suppress CERT_C-EXP37-a-3
84
85 public:
86 /// @brief The type of the elements contained in the string.
87 using value_type = detail::character;
88 /// @brief The type of a reference to an element in the string.
89 using reference = value_type&;
90 /// @brief The type of a const reference to an element in the string.
91 using const_reference = value_type const&;
92 /// @brief The type of a pointer to an element in the string.
93 using pointer = value_type*;
94 /// @brief The type of a const pointer to an element in the string
95 using const_pointer = value_type const*;
96 /// @brief The non-const iterator type
97 using iterator = ::arene::base::detail::wrapped_iterator<pointer, iterator_passkey>;
98 /// @brief The const iterator type
99 using const_iterator = ::arene::base::detail::wrapped_iterator<const_pointer, iterator_passkey>;
100 /// @brief The type of a non-const reverse iterator
101 using reverse_iterator = ::arene::base::reverse_iterator<iterator>;
102 /// @brief The type of a const reverse iterator
103 using const_reverse_iterator = ::arene::base::reverse_iterator<const_iterator>;
104 /// @brief The difference type between two iterators.
105 using difference_type = typename iterator::difference_type;
106
107 /// @brief Get the length of the string
108 ///
109 /// @return The number of characters in the string, non-inclusive of the null-terminator. Equivalent to
110 /// @c distance(begin(),end())
111 constexpr auto size() const noexcept -> size_type { return string_length_; }
112
113 /// @brief Get the length of the string
114 ///
115 /// @return The same as @c size()
116 constexpr auto length() const noexcept -> size_type { return size(); }
117
118 // parasoft-begin-suppress AUTOSAR-A8_4_7-b-2 "Base class passed by reference to avoid slicing"
119 /// @brief Helper to detemplatize fast_inequality_check to remove uncovered branches for inline_string instantiations.
120 ///
121 /// @tparam SizeType The type used for the size comparison
122 /// @param lhs The left hand size
123 /// @param rhs The right hand size
124 /// @return inequality_heuristic::definitely_not_equal if lhs != rhs
125 /// @return inequality_heuristic::may_be_equal_or_not_equal if lhs == rhs
126 ///
127 static constexpr auto common_fast_inequality_check(inline_string_base const& lhs, string_view const& rhs) noexcept
128 -> inequality_heuristic {
129 return lhs.size() != rhs.size() ? inequality_heuristic::definitely_not_equal
130 : inequality_heuristic::may_be_equal_or_not_equal;
131 }
132 // parasoft-end-suppress AUTOSAR-A8_4_7-b-2
133
134 protected:
135 /// @brief sets the size to a new value
136 ///
137 /// @param new_size the new size to set
138 /// @post @c size() will be @c new_size
139 constexpr void set_size(size_type const new_size) noexcept { string_length_ = new_size; }
140
141 private:
142 /// @brief The current size of the string
143 size_type string_length_{0U};
144};
145
146} // namespace inline_string_detail
147
148// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "False positive: 'generic_ordering_from_three_way_compare' is an
149// interface"
150/// @brief A string type with a fixed maximum capacity, where the data is stored internally without allocations.
151///
152/// @tparam MaxSize the maximum capacity of the string, _not_ including the null terminator. Must be non-zero, and
153/// less than @c std::numeric_limits<difference_type>::max()
154template <std::size_t MaxSize>
155// NOLINTNEXTLINE(hicpp-special-member-functions) provides converting ctors that are equivalent to copy/move.
156class inline_string
157 : public inline_string_detail::inline_string_base
158 , public detail::mixin_at<inline_string<MaxSize>, typename inline_string_detail::inline_string_base::size_type>
159 , inline_string_std_string_mixin<inline_string<MaxSize>>
160 , generic_ordering_from_three_way_compare<inline_string<MaxSize>> {
161 /// @brief Internal type alias for the base class
162 using ordering_base = generic_ordering_from_three_way_compare<inline_string<MaxSize>>;
163
164 // parasoft-begin-suppress AUTOSAR-A3_9_1-b-2 "Returning an int for compatibility with std::string_view"
165 /// @brief The type of comparisons that yield an integer rather than a @c strong_ordering
166 using integral_comparison_result = int;
167 // parasoft-end-suppress AUTOSAR-A3_9_1-b-2
168
169 public:
170 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
171 // side-effects"
172 static_assert(
173 cmp_less(MaxSize, std::numeric_limits<difference_type>::max()),
174 "Must have ability to get difference between iterators"
175 );
176 // parasoft-end-suppress CERT_C-PRE31-c-3
177
178 // member types
179 using typename inline_string_base::size_type;
180 using typename inline_string_base::value_type;
181
182 using typename inline_string_base::const_reference;
183 using typename inline_string_base::reference;
184
185 using typename inline_string_base::const_pointer;
186 using typename inline_string_base::pointer;
187
188 using typename inline_string_base::const_iterator;
189 using typename inline_string_base::const_reverse_iterator;
190 using typename inline_string_base::iterator;
191 using typename inline_string_base::reverse_iterator;
192
193 using inline_string_std_string_mixin<inline_string>::three_way_compare;
194 using inline_string_std_string_mixin<inline_string>::fast_inequality_check;
195
196 // parasoft-begin-suppress AUTOSAR-M11_0_1-a-2 "False positive: this is not 'member data', it is a public property"
197 /// @brief Special marker for element not in string.
198 static constexpr size_type npos{string_view::npos};
199 // parasoft-end-suppress AUTOSAR-M11_0_1-a-2
200
201 /// @brief Use the default destructor
202 ~inline_string() = default;
203
204 /// @brief Default-construct an empty string
205 constexpr inline_string() noexcept = default;
206
207 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
208 /// @brief Default copy construction
209 constexpr inline_string(inline_string const&) = default;
210 // parasoft-end-suppress CERT_C-EXP37-a-3
211
212 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
213 /// @brief Default move construction
214 constexpr inline_string(inline_string&&) = default;
215 // parasoft-end-suppress CERT_C-EXP37-a-3
216
217 // parasoft-begin-suppress AUTOSAR-A7_1_3-a "False positive: const is placed on the right hand side"
218 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
219 // initialize the base class"
220 /// @brief Construct from the provided NUL-terminated string.
221 ///
222 /// @param str The source string
223 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
224 /// @pre @c str must point to a NUL-terminated string, else behavior is undefined.
225 /// @post @c size() is the length of @c str
226 /// @post The content of this string is equivalent to the content of @c str
227 constexpr explicit inline_string(detail::raw_c_string const str) noexcept
228 : inline_string{} {
229 copy_from(str);
230 }
231 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
232 // parasoft-end-suppress AUTOSAR-A7_1_3-a
233
234 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
235 // initialize the base class"
236 /// @brief Construct from the source string literal
237 ///
238 /// @tparam N the size of the source character array. Must be @c <=(MaxLength+1)
239 /// @param str The string to copy from
240 /// @pre @c str must have a NUL terminator somewhere in it
241 /// @post The content of this string compares equal to @c str
242 template <std::size_t N>
243 // NOLINTNEXTLINE(hicpp-avoid-c-arrays, hicpp-explicit-conversions) string literal implementation can safely convert
244 constexpr inline_string(detail::character const (&str)[N]) noexcept
245 : inline_string{} {
246 static_assert(N - 1UL <= MaxSize, "String literal must fit into MaxLength");
247
248 // Like std::string, copy until the first NUL; if there's no NUL, it's not really a string => precondition violation
249 string_view as_view{&str[0], N};
250 auto const first_nul_idx = as_view.find('\0');
251 ARENE_PRECONDITION(first_nul_idx < as_view.size());
252 as_view = as_view.substr(0UL, first_nul_idx);
253
254 // We've just made sure that as_view.size() <= N - 1UL <= MaxSize, so we don't need the checked copy_from
255 copy_from_unchecked(as_view);
256 }
257 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
258
259 // parasoft-begin-suppress AUTOSAR-A7_1_3-a "False positive: const is placed on the right hand side"
260 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
261 // initialize the base class"
262 /// @brief Construct from the provided string_view.
263 ///
264 /// @param str The source string
265 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
266 /// @pre @c str must point to a NUL-terminated string, else behavior is undefined.
267 /// @post @c size() is the length of @c str
268 /// @post The content of this string is equivalent to the content of @c str
269 constexpr explicit inline_string(string_view const str) noexcept
270 : inline_string{} {
271 copy_from(str);
272 }
273 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
274 // parasoft-end-suppress AUTOSAR-A7_1_3-a
275
276 // parasoft-begin-suppress AUTOSAR-A7_1_3-a "False positive: const is placed on the right hand side"
277 /// @brief Attempt to construct from a @c string_view .
278 ///
279 /// @param str The source string.
280 /// @return optional<inline_string> If @c str.size()>MaxLength , a null optional, else an optional populated as if
281 /// via @c inline_string{str} .
282 ///
283 static constexpr auto try_construct(string_view const str) noexcept -> optional<inline_string> {
284 if (str.length() > MaxSize) {
285 return nullopt;
286 }
287 return {inline_string{str}};
288 }
289 // parasoft-end-suppress AUTOSAR-A7_1_3-a
290
291 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
292 // initialize the base class"
293 /// @brief Implicit conversion from another @c inline_string which can provably fit in this @c inline_string.
294 ///
295 /// @tparam OtherMaxLength The length of the other string. Must be @c <= MaxLength
296 /// @param other The other string
297 /// @post @c size()==other.size()
298 /// @post The content of this string is equivalent to the content of @c other
299 template <size_type OtherMaxLength, constraints<std::enable_if_t<(OtherMaxLength <= MaxSize)>> = nullptr>
300 // NOLINTNEXTLINE(hicpp-explicit-conversions) Morally this is a copy-ctor not a conversion
301 constexpr inline_string(inline_string<OtherMaxLength> const& other) noexcept
302 : inline_string{} {
303 copy_from(other);
304 }
305 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
306
307 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
308 // initialize the base class"
309 /// @brief Explicit conversion from another @c inline_string which cannot provably fit in this @c inline_string.
310 ///
311 /// @tparam OtherMaxLength The length of the other string
312 /// @param other The other string
313 /// @pre @c other.size() is less than or equal to @c MaxLength else @c ARENE_PRECONDITION violation
314 /// @post @c size()==other.size()
315 /// @post The content of this string is equivalent to the content of @c other
316 template <size_type OtherMaxLength, constraints<std::enable_if_t<(OtherMaxLength > MaxSize)>> = nullptr>
317 constexpr explicit inline_string(inline_string<OtherMaxLength> const& other) noexcept
318 : inline_string{} {
319 copy_from(other);
320 }
321 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
322
323 // parasoft-begin-suppress AUTOSAR-A12_1_1-a "False positive: This constructor delegates to another, which does
324 // initialize the base class"
325
326 /// @brief Construct a pre-filled @c inline_string of a given length.
327 ///
328 /// @param len The length of the constructed string.
329 /// @param chr The character to fill the string.
330 /// @pre @c len must be less than or equal to @c MaxLength , else @c ARENE_PRECONDITION violation.
331 /// @post @c size() is equal to @c len .
332 /// @post This string is filled with @c chr .
333 constexpr inline_string(size_type len, detail::character chr) noexcept
334 : inline_string{} {
335 resize(len, chr);
336 }
337
338 // parasoft-end-suppress AUTOSAR-A12_1_1-a
339
340 /// @brief Attempt to construct from another @c inline_string with a capacity that is less than or equal to the
341 /// capacity of this.
342 ///
343 /// @tparam OtherMaxSize The capacity of the other string
344 /// @param str The source string.
345 /// @return If @c str.size()>MaxLength , a null optional, else an optional populated as if via @c inline_string{str} .
346 template <size_type OtherMaxSize, constraints<std::enable_if_t<(OtherMaxSize <= MaxSize)>> = nullptr>
347 static constexpr auto try_construct(inline_string<OtherMaxSize> const& str) noexcept -> optional<inline_string> {
348 return {inline_string{str}};
349 }
350 /// @brief Attempt to construct from another @c inline_string with a larger capacity.
351 ///
352 /// @tparam OtherMaxSize The capacity of the other string
353 /// @param str The source string.
354 /// @return If @c str.size()>MaxLength , a null optional, else an optional populated as if via @c inline_string{str} .
355 template <size_type OtherMaxSize, constraints<std::enable_if_t<(OtherMaxSize > MaxSize)>> = nullptr>
356 static constexpr auto try_construct(inline_string<OtherMaxSize> const& str) noexcept -> optional<inline_string> {
357 if (str.length() > MaxSize) {
358 return nullopt;
359 }
360 return {inline_string{str}};
361 }
362
363 // parasoft-begin-suppress AUTOSAR-A12_1_1-a-2 "False positive: This constructor delegates to another, which does
364 // initialize the base class"
365 /// @brief Construction from a sequence of characters represented as a pair of iterators.
366 ///
367 /// @tparam InputIterator The type of the iterators
368 /// @param first The start of the iterator range
369 /// @param last The end of the iterator range
370 /// @pre @c std::distance(first,last)<=MaxSize else @c ARENE_PRECONDITION violation.
371 template <typename InputIterator, constraints<std::enable_if_t<is_input_iterator_v<InputIterator>>> = nullptr>
372 constexpr explicit inline_string(
373 InputIterator const first,
374 InputIterator const last
375 ) noexcept(denotes_nothrow_iterable_range_v<InputIterator>)
376 : inline_string{} {
377 copy_from(typename std::iterator_traits<InputIterator>::iterator_category{}, first, last);
378 }
379 // parasoft-end-suppress AUTOSAR-A12_1_1-a-2
380
381 /// @brief Attempt to construct from a sequence of characters.
382 ///
383 /// @param first An iterator referring to the start of the source string
384 /// @param last An iterator referring to the end of the source string
385 /// @return optional<inline_string> If the length of the range is greater than @c MaxLength , a null optional, else an
386 /// optional populated with the elements in the range @c [first,last) .
387 ///
388 template <typename InputIterator, constraints<std::enable_if_t<is_input_iterator_v<InputIterator>>> = nullptr>
389 static constexpr auto
390 try_construct(InputIterator first, InputIterator last) noexcept(denotes_nothrow_iterable_range_v<InputIterator>)
391 -> optional<inline_string> {
392 return inline_string::do_try_construct(
393 typename std::iterator_traits<InputIterator>::iterator_category{},
394 first,
395 last
396 );
397 }
398
399 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
400 /// @brief Default copy assignment
401 /// @return A reference to @c *this
402 constexpr auto operator=(inline_string const&) -> inline_string& = default;
403 // parasoft-end-suppress CERT_C-EXP37-a-3
404
405 // parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
406 /// @brief Default move assignment
407 /// @return A reference to @c *this
408 constexpr auto operator=(inline_string&&) -> inline_string& = default;
409 // parasoft-end-suppress CERT_C-EXP37-a-3
410
411 /// @brief Assign from a string_view.
412 ///
413 /// @param str The source string
414 /// @return inline_string& @c *this
415 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
416 /// @post @c size() is the length of @c str
417 /// @post The content of this string is equivalent to the content of @c str
418 constexpr auto operator=(string_view str) noexcept -> inline_string& {
419 copy_from(str);
420 return *this;
421 }
422
423 /// @brief Assign from a nul-terminated string
424 ///
425 /// @param str The source string
426 /// @return inline_string& @c *this
427 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
428 /// @pre @c str must point to a NUL-terminated string, else behavior is undefined.
429 /// @post @c size() is the length of @c str
430 /// @post The content of this string is equivalent to the content of @c str
431 constexpr auto operator=(detail::raw_c_string str) noexcept -> inline_string& {
432 copy_from(str);
433 return *this;
434 }
435
436 /// @brief Assign from an initializer list.
437 ///
438 /// @param str The source string
439 /// @return inline_string& @c *this
440 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
441 /// @post @c size() is the length of @c str
442 /// @post The content of this string is equivalent to the content of @c str
443 constexpr auto operator=(std::initializer_list<detail::character> str) noexcept -> inline_string& {
444 copy_from(string_view(str.begin(), str.size()));
445 return *this;
446 }
447
448 /// @brief Assign from a single character
449 ///
450 /// @param chr The source character
451 /// @return inline_string& @c *this
452 /// @post @c size() is @c 1
453 /// @post The content of this string is @c chr
454 constexpr auto operator=(detail::character chr) noexcept -> inline_string& {
455 copy_from_unchecked(string_view(&chr, 1U));
456 return *this;
457 }
458
459 /// @brief Assign from another string.
460 ///
461 /// @tparam OtherMaxLength the max length of the other string
462 /// @param other The source string
463 /// @return inline_string& @c *this
464 /// @pre @c other.size() is less than or equal to @c MaxLength else @c ARENE_PRECONDITION violation
465 /// @post @c size()==other.size()
466 /// @post The content of this string is equivalent to the content of @c other
467 template <std::size_t OtherMaxLength>
468 constexpr auto operator=(inline_string<OtherMaxLength> const& other) noexcept -> inline_string& {
469 copy_from(other);
470 return *this;
471 }
472
473 /// @brief Assign from a string_view.
474 ///
475 /// @param str The source string
476 /// @return inline_string& @c *this
477 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
478 /// @post @c size() is the length of @c str
479 /// @post The content of this string is equivalent to the content of @c str
480 constexpr auto assign(string_view str) noexcept -> inline_string& { return *this = str; }
481
482 /// @brief Assign from a string_view.
483 ///
484 /// @param str The source string
485 /// @param pos The offset in @c str of the substring to assign
486 /// @return inline_string& @c *this
487 /// @pre @c str.substr(pos).size() must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
488 /// @post @c size() is @c str.substr(pos).size()
489 /// @post The content of this string is equivalent to the content of @c str.substr(pos)
490 constexpr auto assign(string_view str, size_type pos) noexcept -> inline_string& { return assign(str.substr(pos)); }
491
492 /// @brief Assign from a substring of a string_view starting at the specified position, with the specified max length.
493 ///
494 /// @param str The source string
495 /// @param pos The offset in @c str of the substring to assign
496 /// @param count The maximum number of characters in the substring
497 /// @return inline_string& @c *this
498 /// @pre @c str.substr(pos,count).size() must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
499 /// @post @c size() is @c str.substr(pos).size()
500 /// @post The content of this string is equivalent to the content of @c str.substr(pos,count)
501 constexpr auto assign(string_view str, size_type pos, size_type count) noexcept -> inline_string& {
502 return assign(str.substr(pos, count));
503 }
504
505 /// @brief Assign from an initializer list of characters.
506 ///
507 /// @param str The source initializer list
508 /// @return inline_string& @c *this
509 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
510 /// @post @c size() is the length of @c str
511 /// @post The content of this string is equivalent to the content of @c str
512 constexpr auto assign(std::initializer_list<detail::character> str) noexcept -> inline_string& { return *this = str; }
513
514 /// @brief Assign from a string specified as pointer and length to the current string.
515 ///
516 /// @param str The start if the string to assign
517 /// @param count The number of characters in the string to assign
518 /// @return inline_string& @c *this
519 /// @pre str must not be @c nullptr , else @c ARENE_PRECONDITION violation.
520 /// @pre str must be a null-terminated string, else behavior is undefined.
521 /// @pre count must be less than the length of @c str, else behavior is undefined.
522 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
523 /// @post @c size() is the length of @c str
524 /// @post The content of this string is equivalent to the content of @c str
525 constexpr auto assign(detail::raw_c_string str, size_type count) noexcept -> inline_string& {
526 return assign(string_view{str, count});
527 }
528
529 /// @brief Assign from a single character
530 ///
531 /// @param chr The source character
532 /// @return inline_string& @c *this
533 /// @post @c size() is @c 1
534 /// @post The content of this string is @c chr
535 constexpr auto assign(detail::character chr) noexcept -> inline_string& { return *this = chr; }
536
537 /// @brief Assign repeated copies of a single character
538 ///
539 /// @param count The number of times to repeat the character
540 /// @param chr The source character
541 /// @return inline_string& @c *this
542 /// @pre @c count<=MaxLength , else @c ARENE_PRECONDITION violation.
543 constexpr auto assign(size_type count, detail::character chr) noexcept -> inline_string& {
544 ARENE_PRECONDITION(count <= MaxSize);
545 clear();
546 resize(count, chr);
547 return *this;
548 }
549
550 /// @brief Insert the supplied string at the specified position.
551 ///
552 /// @param pos The insertion position
553 /// @param str The string to insert
554 /// @return inline_string& @c *this
555 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
556 /// @pre @c pos+str.length()<max_size() , else @c ARENE_PRECONDITION violation.
557 /// @post @c size() is increased by @c str.size() .
558 /// @post @c str is inserted at @c pos
559 constexpr auto insert(size_type pos, string_view str) noexcept -> inline_string& {
560 std::ignore = ::arene::base::copy(str.begin(), str.end(), prepare_insert(pos, str.size()));
561 return *this;
562 }
563
564 /// @brief Insert the substring of the supplied string starting from @c pos2 at @c pos1.
565 ///
566 /// @param pos1 The insertion position
567 /// @param str The string holding the substring to insert
568 /// @param pos2 The position of the start of the substring to insert. If @c >=str.size(), this is a no-op.
569 /// @return inline_string& @c *this
570 /// @pre @c pos1<=size() else @c ARENE_PRECONDITION violation.
571 /// @pre @c pos1+(str.length()-pos2)<max_size() , else @c ARENE_PRECONDITION violation.
572 /// @post @c size() is increased by @c (str.size()-pos2) .
573 /// @post The range @c [str.begin()+pos2,str.end()) is inserted at @c pos1
574 constexpr auto insert(size_type pos1, string_view str, size_type pos2) noexcept -> inline_string& {
575 return insert(pos1, str.substr(pos2));
576 }
577
578 /// @brief Insert the substring of the supplied string of max length @c length2 starting from @c pos2 at @c pos1.
579 ///
580 /// @param pos1 The insertion position
581 /// @param str The string holding the substring to insert
582 /// @param pos2 The position of the start of the substring to insert. If @c >=str.size(), this is a no-op.
583 /// @param length2 The maximum length of the substring to insert
584 /// @return inline_string& @c *this
585 /// @pre @c pos1<=size() else @c ARENE_PRECONDITION violation.
586 /// @pre @c pos1+min(length2,str.size()-pos2)<max_size() , else @c ARENE_PRECONDITION violation.
587 /// @post @c size() is increased by @c min(length2,str.size()-pos2) .
588 /// @post The range @c [str.begin()+pos2,str.begin()+min(length2,str.size()-pos2)) is inserted at @c pos1
589 constexpr auto insert(size_type pos1, string_view str, size_type pos2, size_type length2) noexcept -> inline_string& {
590 return insert(pos1, str.substr(pos2, length2));
591 }
592
593 /// @brief Insert the string of @c count characters starting at @c str at @c pos
594 ///
595 /// @param pos The insertion position
596 /// @param str The start of the string to insert
597 /// @param count The length of the string to insert
598 /// @return inline_string& @c *this
599 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
600 /// @pre @c pos+count<max_size() , else @c ARENE_PRECONDITION violation.
601 /// @pre @c str+count must be in the valid range of @c str else behavior is undefined.
602 /// @post @c size() is increased by @c count .
603 /// @post @c str is inserted at @c pos
604 constexpr auto insert(size_type pos, detail::raw_c_string str, size_type count) noexcept -> inline_string& {
605 return insert(pos, string_view{str, count});
606 }
607
608 /// @brief Insert @c count copies of the specified character starting at position @c pos
609 ///
610 /// @param pos The insertion position
611 /// @param count The number of times to insert the character
612 /// @param chr The character to insert
613 /// @return inline_string& @c *this
614 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
615 /// @pre @c pos+count<max_size() , else @c ARENE_PRECONDITION violation.
616 /// @post @c size() is increased by @c count .
617 /// @post @c count copies of @c chr are inserted beginning at @c pos
618 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
619 constexpr auto insert(size_type pos, size_type count, detail::character chr) noexcept -> inline_string& {
620 auto const insert_begin = prepare_insert(pos, count);
621 ::arene::base::fill(insert_begin, insert_begin + static_cast<difference_type>(count), chr);
622 return *this;
623 }
624
625 /// @brief Insert the specified character starting at position @c pos
626 ///
627 /// @param pos The insertion position
628 /// @param chr The character to insert
629 /// @return iterator An iterator referring to the inserted character
630 /// @pre @c pos must be a valid iterator into @c *this else behavior is undefined.
631 /// @pre @c size()+1<max_size() , else @c ARENE_PRECONDITION violation.
632 /// @post @c size() is increased by @c 1 .
633 /// @post @c chr is inserted at @c pos
634 constexpr auto insert(const_iterator pos, detail::character chr) noexcept -> iterator { return insert(pos, 1U, chr); }
635
636 /// @brief Insert @c count copies of a character into the string at the specified position.
637 ///
638 /// @param pos An iterator representing the position to insert
639 /// @param count The number of times to insert the character
640 /// @param chr The character to insert
641 /// @return iterator An iterator referring to the start of the sequence of inserted characters.
642 /// @pre @c pos must be a valid iterator into @c *this else behavior is undefined.
643 /// @pre @c pos+count<max_size() , else @c ARENE_PRECONDITION violation.
644 /// @post @c size() is increased by @c count .
645 /// @post @c count copies of @c chr are inserted beginning at @c pos
646 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
647 constexpr auto insert(const_iterator pos, size_type count, detail::character chr) noexcept -> iterator {
648 auto const offset = pos - cbegin();
649 std::ignore = insert(static_cast<size_type>(offset), count, chr);
650 return begin() + offset;
651 }
652
653 /// @brief Insert a series of characters into the string at the specified position.
654 ///
655 /// @param pos An iterator representing the position to insert
656 /// @param chars The characters to insert
657 /// @return iterator An iterator referring to the start of the sequence of inserted characters.
658 /// @pre @c pos must be a valid iterator into @c *this else behavior is undefined.
659 /// @pre @c pos+chars.size()<max_size() , else @c ARENE_PRECONDITION violation.
660 /// @post @c size() is increased by @c chars.size() .
661 /// @post @c chars are inserted beginning at @c pos
662 constexpr auto insert(const_iterator pos, std::initializer_list<detail::character> chars) noexcept -> iterator {
663 auto const offset = pos - cbegin();
664 std::ignore = insert(static_cast<size_type>(offset), string_view{chars.begin(), chars.size()});
665 return begin() + offset;
666 }
667
668 /// @brief Insert a series of characters from an iterator range into the string at the specified position.
669 ///
670 /// @tparam InputIterator The type of the input iterator.
671 /// @param pos An iterator representing the position to insert
672 /// @param first The start of the input range
673 /// @param last The end of the input range
674 /// @return iterator An iterator referring to the start of the sequence of inserted characters.
675 /// @pre @c size()+std::distance(first,last)<=max_size() else @c ARENE_PRECONDITION violation.
676 /// @pre @c pos must be a valid iterator into @c *this
677 /// @pre @c InputIterator must be an input iterator
678 /// @pre @c first and @c last must form a valid iterator range
679 template <typename InputIterator, constraints<std::enable_if_t<base::is_input_iterator_v<InputIterator>>> = nullptr>
680 constexpr auto insert(
681 const_iterator pos,
682 InputIterator first,
683 InputIterator last
684 ) noexcept(denotes_nothrow_iterable_range_v<InputIterator>) -> iterator {
685 return do_insert(typename std::iterator_traits<InputIterator>::iterator_category{}, pos, first, last);
686 }
687
688 /// @brief Erase all the characters in the string.
689 /// @return inline_string& @c *this
690 constexpr auto erase() noexcept -> inline_string& {
691 clear();
692 return *this;
693 }
694
695 /// @brief Erase characters from the string starting at the specified position to the end of the string
696 /// @param pos The position of the first character to remove. If @c >=size() is a noop.
697 /// @return inline_string& @c *this
698 /// @post If @c pos<size() , @c size() is reduced by the difference between the original @c size() and @c pos .
699 constexpr auto erase(size_type pos) -> inline_string& {
700 // This can wrap around if pos > size(), but in that case the body of 2-arg erase will be skipped.
701 return erase(pos, this->size() - pos);
702 }
703
704 /// @brief Erase the specified number of characters in the string starting at the specified position.
705 ///
706 /// @param pos The position of the characters to remove. If @c pos>=size() this is a noop.
707 /// @param count The maximum number of characters to remove.
708 /// @return inline_string& @c *this
709 /// @post If @c pos<size() , then @c size() is reduced by @c min(count,size()-pos) .
710 /// @post If @c pos<size() , then the characters in the range @c [pos,min(size(),count+size())) are removed, and the
711 /// characters in the range [min(size(),count+size()),size()) are moved to be located starting at @c pos .
712 constexpr auto erase(size_type pos, size_type count) noexcept -> inline_string& {
713 if (pos < this->size()) {
714 count = std::min(count, this->size() - pos);
715 // From here, pos < size(), count <= size(), and pos + count <= size()
716 size_type const erase_end{pos + count};
717 std::ignore = ::arene::base::copy(
718 begin() + static_cast<difference_type>(erase_end),
719 end(),
720 begin() + static_cast<difference_type>(pos)
721 );
722 set_null_terminator_to(this->size() - count);
723 }
724
725 return *this;
726 }
727
728 /// @brief Erase the character at the specified range.
729 /// @pre @c pos must be a valid iterator into the current string
730 /// @param pos The iterator referring to the character to erase
731 /// @return An iterator referring to the character after the removed range,
732 /// or @c end() if there is no such character
733 constexpr auto erase(const_iterator pos) noexcept -> iterator {
734 auto const offset = pos - cbegin();
735 ARENE_PRECONDITION((offset >= 0) && (static_cast<size_type>(offset) <= this->size()));
736 std::ignore = erase(static_cast<size_type>(offset), 1U);
737 return begin() + offset;
738 }
739
740 /// @brief Erase the characters in the specified range.
741 /// @pre @c first and @c last must form a valid iterator range into the
742 /// current string
743 /// @param first The start of the range
744 /// @param last The end of the range
745 /// @return An iterator referring to the character after the removed range,
746 /// or @c end() if there is no such character
747 constexpr auto erase(const_iterator first, const_iterator last) noexcept -> iterator {
748 ARENE_PRECONDITION(last >= first);
749 auto const offset = first - cbegin();
750 ARENE_PRECONDITION(offset >= 0);
751 std::ignore = erase(static_cast<size_type>(offset), static_cast<size_type>(last - first));
752 return begin() + offset;
753 }
754
755 /// @brief Replace a substring with another string.
756 ///
757 /// @param pos The start of the substring to replace.
758 /// @param count The length of the substring to replace
759 /// @param str The string to replace the substring with
760 /// @return inline_string& @c *this
761 /// @post The characters in the range @c [pos,std::min(pos+count,size())) are replaced by the characters in @c str .
762 /// @post If @c count<str.size() , then the remaining characters from @c str are inserted at the position equivalent
763 /// to @c pos+count .
764 /// @post If @c count<str.size(), then @c size() will increase by the difference.
765 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
766 /// @pre If @c count<str.size(), then @c size()+(str.size()-count)<=max_size() else @c ARENE_PRECONDITION violation.
767 constexpr auto replace(size_type pos, size_type count, string_view str) noexcept -> inline_string& {
768 prepare_replace(pos, count, str.length());
769 std::ignore = ::arene::base::copy(str.begin(), str.end(), begin() + static_cast<difference_type>(pos));
770 return *this;
771 }
772
773 /// @brief Replace a substring with another substring.
774 ///
775 /// @param pos The start of the substring to replace.
776 /// @param count The length of the substring to replace
777 /// @param str The string to replace the substring with
778 /// @param pos2 The offset into @c str to start the replacement string. If @c pos2>str.size() , this is a no-op.
779 /// @return inline_string& @c *this
780 /// @post The characters in the range @c [pos,std::min(pos+count,size())) are replaced by the characters in the range
781 /// @c [pos2,str.size()) .
782 /// @post If @c count<(str.size()-pos2) , then the remaining characters from @c str are inserted at the position
783 /// equivalent to @c pos+count .
784 /// @post If @c count<(str.size()-pos2) , then @c size() will increase by the difference.
785 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
786 /// @pre If @c count<(str.size()-pos2), then @c size()+(str.size()-pos2-count)<=max_size() else @c ARENE_PRECONDITION
787 /// violation.
788 constexpr auto replace(size_type pos, size_type count, string_view str, size_type pos2) noexcept -> inline_string& {
789 return replace(pos, count, str.substr(pos2));
790 }
791
792 /// @brief Replace a substring with another substring.
793 ///
794 /// @param pos The start of the substring to replace.
795 /// @param count The length of the substring to replace
796 /// @param str The string to replace the substring with
797 /// @param pos2 The offset into @c str to start the replacement string. If @c pos2>str.size() , this is a no-op.
798 /// @param count2 The count into @c str to cap the replacement.
799 /// @return inline_string& @c *this
800 /// @post The characters in the range @c [pos,std::min(pos+count,size())) are replaced by the characters in the range
801 /// @c [pos2,std::min(count2,str.size())) .
802 /// @post If @c count<(std::min(count2,str.size())-pos2) , then the remaining characters from @c str are inserted at
803 /// the position equivalent to @c pos+count .
804 /// @post If @c count<(std::min(count2,str.size())-pos2) , then @c size() will increase by the difference.
805 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
806 /// @pre If @c count<(std::min(count2,str.size())-pos2), then @c size()+(str.size()-pos2-count)<=max_size() else
807 /// @c ARENE_PRECONDITION violation.
808 constexpr auto replace(size_type pos, size_type count, string_view str, size_type pos2, size_type count2) noexcept
809 -> inline_string& {
810 return replace(pos, count, str.substr(pos2, count2));
811 }
812
813 /// @brief Replace a substring with a c-string.
814 ///
815 /// @param pos The start of the substring to replace.
816 /// @param count The length of the substring to replace
817 /// @param str The string to replace the substring with
818 /// @param count2 The count into @c str to cap the replacement.
819 /// @return inline_string& @c *this
820 /// @post The characters in the range @c [pos,std::min(pos+count,size())) are replaced by the characters in the range
821 /// @c [str,str+count) .
822 /// @post If @c count<count2 , then the remaining characters from @c str are inserted at
823 /// the position equivalent to @c pos+count .
824 /// @post If @c count<count2 , then @c size() will increase by the difference.
825 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
826 /// @pre @c str+count must be in the valid range of @c str else behavior is undefined.
827 /// @pre If @c count<count2, then @c size()+(count2-count)<=max_size() else @c ARENE_PRECONDITION violation.
828 constexpr auto replace(size_type pos, size_type count, detail::raw_c_string str, size_type count2) noexcept
829 -> inline_string& {
830 return replace(pos, count, string_view{str, count2});
831 }
832
833 /// @brief Replace a substring with repeated copies of a given character.
834 ///
835 /// @param pos The start of the substring to replace.
836 /// @param count The length of the substring to replace
837 /// @param count2 The number of characters to fill.
838 /// @param chr The character to fill with.
839 /// @return inline_string& @c *this
840 /// @post The characters in the range @c [pos,std::min(pos+count,size())) are replaced by @c count2 copies of chr
841 /// @post If @c count<count2 , then the remaining copies of @c chr are inserted at the position equivalent
842 /// to @c pos+count , and @c size() will increase by the difference
843 /// @post If @c count>count2 , then the remaining characters in the replacement range will be erased, and @c size()
844 /// will decrease by the difference.
845 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
846 /// @pre If @c count<count2, then @c size()+(count2-count)<=max_size() else @c ARENE_PRECONDITION violation.
847 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
848 constexpr auto replace(size_type pos, size_type count, size_type count2, detail::character chr) noexcept
849 -> inline_string& {
850 prepare_replace(pos, count, count2);
851 auto const fill_begin = begin() + static_cast<difference_type>(pos);
852 ::arene::base::fill(fill_begin, fill_begin + static_cast<difference_type>(count2), chr);
853 return *this;
854 }
855
856 /// @brief Replace a substring with another string.
857 ///
858 /// @param first The start of the substring to replace.
859 /// @param last The end of the substring to replace
860 /// @param str The string to replace the substring with
861 /// @return inline_string& @c *this
862 /// @post The characters in the range @c [first,last) are replaced by the characters in @c str .
863 /// @post If @c std::distance(first,last)<str.size() , then the remaining characters from @c str are inserted
864 /// at @c last , and @c size() will increase by the difference.
865 /// @post If @c std::distance(first,last)>str.size(), then the remain characters from @c [first,last) are erased and
866 /// @c size() will decrease by the difference.
867 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
868 /// @pre Let @c dist=std::distance(first,last) ; if @c dist<str.size(), then
869 /// @c size()+(str.size()-dist)<=max_size() else @c ARENE_PRECONDITION violation.
870 constexpr auto replace(const_iterator first, const_iterator last, string_view str) noexcept -> inline_string& {
871 ARENE_PRECONDITION(last >= first);
872 auto const offset = first - cbegin();
873 ARENE_PRECONDITION(offset >= 0);
874 return replace(static_cast<size_type>(offset), static_cast<size_type>(last - first), str);
875 }
876
877 /// @brief Replace a substring with another substring.
878 ///
879 /// @param first The start of the substring to replace.
880 /// @param last The end of the substring to replace
881 /// @param str The string to replace the substring with
882 /// @param pos The offset into @c str to start the replacement string. If @c pos>str.size() , this is a no-op.
883 /// @return inline_string& @c *this
884 /// @post The characters in the range @c [first,last) are replaced by the characters in the
885 /// range @c [str.begin()+pos,str.end()) .
886 /// @post If @c std::distance(first,last)<(str.size()-pos) , then the remaining characters from @c str are inserted
887 /// at @c last , and @c size() will increase by the difference.
888 /// @post If @c std::distance(first,last)>(str.size()-pos), then the remain characters from @c [first,last) are erased
889 /// and @c size() will decrease by the difference.
890 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
891 /// @pre Let @c dist=std::distance(first,last) ; if @c dist<(str.size()-pos), then
892 /// @c size()+(str.size()-pos-dist)<=max_size() else @c ARENE_PRECONDITION violation.
893 constexpr auto replace(const_iterator first, const_iterator last, string_view str, size_type pos) noexcept
894 -> inline_string& {
895 return replace(first, last, str.substr(pos));
896 }
897
898 /// @brief Replace a substring with another substring.
899 ///
900 /// @param first The start of the substring to replace.
901 /// @param last The end of the substring to replace
902 /// @param str The string to replace the substring with
903 /// @param pos The offset into @c str to start the replacement string. If @c pos>str.size() , this is a no-op.
904 /// @param count The count into @c str to cap the replacement.
905 /// @return inline_string& @c *this
906 /// @post The characters in the range @c [first,last) are replaced by the characters in the
907 /// range @c [str.begin()+pos,str.begin()+std::min(str.size(),count)) .
908 /// @post If @c std::distance(first,last)<std::min(str.size()-pos,count) , then the remaining characters from @c str
909 /// are inserted at @c last , and @c size() will increase by the difference.
910 /// @post If @c std::distance(first,last)>std::min(str.size()-pos,count), then the remain characters from
911 /// @c [first,last) are erased and @c size() will decrease by the difference.
912 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
913 /// @pre Let @c dist=std::distance(first,last) and @c length=std::min(str.size()-pos,count) ;
914 /// if @c dist<length, then @c size()+(length-dist)<=max_size() else @c ARENE_PRECONDITION violation.
915 constexpr auto
916 replace(const_iterator first, const_iterator last, string_view str, size_type pos, size_type count) noexcept
917 -> inline_string& {
918 return replace(first, last, str.substr(pos, count));
919 }
920
921 /// @brief Replace a substring with a c-string.
922 ///
923 /// @param first The start of the substring to replace.
924 /// @param last The end of the substring to replace
925 /// @param str The string to replace the substring with
926 /// @param count The count into @c str to cap the replacement.
927 /// @return inline_string& @c *this
928 /// @post The characters in the range @c [first,last) are replaced by the characters in the
929 /// range @c [str+pos,str+count) .
930 /// @post If @c std::distance(first,last)<count , then the remaining characters from @c str
931 /// are inserted at @c last , and @c size() will increase by the difference.
932 /// @post If @c std::distance(first,last)>count, then the remain characters from
933 /// @c [first,last) are erased and @c size() will decrease by the difference.
934 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
935 /// @pre @c str+count must be in the valid range of @c str else behavior is undefined.
936 /// @pre Let @c dist=std::distance(first,last) ; if @c dist<count, then @c size()+(count-dist)<=max_size() else
937 /// @c ARENE_PRECONDITION violation.
938 constexpr auto replace(const_iterator first, const_iterator last, detail::raw_c_string str, size_type count) noexcept
939 -> inline_string& {
940 return replace(first, last, string_view{str, count});
941 }
942
943 /// @brief Replace a substring with repeated copies of a character.
944 ///
945 /// @param first The start of the substring to replace.
946 /// @param last The end of the substring to replace
947 /// @param count The count into @c str to cap the replacement.
948 /// @param chr The character to fill with.
949 /// @return inline_string& @c *this
950 /// @post The characters in the range @c [first,last) are replaced by @c count repeated copies of @c chr
951 /// @post If @c std::distance(first,last)<count , then the remaining characters are inserted at @c last , and
952 /// @c size() will increase by the difference.
953 /// @post If @c std::distance(first,last)>count, then the remain characters from @c [first,last) are erased and
954 /// @c size() will decrease by the difference.
955 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
956 /// @pre Let @c dist=std::distance(first,last) ; if @c dist<count, then @c size()+(count-dist)<=max_size() else
957 /// @c ARENE_PRECONDITION violation.
958 constexpr auto replace(const_iterator first, const_iterator last, size_type count, detail::character chr) noexcept
959 -> inline_string& {
960 ARENE_PRECONDITION(last >= first);
961 auto const offset = first - cbegin();
962 ARENE_PRECONDITION(offset >= 0);
963 return replace(static_cast<size_type>(offset), static_cast<size_type>(last - first), count, chr);
964 }
965
966 /// @brief Replace a substring with a sequence of characters.
967 ///
968 /// @param first The start of the substring to replace.
969 /// @param last The end of the substring to replace
970 /// @param chars the sequence of characters to replace
971 /// @return inline_string& @c *this
972 /// @post The characters in the range @c [first,last) are replaced by the characters from @c chars
973 /// @post If @c std::distance(first,last)<chars.size() , then the remaining characters from @c chars
974 /// are inserted at @c last , and @c size() will increase by the difference.
975 /// @post If @c std::distance(first,last)>chars.size(), then the remain characters from
976 /// @c [first,last) are erased and @c size() will decrease by the difference.
977 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
978 /// @pre Let @c dist=std::distance(first,last) ; if @c dist<chars.size(), then @c size()+(str.size()-dist)<=max_size()
979 /// else @c ARENE_PRECONDITION violation.
980 constexpr auto
981 replace(const_iterator first, const_iterator last, std::initializer_list<detail::character> chars) noexcept
982 -> inline_string& {
983 return replace(first, last, string_view{chars.begin(), chars.size()});
984 }
985
986 /// @brief Replace a substring with another substring.
987 ///
988 /// @tparam InputIterator The iterator type
989 /// @param first The start of the substring to replace.
990 /// @param last The end of the substring to replace
991 /// @param first2 The start of the substring to replace the substring with
992 /// @param last2 The end of the substring to replace the substring with.
993 /// @return inline_string& @c *this
994 /// @post The characters in the range @c [first,last) are replaced by the characters in the range @c [first2,last2) .
995 /// @post If @c std::distance(first,last)<std::distance(first2,last2) , then the remaining characters from
996 /// @c [first2,last2] are inserted at @c last , and @c size() will increase by the difference.
997 /// @post If @c std::distance(first,last)>std::distance(first2,last2), then the remain characters from
998 /// @c [first,last) are erased and @c size() will decrease by the difference.
999 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
1000 /// @pre Let @c dist=std::distance(first,last) and @c length=std::distance(first,last) ;
1001 /// if @c dist<length, then @c size()+(length-dist)<=max_size() else @c ARENE_PRECONDITION violation.
1002 template <
1003 typename InputIterator,
1004 constraints<
1005 std::enable_if_t<base::is_input_iterator_v<InputIterator>>,
1006 std::enable_if_t<!base::is_random_access_iterator_v<InputIterator>>> = nullptr>
1007 constexpr auto replace(
1008 const_iterator first,
1009 const_iterator last,
1010 InputIterator first2,
1011 InputIterator last2
1012 ) noexcept(denotes_nothrow_iterable_range_v<InputIterator>) -> inline_string& {
1013 return replace(first, last, inline_string{first2, last2});
1014 }
1015 /// @brief Replace a substring with another substring.
1016 ///
1017 /// @tparam RandomAccessIterator The iterator type
1018 /// @param first The start of the substring to replace.
1019 /// @param last The end of the substring to replace
1020 /// @param first2 The start of the substring to replace the substring with
1021 /// @param last2 The end of the substring to replace the substring with.
1022 /// @return inline_string& @c *this
1023 /// @post The characters in the range @c [first,last) are replaced by the characters in the range @c [first2,last2) .
1024 /// @post If @c std::distance(first,last)<std::distance(first2,last2) , then the remaining characters from
1025 /// @c [first2,last2] are inserted at @c last , and @c size() will increase by the difference.
1026 /// @post If @c std::distance(first,last)>std::distance(first2,last2), then the remain characters from
1027 /// @c [first,last) are erased and @c size() will decrease by the difference.
1028 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
1029 /// @pre Let @c dist=std::distance(first,last) and @c length=std::distance(first,last) ;
1030 /// if @c dist<length, then @c size()+(length-dist)<=max_size() else @c ARENE_PRECONDITION violation.
1031 template <
1032 typename RandomAccessIterator,
1033 constraints<std::enable_if_t<base::is_random_access_iterator_v<RandomAccessIterator>>> = nullptr>
1034 constexpr auto replace(
1035 const_iterator first,
1036 const_iterator last,
1037 RandomAccessIterator first2,
1038 RandomAccessIterator last2
1039 ) noexcept(denotes_nothrow_iterable_range_v<RandomAccessIterator>) -> inline_string& {
1040 auto const length_of_replacement = last2 - first2;
1041 ARENE_PRECONDITION(length_of_replacement >= 0);
1042 ARENE_PRECONDITION(last >= first);
1043 auto const offset = first - cbegin();
1044 ARENE_PRECONDITION(offset >= 0);
1045 inline_string::size_type pos{static_cast<inline_string::size_type>(offset)};
1046 prepare_replace(
1047 pos,
1048 static_cast<inline_string::size_type>(last - first),
1049 static_cast<inline_string::size_type>(length_of_replacement)
1050 );
1051 std::ignore = ::arene::base::copy(first2, last2, begin() + offset);
1052 return *this;
1053 }
1054
1055 /// @brief Remove the last character.
1056 /// @post @c size() is reduced by 1.
1057 /// @pre The string must not be empty, else @c ARENE_PRECONDITION violation.
1058 constexpr void pop_back() noexcept {
1059 ARENE_PRECONDITION(!empty());
1060 std::ignore = erase(this->size() - 1U);
1061 }
1062
1063 /// @brief Copy the string into the specified buffer up to the specified maximum length.
1064 ///
1065 /// @param str A pointer to the target buffer
1066 /// @param count The maximum number of characters to copy
1067 /// @return The number of characters copied
1068 /// @pre @c str+n must be valid , else behavior is undefined.
1069 constexpr auto copy(detail::character* str, size_type count) const -> size_type {
1070 return string_view{*this}.copy(str, count);
1071 }
1072
1073 /// @brief Copy the substring starting at the specified position into the specified buffer up to the specified maximum
1074 /// length.
1075 ///
1076 /// @param str A pointer to the target buffer
1077 /// @param count The maximum number of characters to copy
1078 /// @param pos The starting position to copy from. If @c >size() , no characters are copied.
1079 /// @return The number of characters copied
1080 /// @pre @c str[min(count,size()-pos)] must be valid , else behavior is undefined.
1081 constexpr auto copy(detail::character* str, size_type count, size_type pos) const -> size_type {
1082 return string_view{*this}.copy(str, count, pos);
1083 }
1084
1085 /// @brief Produce a copy of the string.
1086 /// @return inline_string A copy of @c *this
1087 ARENE_NODISCARD constexpr auto substr() const noexcept -> inline_string { return *this; }
1088
1089 /// @brief Produce substring of the string starting at an offset.
1090 ///
1091 /// @param pos The start of the substring to return.
1092 /// @return inline_string A new string holding the characters in the range @c [begin()+pos,end()) . If @c pos>=size()
1093 /// , returns an empty string.
1094 ARENE_NODISCARD constexpr auto substr(size_type pos) const noexcept -> inline_string {
1095 return inline_string{string_view{*this}.substr(pos)};
1096 }
1097
1098 /// @brief Produce a substring of the string with an offset and length.
1099 ///
1100 /// @param pos The start of the substring to return
1101 /// @param n The maximum number of characters to return
1102 /// @return inline_string A new string holding the characters in the range
1103 /// @c [begin()+pos,begin()+std::min(size()-pos,count)) . If @c pos>=size() , returns an empty string.
1104 ARENE_NODISCARD constexpr auto substr(size_type pos, size_type n) const noexcept -> inline_string {
1105 return inline_string{string_view{*this}.substr(pos, n)};
1106 }
1107
1108 /// @brief Check if the string is empty
1109 ///
1110 /// @return true If @c size()==0 .
1111 /// @return false If @c size()!=0 .
1112 ARENE_NODISCARD constexpr auto empty() const noexcept -> bool { return this->size() == 0U; }
1113
1114 /// @brief Return a pointer to the NUL-terminated string held in @c *this
1115 ///
1116 /// @return a pointer to the NUL-terminated string held in @c *this
1117 ARENE_NODISCARD constexpr auto c_str() const noexcept -> detail::raw_c_string { return data(); }
1118
1119 /// @brief Return a pointer to the NUL-terminated string held in @c *this
1120 ///
1121 /// @return a pointer to the NUL-terminated string held in @c *this
1122 ARENE_NODISCARD constexpr auto data() const noexcept -> detail::raw_c_string { return buffer_.data(); }
1123
1124 /// @brief Return a pointer to the NUL-terminated string held in @c *this
1125 ///
1126 /// @return a pointer to the NUL-terminated string held in @c *this
1127 ARENE_NODISCARD constexpr auto data() noexcept -> detail::character* { return buffer_.data(); }
1128
1129 /// @brief The maximum length of the string
1130 /// @return size_type @c MaxSize
1131 static constexpr auto capacity() -> std::size_t { return MaxSize; }
1132
1133 /// @brief The maximum length of the string
1134 /// @return size_type @c MaxSize
1135 static constexpr auto max_size() -> std::size_t { return capacity(); }
1136
1137 /// @brief Clear the string, so it is empty.
1138 /// @post size()==0 .
1139 /// @post @c data()[0]=='\0' .
1140 constexpr void clear() noexcept { set_null_terminator_to(0U); }
1141
1142 /// @brief Resize the string. If the new size is larger than the old size, appending copies of @c new_char to make the
1143 /// string the required length
1144 ///
1145 /// @param new_size The new size of the string
1146 /// @param new_char The character to append if extending the string. Defaults to @c '\0' .
1147 /// @pre @c new_size<=max_size() else @c ARENE_PRECONDITION violation.
1148 // Argument order matches the order in @c std::string::resize
1149 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
1150 constexpr void resize(size_type new_size, detail::character new_char = '\0') noexcept {
1151 ARENE_PRECONDITION(new_size <= max_size());
1152 inline_string::iterator original_end{end()};
1153 set_null_terminator_to(new_size);
1154 ::arene::base::fill(std::min(original_end, end()), end(), new_char);
1155 }
1156
1157 // parasoft-begin-suppress AUTOSAR-A2_10_1-a "False positive: 'index' does not hide anything"
1158 /// @brief Retrieve the @c index -th character in the string.
1159 ///
1160 /// @param index The index of the character to retrieve
1161 /// @return A reference to that character
1162 /// @pre @c index<=size() else @c ARENE_PRECONDITION violation.
1163 ARENE_NODISCARD constexpr auto operator[](size_type index) const noexcept -> detail::character const& {
1164 ARENE_PRECONDITION(index <= this->size());
1165 return buffer_[index];
1166 }
1167
1168 /// @brief Retrieve the @c index -th character in the string.
1169 ///
1170 /// @param index The index of the character to retrieve
1171 /// @return A reference to that character
1172 /// @pre @c index<=size() else @c ARENE_PRECONDITION violation.
1173 /// @warning Setting @c index[size()] to anything other than @c 0 is undefined behaviour.
1174 ARENE_NODISCARD constexpr auto operator[](size_type index) noexcept -> detail::character& {
1175 ARENE_PRECONDITION(index <= this->size());
1176 return buffer_[index];
1177 }
1178 // parasoft-end-suppress AUTOSAR-A2_10_1-a
1179
1180 /// @brief Get the first character in the string
1181 ///
1182 /// @return A reference to the first character
1183 /// @pre @c size()>0 , else @c ARENE_PRECONDITION violation.
1184 ARENE_NODISCARD constexpr auto front() const noexcept -> detail::character const& {
1185 ARENE_PRECONDITION(!empty());
1186 return buffer_.front();
1187 }
1188
1189 /// @brief Get the first character in the string
1190 ///
1191 /// @return A reference to the first character
1192 /// @pre @c size()>0 , else @c ARENE_PRECONDITION violation.
1193 ARENE_NODISCARD constexpr auto front() noexcept -> detail::character& {
1194 ARENE_PRECONDITION(!empty());
1195 return buffer_.front();
1196 }
1197
1198 /// @brief Get the last character in the string
1199 ///
1200 /// @return A reference to the last character
1201 /// @pre @c size()>0 , else @c ARENE_PRECONDITION violation.
1202 ARENE_NODISCARD constexpr auto back() const noexcept -> detail::character const& {
1203 ARENE_PRECONDITION(!empty());
1204 return buffer_[this->size() - 1U];
1205 }
1206
1207 /// @brief Get the last character in the string
1208 ///
1209 /// @return A reference to the last character
1210 /// @pre @c size()>0 , else @c ARENE_PRECONDITION violation.
1211 ARENE_NODISCARD constexpr auto back() noexcept -> detail::character& {
1212 ARENE_PRECONDITION(!empty());
1213 return buffer_[this->size() - 1U];
1214 }
1215
1216 /// @brief Iterator to the first position in the string.
1217 ///
1218 /// @return iterator An iterator to that refers to the first element if the string is not empty, or @c end()
1219 /// otherwise
1220 ARENE_NODISCARD constexpr auto begin() noexcept -> iterator {
1221 return iterator(iterator_passkey{}, buffer_.begin().base());
1222 }
1223
1224 /// @brief Iterator to the first position in the string.
1225 ///
1226 /// @return const_iterator An iterator to that refers to the first element if the string is not empty, or @c end()
1227 /// otherwise
1228 ARENE_NODISCARD constexpr auto begin() const noexcept -> const_iterator {
1229 return const_iterator(iterator_passkey{}, buffer_.begin().base());
1230 }
1231 /// @brief Iterator to the first position in the string.
1232 ///
1233 /// @return const_iterator An iterator to that refers to the first element if the string is not empty, or @c end()
1234 /// otherwise
1235 ARENE_NODISCARD constexpr auto cbegin() const noexcept -> const_iterator { return begin(); }
1236
1237 /// @brief The one-past-the-last position in the string.
1238 ///
1239 /// @return iterator An iterator to that refers to one-past-the-last position in the string.
1240 ARENE_NODISCARD constexpr auto end() noexcept -> iterator {
1241 return begin() + static_cast<difference_type>(this->size());
1242 }
1243
1244 /// @brief Return an iterator to one-past-the-last position in the string.
1245 ///
1246 /// @return const_iterator An iterator to that refers to one-past-the-last position in the string.
1247 ARENE_NODISCARD constexpr auto end() const noexcept -> const_iterator {
1248 return begin() + static_cast<difference_type>(this->size());
1249 }
1250 /// @brief Return an iterator to one-past-the-last position in the string.
1251 ///
1252 /// @return const_iterator An iterator to that refers to one-past-the-last position in the string.
1253 ARENE_NODISCARD constexpr auto cend() const noexcept -> const_iterator { return end(); }
1254
1255 /// @brief Return an iterator to the start of the reversed string
1256 ///
1257 /// @return reverse_iterator An iterator equivalent to @c reverse_iterator(end())
1258 ARENE_NODISCARD constexpr auto rbegin() noexcept -> reverse_iterator { return reverse_iterator(end()); }
1259
1260 /// @brief Return an iterator to the start of the reversed string
1261 ///
1262 /// @return const_reverse_iterator An iterator equivalent to @c const_reverse_iterator(end())
1263 ARENE_NODISCARD auto rbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(end()); }
1264
1265 /// @brief Return an iterator to the start of the reversed string
1266 ///
1267 /// @return const_reverse_iterator An iterator equivalent to @c const_reverse_iterator(end())
1268 ARENE_NODISCARD auto crbegin() const noexcept -> const_reverse_iterator { return rbegin(); }
1269
1270 /// @brief Return an iterator to the end of the reversed string
1271 ///
1272 /// @return reverse_iterator An iterator equivalent to @c reverse_iterator(begin())
1273 ARENE_NODISCARD constexpr auto rend() noexcept -> reverse_iterator { return reverse_iterator(begin()); }
1274
1275 /// @brief Return an iterator to the end of the reversed string
1276 ///
1277 /// @return const_reverse_iterator An iterator equivalent to @c const_reverse_iterator(begin())
1278 ARENE_NODISCARD auto rend() const noexcept -> const_reverse_iterator { return const_reverse_iterator(begin()); }
1279
1280 /// @brief Return an iterator to the end of the reversed string
1281 ///
1282 /// @return const_reverse_iterator An iterator equivalent to @c const_reverse_iterator(begin())
1283 ARENE_NODISCARD auto crend() const noexcept -> const_reverse_iterator { return rend(); }
1284
1285 // parasoft-begin-suppress AUTOSAR-A2_10_1-e "These functions are called with qualified names so they can't be hidden"
1286 /// @brief Compare two strings for lexicographical ordering.
1287 ///
1288 /// @tparam OtherMaxLength The max length of the other string
1289 /// @param lhs The first string
1290 /// @param rhs The second string
1291 /// @return strong_ordering::equal If both strings have the same @c size() and equivalent characters.
1292 /// @return strong_ordering::less If @c lhs is lexicographically before @c rhs .
1293 /// @return strong_ordering::greater If @c lhs is lexicographically after @c rhs .
1294 template <std::size_t OtherMaxLength>
1295 ARENE_NODISCARD static constexpr auto
1296 three_way_compare(inline_string const& lhs, inline_string<OtherMaxLength> const& rhs) noexcept -> strong_ordering {
1297 return string_view::three_way_compare(string_view{lhs}, string_view{rhs});
1298 }
1299
1300 /// @brief Compare two strings for lexicographical ordering.
1301 ///
1302 /// @param lhs The first string
1303 /// @param rhs The second string
1304 /// @return strong_ordering::equal If both strings have the same @c size() and equivalent characters.
1305 /// @return strong_ordering::less If @c lhs is lexicographically before @c rhs .
1306 /// @return strong_ordering::greater If @c lhs is lexicographically after @c rhs .
1307 ARENE_NODISCARD static constexpr auto three_way_compare(inline_string const& lhs, string_view rhs) noexcept
1308 -> strong_ordering {
1309 return string_view::three_way_compare(string_view{lhs}, rhs);
1310 }
1311
1312 /// @brief Compare two strings for lexicographical ordering.
1313 ///
1314 /// @param lhs The first string
1315 /// @param rhs The second string
1316 /// @return strong_ordering::equal If both strings have the same @c size() and equivalent characters.
1317 /// @return strong_ordering::less If @c lhs is lexicographically before @c rhs .
1318 /// @return strong_ordering::greater If @c lhs is lexicographically after @c rhs .
1319 ARENE_NODISCARD static constexpr auto three_way_compare(inline_string const& lhs, detail::raw_c_string rhs) noexcept
1320 -> strong_ordering {
1321 return string_view::three_way_compare(string_view{lhs}, rhs);
1322 }
1323
1324 /// @brief Compare two strings for lexicographical ordering.
1325 ///
1326 /// @param lhs The first string
1327 /// @param rhs The second string
1328 /// @return strong_ordering::equal If both strings have the same @c size() and equivalent characters.
1329 /// @return strong_ordering::less If @c lhs is lexicographically before @c rhs .
1330 /// @return strong_ordering::greater If @c lhs is lexicographically after @c rhs .
1331 ARENE_NODISCARD static constexpr auto
1332 three_way_compare(inline_string const& lhs, null_terminated_string_view rhs) noexcept -> strong_ordering {
1333 return inline_string::three_way_compare(lhs, rhs.c_str());
1334 }
1335
1336 /// @brief Determine if two strings are definitely not equal.
1337 ///
1338 /// @tparam OtherMaxLength The max length of the second string
1339 /// @param lhs The first string
1340 /// @param rhs The second string
1341 /// @return inequality_heuristic::definitely_not_equal If @c lhs.size()!=rhs.size() .
1342 /// @return inequality_heuristic::may_be_equal_or_not_equal If @c lhs.size()==rhs.size() .
1343 template <std::size_t OtherMaxLength>
1344 ARENE_NODISCARD static constexpr auto
1345 fast_inequality_check(inline_string const& lhs, inline_string<OtherMaxLength> const& rhs) noexcept
1346 -> inequality_heuristic {
1347 return inline_string::fast_inequality_check(lhs, string_view{rhs});
1348 }
1349
1350 /// @brief Determine if two strings are definitely not equal.
1351 ///
1352 /// @param lhs The first string
1353 /// @param rhs The second string
1354 /// @return inequality_heuristic::definitely_not_equal If @c lhs.size()!=rhs.size() .
1355 /// @return inequality_heuristic::may_be_equal_or_not_equal If @c lhs.size()==rhs.size() .
1356 ARENE_NODISCARD static constexpr auto fast_inequality_check(inline_string const& lhs, string_view rhs) noexcept
1357 -> inequality_heuristic {
1358 return inline_string_base::common_fast_inequality_check(lhs, rhs);
1359 }
1360 // parasoft-end-suppress AUTOSAR-A2_10_1-e
1361
1362 /// @brief Append a string to the current string
1363 ///
1364 /// @param rhs The string to append
1365 /// @return inline_string& @c *this
1366 /// @pre @c size()+rhs.size()<=max_size() else @c ARENE_PRECONDITION violation.
1367 /// @post @c size() is increased by @c rhs.size()
1368 /// @post The final characters in the string will be a substring equivalent to @c rhs .
1369 constexpr auto append(string_view rhs) noexcept -> inline_string& {
1370 ARENE_PRECONDITION(this->size() + rhs.size() <= max_size());
1371 std::ignore = ::arene::base::copy(rhs.begin(), rhs.end(), begin() + static_cast<difference_type>(this->size()));
1372 set_null_terminator_to(this->size() + rhs.size());
1373 return *this;
1374 }
1375
1376 /// @brief Append a character to the current string
1377 ///
1378 /// @param rhs The character to append
1379 /// @return inline_string& @c *this
1380 /// @pre @c size()+1<=max_size() else @c ARENE_PRECONDITION violation.
1381 /// @post @c size() is increased by @c 1
1382 /// @post @c back()==rhs
1383 constexpr auto append(detail::character rhs) noexcept -> inline_string& { return append(string_view{&rhs, 1U}); }
1384
1385 /// @brief Append a series of characters from an initializer list to the string.
1386 ///
1387 /// @param rhs The characters to append
1388 /// @return inline_string& @c *this
1389 /// @pre @c size()+rhs.size()<=max_size() else @c ARENE_PRECONDITION violation.
1390 /// @post @c size() is increased by @c rhs.size()
1391 /// @post The final characters in the string will be a substring equivalent to @c rhs .
1392 constexpr auto append(std::initializer_list<detail::character> rhs) noexcept -> inline_string& {
1393 return append(string_view{rhs.begin(), rhs.size()});
1394 }
1395
1396 /// @brief Append a substring of a string to the current string
1397 ///
1398 /// @param rhs The string containing the substring to append
1399 /// @param pos The offset into @c rhs of the substring to append
1400 /// @return inline_string& @c *this
1401 /// @pre @c size()+rhs.substr(pos).size()<=max_size() else @c ARENE_PRECONDITION violation.
1402 /// @post @c size() is increased by @c rhs.substr(pos).size()
1403 /// @post The final characters in the string will be a substring equivalent to @c rhs.substr(pos) .
1404 constexpr auto append(string_view rhs, size_type pos) noexcept -> inline_string& { return append(rhs.substr(pos)); }
1405
1406 /// @brief Append a substring of a string to the current string
1407 ///
1408 /// @param rhs The string containing the substring to append
1409 /// @param pos The offset into @c rhs of the substring to append
1410 /// @param count The maximum length of the substring to append
1411 /// @return inline_string& @c *this
1412 /// @pre @c size()+rhs.substr(pos,count).size()<=max_size() else @c ARENE_PRECONDITION violation.
1413 /// @post @c size() is increased by @c rhs.substr(pos,count).size()
1414 /// @post The final characters in the string will be a substring equivalent to @c rhs.substr(pos,count) .
1415 constexpr auto append(string_view rhs, size_type pos, size_type count) noexcept -> inline_string& {
1416 return append(rhs.substr(pos, count));
1417 }
1418
1419 /// @brief Append a string specified as pointer and length to the current string
1420 ///
1421 /// @param rhs The start if the string to append
1422 /// @param count The number of characters in the string to append
1423 /// @return inline_string& @c *this
1424 /// @pre @c size()+count<=max_size() else @c ARENE_PRECONDITION violation.
1425 /// @post @c size() is increased by @c count
1426 /// @post The last @c count characters in the string are the @c count characters from @c rhs .
1427 constexpr auto append(detail::raw_c_string rhs, size_type count) noexcept -> inline_string& {
1428 return append(string_view{rhs, count});
1429 }
1430
1431 /// @brief Append the specified number of copies of a character to the string
1432 ///
1433 /// @param count The number of characters to append
1434 /// @param chr The character to append
1435 /// @return inline_string& @c *this
1436 /// @pre @c size()+count<=max_size() else @c ARENE_PRECONDITION violation.
1437 /// @post @c size() is increased by @c count
1438 /// @post The last @c count characters in the string are @c chr .
1439 // Argument order matches the order in @c std::string::append
1440 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
1441 constexpr auto append(size_type count, detail::character chr) noexcept -> inline_string& {
1442 resize(this->size() + count, chr);
1443 return *this;
1444 }
1445
1446 /// @brief Append a character to the current string
1447 ///
1448 /// @param rhs The character to append
1449 /// @pre @c size()+1<=max_size() else @c ARENE_PRECONDITION violation.
1450 /// @post @c size() is increased by @c 1
1451 /// @post @c back()==rhs
1452 constexpr void push_back(detail::character rhs) noexcept { std::ignore = append(rhs); }
1453
1454 /// @brief Append a string to the current string
1455 ///
1456 /// @param rhs The string to append
1457 /// @return inline_string& @c *this
1458 /// @pre @c size()+rhs.size()<=max_size() else @c ARENE_PRECONDITION violation.
1459 /// @post @c size() is increased by @c rhs.size()
1460 /// @post The final characters in the string will be a substring equivalent to @c rhs .
1461 constexpr auto operator+=(string_view rhs) noexcept -> inline_string& { return append(rhs); }
1462
1463 /// @brief Append a character to the current string
1464 ///
1465 /// @param rhs The character to append
1466 /// @return inline_string& @c *this
1467 /// @pre @c size()+1<=max_size() else @c ARENE_PRECONDITION violation.
1468 /// @post @c size() is increased by @c 1
1469 /// @post @c back()==rhs
1470 constexpr auto operator+=(detail::character rhs) noexcept -> inline_string& { return append(rhs); }
1471
1472 /// @brief Append a series of characters from an initializer list to the string.
1473 ///
1474 /// @param rhs The characters to append
1475 /// @return inline_string& @c *this
1476 /// @pre @c size()+rhs.size()<=max_size() else @c ARENE_PRECONDITION violation.
1477 /// @post @c size() is increased by @c rhs.size()
1478 /// @post The final characters in the string will be a substring equivalent to @c rhs .
1479 constexpr auto operator+=(std::initializer_list<detail::character> rhs) noexcept -> inline_string& {
1480 return append(rhs);
1481 }
1482
1483 // parasoft-begin-suppress AUTOSAR-A13_5_2-a-2 "Implicit conversion to string_view is part of the API"
1484 /// @brief Convert to string view
1485 ///
1486 /// Implicit conversion to @c string_view supports the use of @c string_view as a vocabulary type for accepting string
1487 /// parameters.
1488 /// @return A string view referring to the characters of @c *this
1489 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1490 ARENE_NODISCARD constexpr operator string_view() const noexcept {
1491 // We specify MaxLength as a maximum valid value to eliminate the
1492 // precondition in base::span constructor.
1493 return {c_str(), std::min(this->size(), max_size())};
1494 }
1495 // parasoft-end-suppress AUTOSAR-A13_5_2-a-2
1496
1497 // parasoft-begin-suppress AUTOSAR-A13_5_2-a-2 "Implicit conversion to null_terminated_string_view is part of the API"
1498 /// @brief Convert to null terminated string view
1499 ///
1500 /// Implicit conversion to @c null_terminated_string_view supports the use of @c null_terminated_string_view as a
1501 /// vocabulary type for accepting string parameters.
1502 /// @return A null-terminated string view referring to the characters of @c *this
1503 // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions)
1504 ARENE_NODISCARD constexpr operator null_terminated_string_view() const noexcept {
1505 return null_terminated_string_view{c_str()};
1506 }
1507 // parasoft-end-suppress AUTOSAR-A13_5_2-a-2
1508
1509 /// @brief Find the earliest position of the given substring within the string, starting at the specified position.
1510 ///
1511 /// @param str The substring to search for.
1512 /// @param pos The lowest position to search from. Defaults to 0.
1513 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1514 ARENE_NODISCARD constexpr auto find(string_view str, size_type pos = 0U) const noexcept -> size_type {
1515 return string_view{*this}.find(str, pos);
1516 }
1517
1518 /// @brief Find the earliest position of the specified character within the string.
1519 ///
1520 /// @param chr The character to search for
1521 /// @return The position of that character, or @c npos if not found
1522 ARENE_NODISCARD constexpr auto find(detail::character chr) const noexcept -> size_type {
1523 return find(string_view{&chr, 1U});
1524 }
1525
1526 /// @brief Find the earliest position of the specified character within the string, starting at the specified position
1527 ///
1528 /// @param chr The character to search for
1529 /// @param pos The lowest position to search from
1530 /// @return The position of that character, or @c npos if not found
1531 ARENE_NODISCARD constexpr auto find(detail::character chr, size_type pos) const noexcept -> size_type {
1532 return find(string_view{&chr, 1U}, pos);
1533 }
1534
1535 /// @brief Find the earliest position of the given substring within the string.
1536 ///
1537 /// @param str The substring to search for
1538 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1539 ARENE_NODISCARD constexpr auto find(detail::raw_c_string str) const noexcept -> size_type {
1540 return find(string_view{str});
1541 }
1542
1543 /// @brief Find the earliest position of the given substring within the string, starting at the specified position
1544 ///
1545 /// @param str The substring to search for
1546 /// @param pos The lowest position to search from
1547 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1548 ARENE_NODISCARD constexpr auto find(detail::raw_c_string str, size_type pos) const noexcept -> size_type {
1549 return find(string_view{str}, pos);
1550 }
1551
1552 /// @brief Find the earliest position of the @c n character string starting at @c str within the string, starting at
1553 /// the specified position
1554 ///
1555 /// @param str The start of the string to search for
1556 /// @param pos The lowest position to search from
1557 /// @param count The length of the string to search for
1558 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1559 ARENE_NODISCARD constexpr auto find(detail::raw_c_string str, size_type pos, size_type count) const noexcept
1560 -> size_type {
1561 return find(string_view{str, count}, pos);
1562 }
1563
1564 /// @brief Find the latest position of the given substring within the string.
1565 ///
1566 /// @param str The substring to search for
1567 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1568 ARENE_NODISCARD constexpr auto rfind(string_view str) const noexcept -> size_type { return rfind(str, this->size()); }
1569
1570 /// @brief Find the latest position of the given substring within the string, starting at the specified position
1571 ///
1572 /// @param str The substring to search for
1573 /// @param pos The highest position to search from
1574 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1575 ARENE_NODISCARD constexpr auto rfind(string_view str, size_type pos) const noexcept -> size_type {
1576 return string_view{*this}.rfind(str, pos);
1577 }
1578
1579 /// @brief Find the latest position of the specified character within the string
1580 ///
1581 /// @param chr The character to search for
1582 /// @return The position of that character, or @c npos if not found
1583 ARENE_NODISCARD constexpr auto rfind(detail::character chr) const noexcept -> size_type {
1584 return rfind(string_view{&chr, 1U});
1585 }
1586
1587 /// @brief Find the latest position of the specified character within the string, starting at the specified position.
1588 ///
1589 /// @param chr The character to search for
1590 /// @param pos The highest position to search from
1591 /// @return The position of that character, or @c npos if not found
1592 ARENE_NODISCARD constexpr auto rfind(detail::character chr, size_type pos) const noexcept -> size_type {
1593 return rfind(string_view{&chr, 1U}, pos);
1594 }
1595
1596 /// @brief Find the latest position of the given substring within the string.
1597 ///
1598 /// @param str The substring to search for
1599 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1600 ARENE_NODISCARD constexpr auto rfind(detail::raw_c_string str) const noexcept -> size_type {
1601 return rfind(string_view{str});
1602 }
1603
1604 /// @brief Find the latest position of the given substring within the string, starting at the specified position
1605 ///
1606 /// @param str The substring to search for
1607 /// @param pos The highest position to search from
1608 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1609 ARENE_NODISCARD constexpr auto rfind(detail::raw_c_string str, size_type pos) const noexcept -> size_type {
1610 return rfind(string_view{str}, pos);
1611 }
1612
1613 /// @brief Find the latest position of the @c n character string starting at @c str within the string, starting at the
1614 /// specified position
1615 ///
1616 /// @param str The start of the string to search for
1617 /// @param pos The highest position to search from
1618 /// @param count The length of the string to search for
1619 /// @return size_type The offset at which @c str can be found within the string, or @c npos if not found.
1620 ARENE_NODISCARD constexpr auto rfind(detail::raw_c_string str, size_type pos, size_type count) const noexcept
1621 -> size_type {
1622 return rfind(string_view{str, count}, pos);
1623 }
1624
1625 /// @brief Find the earliest position such that the character at that position is one of those in the provided string.
1626 ///
1627 /// @param str The list of characters to find
1628 /// @return The offset of the first character in @c str if there is one, otherwise @c npos
1629 ARENE_NODISCARD constexpr auto find_first_of(string_view str) const noexcept -> size_type {
1630 return find_first_of(str, 0U);
1631 }
1632
1633 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1634 /// position is one of those in the provided string.
1635 ///
1636 /// @param str The list of characters to find
1637 /// @param pos The start position
1638 /// @return The offset of the first character in @c str after @c pos if there is one, otherwise @c npos
1639 ARENE_NODISCARD constexpr auto find_first_of(string_view str, size_type pos) const noexcept -> size_type {
1640 return string_view{*this}.find_first_of(str, pos);
1641 }
1642
1643 /// @brief Find the earliest position such that the character at that position is one of those in the provided string.
1644 ///
1645 /// @param str The list of characters to find
1646 /// @return The offset of the first character in @c str if there is one, otherwise @c npos
1647 ARENE_NODISCARD constexpr auto find_first_of(detail::raw_c_string str) const noexcept -> size_type {
1648 return find_first_of(string_view{str}, 0U);
1649 }
1650
1651 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1652 /// position is one of those in the provided string.
1653 ///
1654 /// @param str The list of characters to find
1655 /// @param pos The start position
1656 /// @return The offset of the first character in @c str after @c pos if there is one, otherwise @c npos
1657 ARENE_NODISCARD constexpr auto find_first_of(detail::raw_c_string str, size_type pos) const noexcept -> size_type {
1658 return find_first_of(string_view{str}, pos);
1659 }
1660
1661 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1662 /// position is one of those in the provided string.
1663 ///
1664 /// @param str The list of characters to find
1665 /// @param pos The start position
1666 /// @param count The number of characters in @c str
1667 /// @return The offset of the first character in @c str after @c pos if there is one, otherwise @c npos
1668 ARENE_NODISCARD constexpr auto find_first_of(detail::raw_c_string str, size_type pos, size_type count) const noexcept
1669 -> size_type {
1670 return find_first_of(string_view{str, count}, pos);
1671 }
1672
1673 /// @brief Find the earliest position such that the character at that position is the provided character.
1674 ///
1675 /// @param chr The character to find
1676 /// @return The offset of the first character matching @c chr if there is one, otherwise @c npos
1677 ARENE_NODISCARD constexpr auto find_first_of(detail::character chr) const noexcept -> size_type { return find(chr); }
1678
1679 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1680 /// position is the provided character.
1681 ///
1682 /// @param chr The character to find
1683 /// @param pos The start position
1684 /// @return The offset of the first character matching @c chr after @c pos if there is one, otherwise @c npos
1685 ARENE_NODISCARD constexpr auto find_first_of(detail::character chr, size_type pos) const noexcept -> size_type {
1686 return find(chr, pos);
1687 }
1688
1689 /// @brief Find the earliest position such that the character at that position is not one of those in the provided
1690 /// string.
1691 ///
1692 /// @param str The list of characters to find
1693 /// @return The offset of the first character not in @c str if there is one, otherwise @c npos
1694 ARENE_NODISCARD constexpr auto find_first_not_of(string_view str) const noexcept -> size_type {
1695 return find_first_not_of(str, 0U);
1696 }
1697
1698 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1699 /// position is one of those in the provided string.
1700 ///
1701 /// @param str The list of characters to find
1702 /// @param pos The start position
1703 /// @return The offset of the first character not in @c str after @c pos if there is one, otherwise @c npos
1704 ARENE_NODISCARD constexpr auto find_first_not_of(string_view str, size_type pos) const noexcept -> size_type {
1705 return string_view{*this}.find_first_not_of(str, pos);
1706 }
1707
1708 /// @brief Find the earliest position such that the character at that position is not one of those in the provided
1709 /// string.
1710 ///
1711 /// @param str The list of characters to find
1712 /// @return The offset of the first character not in @c str if there is one, otherwise @c npos
1713 ARENE_NODISCARD constexpr auto find_first_not_of(detail::raw_c_string str) const noexcept -> size_type {
1714 return find_first_not_of(string_view{str}, 0U);
1715 }
1716
1717 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1718 /// position is not one of those in the provided string.
1719 ///
1720 /// @param str The list of characters to find
1721 /// @param pos The start position
1722 /// @return The offset of the first character not in @c str after @c pos if there is one, otherwise @c npos
1723 ARENE_NODISCARD constexpr auto find_first_not_of(detail::raw_c_string str, size_type pos) const noexcept
1724 -> size_type {
1725 return find_first_not_of(string_view{str}, pos);
1726 }
1727
1728 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1729 /// position is not one of those in the provided string.
1730 ///
1731 /// @param str The list of characters to find
1732 /// @param pos The start position
1733 /// @param count The number of characters in @c str
1734 /// @return The offset of the first character not in @c str after @c pos if there is one, otherwise @c npos
1735 ARENE_NODISCARD constexpr auto find_first_not_of(detail::raw_c_string str, size_type pos, size_type count)
1736 const noexcept -> size_type {
1737 return find_first_not_of(string_view{str, count}, pos);
1738 }
1739
1740 /// @brief Find the earliest position such that the character at that position is the provided character.
1741 ///
1742 /// @param chr The character to find
1743 /// @return The offset of the first character not matching @c chr if there is one, otherwise @c npos
1744 ARENE_NODISCARD constexpr auto find_first_not_of(detail::character chr) const noexcept -> size_type {
1745 return find_first_not_of(string_view{&chr, 1U});
1746 }
1747
1748 /// @brief Find the earliest position from the provided start position onwards such that the character at that
1749 /// position is not the provided character.
1750 ///
1751 /// @param chr The character to find
1752 /// @param pos The start position
1753 /// @return The offset of the first character not matching @c chr after @c pos if there is one, otherwise @c npos
1754 ARENE_NODISCARD constexpr auto find_first_not_of(detail::character chr, size_type pos) const noexcept -> size_type {
1755 return find_first_not_of(string_view{&chr, 1U}, pos);
1756 }
1757
1758 /// @brief Find the last position such that the character at that position is one of those in the provided string.
1759 ///
1760 /// @param str The list of characters to find
1761 /// @return The offset of the last character matching those in @c str if there is one, otherwise @c npos
1762 ARENE_NODISCARD constexpr auto find_last_of(string_view str) const noexcept -> size_type {
1763 return find_last_of(str, npos);
1764 }
1765
1766 /// @brief Find the last position from the provided start position backwards such that the character at that position
1767 /// is one of those in the provided string.
1768 ///
1769 /// @param str The list of characters to find
1770 /// @param pos The start position
1771 /// @return The offset of the last character matching those in @c str before or at @c pos if there is one, otherwise
1772 /// @c npos
1773 ARENE_NODISCARD constexpr auto find_last_of(string_view str, size_type pos) const noexcept -> size_type {
1774 return string_view{*this}.find_last_of(str, pos);
1775 }
1776
1777 /// @brief Find the last position such that the character at that position is one of those in the provided string.
1778 ///
1779 /// @param str The list of characters to find
1780 /// @return The offset of the last character in @c str if there is one, otherwise @c npos
1781 ARENE_NODISCARD constexpr auto find_last_of(detail::raw_c_string str) const noexcept -> size_type {
1782 return find_last_of(string_view{str}, npos);
1783 }
1784
1785 /// @brief Find the last position from the provided start position backwards such that the character at that position
1786 /// is one of those in the provided string.
1787 ///
1788 /// @param str The list of characters to find
1789 /// @param pos The start position
1790 /// @return The offset of the last character matching the characters in @c str at or before @c pos if there is one,
1791 /// otherwise @c npos
1792 ARENE_NODISCARD constexpr auto find_last_of(detail::raw_c_string str, size_type pos) const noexcept -> size_type {
1793 return find_last_of(string_view{str}, pos);
1794 }
1795
1796 /// @brief Find the latest position from the provided start position backwards such that the character at that
1797 /// position is one of those in the provided string.
1798 ///
1799 /// @param str The list of characters to find
1800 /// @param pos The start position
1801 /// @param count The number of characters in @c str
1802 /// @return The offset of the last character matching the characters in the first @c n characters of @c str at or
1803 /// before @c pos if there is one, otherwise @c npos
1804 ARENE_NODISCARD constexpr auto find_last_of(detail::raw_c_string str, size_type pos, size_type count) const noexcept
1805 -> size_type {
1806 return find_last_of(string_view{str, count}, pos);
1807 }
1808
1809 /// @brief Find the latest position such that the character at that position is the provided character.
1810 ///
1811 /// @param chr The character to find
1812 /// @return The offset of the last character matching @c chr if there is one, otherwise @c npos
1813 ARENE_NODISCARD constexpr auto find_last_of(detail::character chr) const noexcept -> size_type { return rfind(chr); }
1814
1815 /// @brief Find the latest position from the provided start position backwards such that the character at that
1816 /// position is the provided character.
1817 ///
1818 /// @param chr The character to find
1819 /// @param pos The start position
1820 /// @return The offset of the last character matching @c chr at or before @c pos if there is one, otherwise @c npos
1821 ARENE_NODISCARD constexpr auto find_last_of(detail::character chr, size_type pos) const noexcept -> size_type {
1822 return rfind(chr, pos);
1823 }
1824
1825 /// @brief Find the latest position such that the character at that position is not one of those in the provided
1826 /// string.
1827 ///
1828 /// @param str The list of characters to find
1829 /// @return The offset of the last character not in @c str if there is one, otherwise @c npos
1830 ARENE_NODISCARD constexpr auto find_last_not_of(string_view str) const noexcept -> size_type {
1831 return find_last_not_of(str, npos);
1832 }
1833
1834 /// @brief Find the latest position from the provided start position backwards such that the character at that
1835 /// position is not one of those in the provided string.
1836 ///
1837 /// @param str The list of characters to find
1838 /// @param pos The start position
1839 /// @return The offset of the last character not in @c str at or before @c pos if there is one, otherwise @c npos
1840 ARENE_NODISCARD constexpr auto find_last_not_of(string_view str, size_type pos) const noexcept -> size_type {
1841 return string_view{*this}.find_last_not_of(str, pos);
1842 }
1843
1844 /// @brief Find the latest position such that the character at that position is not one of those in the provided
1845 /// string.
1846 ///
1847 /// @param str The list of characters to find
1848 /// @return The offset of the last character not in @c str if there is one, otherwise @c npos
1849 ARENE_NODISCARD constexpr auto find_last_not_of(detail::raw_c_string str) const noexcept -> size_type {
1850 return find_last_not_of(string_view{str});
1851 }
1852
1853 /// @brief Find the latest position from the provided start position backwards such that the character at that
1854 /// position is not one of those in the provided string.
1855 ///
1856 /// @param str The list of characters to find
1857 /// @param pos The start position
1858 /// @return The offset of the last character not in @c str at or before @c pos if there is one, otherwise @c npos
1859 ARENE_NODISCARD constexpr auto find_last_not_of(detail::raw_c_string str, size_type pos) const noexcept -> size_type {
1860 return find_last_not_of(string_view{str}, pos);
1861 }
1862
1863 /// @brief Find the latest position from the provided start position backwards such that the character at that
1864 /// position is not one of those in the provided string.
1865 ///
1866 /// @param str The list of characters to find
1867 /// @param pos The start position
1868 /// @param count The number of characters in @c str
1869 /// @return The offset of the last character not in @c str at or before @c pos if there is one, otherwise @c npos
1870 ARENE_NODISCARD constexpr auto find_last_not_of(detail::raw_c_string str, size_type pos, size_type count)
1871 const noexcept -> size_type {
1872 return find_last_not_of(string_view{str, count}, pos);
1873 }
1874
1875 /// @brief Find the latest position such that the character at that position is not the provided character.
1876 ///
1877 /// @param chr The character to find
1878 /// @return The offset of the last character not matching @c chr if there is one, otherwise @c npos
1879 ARENE_NODISCARD constexpr auto find_last_not_of(detail::character chr) const noexcept -> size_type {
1880 return find_last_not_of(string_view{&chr, 1U});
1881 }
1882
1883 /// @brief Find the latest position from the provided start position backwards such that the character at that
1884 /// position is not the provided character.
1885 ///
1886 /// @param chr The character to find
1887 /// @param pos The start position
1888 /// @return The offset of the last character not matching @c chr at or before @c pos if there is one, otherwise
1889 /// @c npos
1890 ARENE_NODISCARD constexpr auto find_last_not_of(detail::character chr, size_type pos) const noexcept -> size_type {
1891 return find_last_not_of(string_view{&chr, 1U}, pos);
1892 }
1893
1894 /// @brief Check if the string starts with a character.
1895 ///
1896 /// @param chr The character to check
1897 /// @return inline_string @c true if the string starts with the character, @c false otherwise
1898 ARENE_NODISCARD constexpr auto starts_with(detail::character chr) const noexcept -> bool {
1899 return string_view{*this}.starts_with(chr);
1900 }
1901
1902 /// @brief Check if the string starts with another string.
1903 ///
1904 /// @param str The string to check
1905 /// @return inline_string @c true if the string starts with the string, @c false otherwise
1906 ARENE_NODISCARD constexpr auto starts_with(string_view str) const noexcept -> bool {
1907 return string_view{*this}.starts_with(str);
1908 }
1909
1910 /// @brief Check if the string ends with a character.
1911 ///
1912 /// @param chr The character to check
1913 /// @return inline_string @c true if the string ends with the character, @c false otherwise
1914 ARENE_NODISCARD constexpr auto ends_with(detail::character chr) const noexcept -> bool {
1915 return string_view{*this}.ends_with(chr);
1916 }
1917
1918 /// @brief Check if the string ends with another string.
1919 ///
1920 /// @param str The string to check
1921 /// @return inline_string @c true if the string ends with the string, @c false otherwise
1922 ARENE_NODISCARD constexpr auto ends_with(string_view str) const noexcept -> bool {
1923 return string_view{*this}.ends_with(str);
1924 }
1925
1926 /// @brief Compare against another string, to see if it is less than, equal to or greater than the other.
1927 ///
1928 /// @param other The other string
1929 /// @return inline_string @c -1 if @c *this is less than @c other, @c 0 if they are equal, and @c 1 if @c *this is
1930 /// greater than @c other
1931 ARENE_NODISCARD constexpr auto compare(string_view other) const noexcept -> integral_comparison_result {
1932 return string_view{*this}.compare(other);
1933 }
1934
1935 /// @brief Compare a substring against another string, to see if it is less than, equal to or greater than the other.
1936 ///
1937 /// @param pos The start of the substring to compare
1938 /// @param count The length of the substring to compare
1939 /// @param other The other string
1940 /// @return inline_string @c substr(pos,n).compare(other)
1941 ARENE_NODISCARD constexpr auto compare(size_type pos, size_type count, string_view other) const noexcept
1942 -> integral_comparison_result {
1943 return string_view{*this}.substr(pos, count).compare(other);
1944 }
1945
1946 /// @brief Compare a substring against a substring of another string, to see if it is less than, equal to or greater
1947 /// than the other.
1948 ///
1949 /// @param pos The start of the substring to compare
1950 /// @param count The length of the substring to compare
1951 /// @param other The other string
1952 /// @param pos2 The start of the substring in the other string
1953 /// @return inline_string @c compare(pos,n,other.substr(pos2))
1954 ARENE_NODISCARD constexpr auto compare(size_type pos, size_type count, string_view other, size_type pos2)
1955 const noexcept -> integral_comparison_result {
1956 return compare(pos, count, other.substr(pos2));
1957 }
1958
1959 /// @brief Compare a substring against a substring of another string, to see if it is less than, equal to or greater
1960 /// than the other.
1961 ///
1962 /// @param pos The start of the substring to compare
1963 /// @param length1 The length of the substring to compare
1964 /// @param other The other string
1965 /// @param pos2 The start of the substring in the other string
1966 /// @param length2 The length of the substring in the other string
1967 /// @return inline_string @c compare(pos,n,other.substr(pos2,length2))
1968 ARENE_NODISCARD constexpr auto
1969 compare(size_type pos, size_type length1, string_view other, size_type pos2, size_type length2) const noexcept
1970 -> integral_comparison_result {
1971 return compare(pos, length1, other.substr(pos2, length2));
1972 }
1973
1974 /// @brief Compare a substring against another string, to see if it is less than, equal to or greater than the other.
1975 ///
1976 /// @param pos The start of the substring to compare
1977 /// @param length1 The length of the substring to compare
1978 /// @param other The start of the other string
1979 /// @param length2 The length of the other string
1980 /// @return inline_string @c compare(pos,n,string_view{other,length2})
1981 ARENE_NODISCARD constexpr auto
1982 compare(size_type pos, size_type length1, detail::raw_c_string other, size_type length2) const noexcept
1983 -> integral_comparison_result {
1984 return compare(pos, length1, string_view{other, length2});
1985 }
1986
1987 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "Hidden friends permitted by A11-3-1 Permit #2"
1988 /// @brief Concatenate two strings
1989 /// @tparam OtherMaxLength the max length of @c rhs
1990 /// @param lhs The first string to concatenate
1991 /// @param rhs The second string to concatenate
1992 /// @return A @c inline_string<MaxLength+OtherMaxLength> holding the concatenation of the two strings.
1993 template <std::size_t OtherMaxLength>
1994 ARENE_NODISCARD friend constexpr auto
1995 operator+(inline_string const& lhs, inline_string<OtherMaxLength> const& rhs) noexcept
1996 -> inline_string<MaxSize + OtherMaxLength> {
1997 inline_string<MaxSize + OtherMaxLength> res{lhs};
1998 std::ignore = res.append(rhs);
1999 return res;
2000 }
2001 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
2002
2003 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
2004 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "Hidden friends permitted by A11-3-1 Permit #2"
2005 /// @brief Concatenate two strings
2006 ///
2007 /// @param lhs The first string to concatenate
2008 /// @param rhs The second string to concatenate
2009 /// @return inline_string holding the concatenation of the two strings.
2010 /// @pre @c lhs.size()+rhs.size()<=lhs.max_size() else @c ARENE_PRECONDITION violation.
2011 ARENE_NODISCARD friend constexpr auto operator+(inline_string const& lhs, string_view const rhs) noexcept
2012 -> inline_string {
2013 ARENE_PRECONDITION(lhs.size() + rhs.size() <= lhs.max_size());
2014 inline_string res{lhs};
2015 std::ignore = res.append(rhs);
2016 return res;
2017 }
2018 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
2019 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
2020
2021 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
2022 // parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "Hidden friends permitted by A11-3-1 Permit #2"
2023 /// @brief Concatenate two strings
2024 ///
2025 /// @param lhs The first string to concatenate
2026 /// @param rhs The second string to concatenate
2027 /// @return inline_string holding the concatenation of the two strings.
2028 /// @pre @c lhs.size()+rhs.size()<=rhs.max_size() else @c ARENE_PRECONDITION violation.
2029 ARENE_NODISCARD friend constexpr auto operator+(string_view const lhs, inline_string const& rhs) noexcept
2030 -> inline_string {
2031 ARENE_PRECONDITION(lhs.size() + rhs.size() <= rhs.max_size());
2032 inline_string res{lhs};
2033 std::ignore = res.append(rhs);
2034 return res;
2035 }
2036 // parasoft-end-suppress AUTOSAR-A11_3_1-a-2
2037 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
2038
2039 private:
2040 /// @brief Tag-dispatch implementation helpers for @c inline_string::try_construct(first,last) .
2041 ///
2042 /// @tparam Itr The type of the iterator.
2043 /// @param first The start of the sequence to construct from.
2044 /// @param last The end of the sequence to construct from.
2045 /// @return optional<inline_string> If @c std::distance(first,last)>MaxLength a null optional, else an optional
2046 /// populated is if via @c inline_string{first,last} .
2047 template <typename Itr>
2048 static constexpr auto do_try_construct(std::random_access_iterator_tag, Itr first, Itr last) noexcept
2049 -> optional<inline_string> {
2050 if (::arene::base::distance(first, last) > static_cast<difference_type>(MaxSize)) {
2051 return nullopt;
2052 }
2053 return {inline_string{first, last}};
2054 }
2055
2056 /// @brief Tag-dispatch implementation helpers for @c inline_string::try_construct(first,last) .
2057 ///
2058 /// @tparam Itr The type of the iterator.
2059 /// @param first The start of the sequence to construct from.
2060 /// @param last The end of the sequence to construct from.
2061 /// @return optional<inline_string> If @c std::distance(first,last)>MaxLength a null optional, else an optional
2062 /// populated is if via @c inline_string{first,last} .
2063 template <typename Itr>
2064 static constexpr auto do_try_construct(std::input_iterator_tag, Itr first, Itr last) noexcept
2065 -> optional<inline_string> {
2066 inline_string str;
2067 while ((str.size() < str.max_size()) && (first != last)) {
2068 str.push_back(*(first++));
2069 }
2070 if (first != last) {
2071 return nullopt;
2072 }
2073 return str;
2074 }
2075
2076 /// @brief Tag-dispatch implementation helpers for @c inline_string::insert(pos,first,last) .
2077 ///
2078 /// @tparam Itr The type of the iterator.
2079 /// @param pos The location to start the insert
2080 /// @param first The start of the sequence to insert.
2081 /// @param last The end of the sequence to insert.
2082 /// @return iterator An iterator to the beginning of the insertion.
2083 template <typename Itr>
2084 constexpr auto do_insert(std::input_iterator_tag, const_iterator pos, Itr first, Itr last) -> iterator {
2085 auto const offset = pos - cbegin();
2086 std::ignore = insert(static_cast<size_type>(offset), inline_string{first, last});
2087 return begin() + offset;
2088 }
2089 /// @brief Tag-dispatch implementation helpers for @c inline_string::insert(pos,first,last) .
2090 ///
2091 /// @tparam Itr The type of the iterator.
2092 /// @param pos The location to start the insert
2093 /// @param first The start of the sequence to insert.
2094 /// @param last The end of the sequence to insert.
2095 /// @return iterator An iterator to the beginning of the insertion.
2096 template <typename Itr>
2097 constexpr auto do_insert(std::random_access_iterator_tag, const_iterator pos, Itr first, Itr last) -> iterator {
2098 auto const offset = pos - cbegin();
2099 auto const distance = last - first;
2100 ARENE_PRECONDITION(distance >= 0);
2101 auto const insertion_location = prepare_insert(static_cast<size_type>(offset), static_cast<size_type>(distance));
2102 std::ignore = ::arene::base::copy(first, last, insertion_location);
2103 return insertion_location;
2104 }
2105
2106 /// @brief Copy from the source span without bounds checking
2107 ///
2108 /// @param str the source data
2109 /// @post @c size()==str.size()
2110 /// @post The content of this string is equivalent to the content of @c str
2111 constexpr void copy_from_unchecked(string_view str) noexcept {
2112 std::ignore = arene::base::copy(str.begin(), str.end(), begin());
2113 set_null_terminator_to(str.size());
2114 }
2115
2116 /// @brief Copy from the source span with bounds checking.
2117 ///
2118 /// @param str the source data
2119 /// @pre @c str.size() is less than or equal to @c MaxLength else @c ARENE_PRECONDITION violation
2120 /// @post @c size()==str.size()
2121 /// @post The content of this string is equivalent to the content of @c str
2122 constexpr void copy_from(string_view str) noexcept {
2123 ARENE_PRECONDITION(str.size() <= MaxSize);
2124 copy_from_unchecked(str);
2125 }
2126
2127 /// @brief Copy from the source string
2128 ///
2129 /// @tparam SourceMaxLength The length of the source string. Must be less than or equal to @c MaxLength
2130 /// @param str the source data
2131 /// @post @c size()==str.size()
2132 /// @post The content of this string is equivalent to the content of @c str
2133 template <std::size_t SourceMaxLength, constraints<std::enable_if_t<SourceMaxLength <= MaxSize>> = nullptr>
2134 constexpr void copy_from(inline_string<SourceMaxLength> str) noexcept {
2135 copy_from_unchecked(string_view(str));
2136 }
2137
2138 /// @brief Copy from the source string
2139 ///
2140 /// @tparam SourceMaxLength The length of the source string. Must be greater than @c MaxLength
2141 /// @param str the source data
2142 /// @pre @c str.size() is less than or equal to @c MaxLength else @c ARENE_PRECONDITION violation
2143 /// @post @c size()==str.size()
2144 /// @post The content of this string is equivalent to the content of @c str
2145 template <std::size_t SourceMaxLength, constraints<std::enable_if_t<(SourceMaxLength > MaxSize)>> = nullptr>
2146 constexpr void copy_from(inline_string<SourceMaxLength> str) noexcept {
2147 copy_from(string_view(str));
2148 }
2149
2150 /// @brief Copy from the source NUL-terminated string
2151 ///
2152 /// @param str Pointer to the source string
2153 /// @pre @c str must not be a null pointer, else @c ARENE_PRECONDITION violation.
2154 /// @pre The length of @c str must be less than @c MaxLength , else @c ARENE_PRECONDITION violation.
2155 /// @pre @c str must point to a NUL-terminated string, else behavior is undefined.
2156 /// @post @c size() is the length of @c str
2157 /// @post The content of this string is equivalent to the content of @c str
2158 constexpr void copy_from(detail::raw_c_string str) noexcept {
2159 ARENE_PRECONDITION(str != nullptr);
2160 copy_from(string_view{str});
2161 }
2162
2163 /// @brief Copy from a pair of iterators
2164 ///
2165 /// @tparam Itr The type of the iterator.
2166 /// @param first The start of the sequence to insert.
2167 /// @param last The end of the sequence to insert.
2168 /// @pre @c std::distance(first,last)<=MaxSize else @c ARENE_PRECONDITION violation
2169 /// @post @c size() is the length of @c str
2170 /// @post The content of this string is equivalent to the content of @c str
2171 template <typename Itr>
2172 constexpr void copy_from(std::input_iterator_tag, Itr first, Itr last) noexcept {
2173 for (auto const chr : make_subrange(first, last)) {
2174 push_back(chr);
2175 }
2176 }
2177 /// @brief Copy from a pair of iterators
2178 ///
2179 /// @tparam Itr The type of the iterator.
2180 /// @param first The start of the sequence to insert.
2181 /// @param last The end of the sequence to insert.
2182 /// @pre @c std::distance(first,last)<=MaxSize else @c ARENE_PRECONDITION violation
2183 /// @post @c size() is the length of @c str
2184 /// @post The content of this string is equivalent to the content of @c str
2185 template <typename Itr>
2186 constexpr void copy_from(std::random_access_iterator_tag, Itr first, Itr last) noexcept {
2187 auto const source_length = ::arene::base::distance(first, last);
2188 ARENE_PRECONDITION(source_length >= 0);
2189 auto const usource_length = static_cast<size_type>(source_length);
2190 ARENE_PRECONDITION(usource_length <= max_size());
2191 std::ignore = ::arene::base::copy(first, last, begin());
2192 set_null_terminator_to(usource_length);
2193 }
2194
2195 /// @brief Prepare for an insert of the specified length at the specified position.
2196 ///
2197 /// Increases the length and moves the characters, so the @c insertion_length characters at @c pos can be
2198 /// overwritten.
2199 /// @param pos The position the insert will occur.
2200 /// @param insertion_length The length of the insertion.
2201 /// @return iterator An iterator to the location to perform the insertion.
2202 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
2203 /// @pre @c MaxLength-size()>=insertion_length else @c ARENE_PRECONDITION violation.
2204 /// @post @c size() is increased by @c insertion_length .
2205 /// @post The characters in the range @c [pos,insertion_length) are now located in the range
2206 /// @c [insertion_length,size())
2207 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
2208 constexpr auto prepare_insert(size_type pos, size_type insertion_length) noexcept -> iterator {
2209 ARENE_PRECONDITION(pos <= this->size());
2210 ARENE_PRECONDITION(max_size() - this->size() >= insertion_length);
2211 std::ignore = ::arene::base::copy(
2212 rbegin(),
2213 rbegin() + static_cast<std::ptrdiff_t>(this->size() - pos),
2214 rbegin() - static_cast<std::ptrdiff_t>(insertion_length)
2215 );
2216 set_null_terminator_to(this->size() + insertion_length);
2217 return begin() + static_cast<difference_type>(pos);
2218 }
2219
2220 /// @brief Prepare for a replacement of the specified length at the specified position with a new string of the
2221 /// specified replacement length.
2222 ///
2223 /// Increases or decreases the length and moves the characters, so the @c original_length characters at @c pos can
2224 /// be overwritten with @c replacement_length new characters.
2225 /// @param pos The position the insert will occur
2226 /// @param original_length The number of characters being replaced
2227 /// @param replacement_length The number of characters in the replacement
2228 /// @pre @c pos<=size() else @c ARENE_PRECONDITION violation.
2229 /// @pre @c size()-removal_length+replacement_length<=(MaxLength) else @c ARENE_PRECONDITION violation.
2230 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
2231 constexpr void prepare_replace(size_type pos, size_type original_length, size_type replacement_length) {
2232 ARENE_PRECONDITION(pos <= this->size());
2233 auto const removal_length = std::min(original_length, this->size() - pos);
2234 ARENE_PRECONDITION(this->size() - removal_length + replacement_length <= MaxSize);
2235 if (removal_length > replacement_length) {
2236 std::ignore = erase(pos + replacement_length, removal_length - replacement_length);
2237 } else {
2238 std::ignore = prepare_insert(pos + removal_length, replacement_length - removal_length);
2239 }
2240 }
2241
2242 /// @brief Sets the null terminator to the desired index.
2243 ///
2244 /// @param pos The index into buffer to place the null terminator.
2245 /// @post @c size()==pos
2246 /// @post @c buffer_[size()]=='\0'
2247 constexpr void set_null_terminator_to(size_type pos) {
2248 this->set_size(pos);
2249 buffer_[this->size()] = '\0';
2250 }
2251
2252 /// @brief The stored characters
2253 arene::base::array<detail::character, MaxSize + 1> buffer_{};
2254};
2255// parasoft-end-suppress AUTOSAR-A10_1_1-a-2
2256
2257template <std::size_t MaxLength>
2258constexpr std::size_t inline_string<MaxLength>::npos;
2259
2260namespace inline_string_detail {
2261
2262/// @brief helper for @c is_inline_string_v
2263/// @tparam Type type to check
2264template <typename Type, typename = constraints<>>
2265extern constexpr bool is_inline_string_v = false;
2266
2267/// @brief helper for @c is_inline_string_v
2268/// @tparam Capacity capacity of the inline string
2269template <std::size_t Capacity>
2270extern constexpr bool is_inline_string_v<inline_string<Capacity>> = true;
2271
2272} // namespace inline_string_detail
2273
2274/// @brief Trait to query if a type is an @c inline_string.
2275/// @tparam Type The type to check.
2276///
2277/// @c true if @c Type is a cv-qualified instantiation of @c inline_string. Otherwise, @c false.
2278template <typename Type>
2279extern constexpr bool is_inline_string_v = inline_string_detail::is_inline_string_v<std::remove_cv_t<Type>>;
2280
2281/// @brief Trait to query if a type is an @c inline_string.
2282/// @tparam Type The type to check.
2283///
2284/// Inherits from @c std::true_type if @c Type is an
2285/// instantiation of @c inline_string, else @c std::false_type.
2286template <typename Type>
2287class is_inline_string : public std::integral_constant<bool, is_inline_string_v<Type>> {};
2288
2289/// @brief Trait to query if a type is an @c inline_string.
2290/// @tparam Type The type to check.
2291///
2292/// @c true if @c Type is a cv-qualified instantiation of @c inline_string. Otherwise, @c false.
2293template <typename Type>
2294extern constexpr bool is_inline_buffer_string_v = is_inline_string_v<Type>;
2295
2296/// @brief Trait to query if a type is an @c inline_string.
2297/// @tparam Type The type to check.
2298///
2299/// Inherits from @c std::true_type if @c Type is an
2300/// instantiation of @c inline_string, else @c std::false_type.
2301template <typename Type>
2302using is_inline_buffer_string = is_inline_string<Type>;
2303
2304namespace inline_string_detail {
2305
2306/// @brief helper for constructing an @c inline_string
2307class make_inline_string_impl_fn {
2308 public:
2309 /// @brief Construct from a C-array of characters (e.g. a string literal)
2310 /// @tparam N the size of the source character array
2311 /// @param str The string to copy from
2312 /// @pre @c str must have a NUL terminator somewhere in it
2313 /// @post The content of this string compares equal to @c str
2314 /// @return @c str as an @c inline_string
2315 template <std::size_t N, constraints<std::enable_if_t<N != 0>> = nullptr>
2316 // NOLINTNEXTLINE(hicpp-avoid-c-arrays) allows use of string literals
2317 constexpr auto operator()(detail::character const (&str)[N]) const noexcept -> inline_string<N - 1U> {
2318 return inline_string<N - 1U>{str};
2319 }
2320};
2321
2322} // namespace inline_string_detail
2323
2324/// @def arene::base::make_inline_string
2325/// @brief helper for constructing an @c inline_string that deduces the capacity template parameter
2326// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
2327// object used in multiple TUs."
2328// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
2329// object used in multiple TUs."
2330ARENE_CPP14_INLINE_VARIABLE(inline_string_detail::make_inline_string_impl_fn, make_inline_string);
2331// parasoft-end-suppress AUTOSAR-M7_3_3-a
2332// parasoft-end-suppress CERT_CPP-DCL59-a
2333
2334} // namespace base
2335} // namespace arene
2336
2337#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_STRINGS_INLINE_STRING_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10