22#include <initializer_list>
26#include "pw_assert/assert.h"
27#include "pw_containers/internal/traits.h"
28#include "pw_containers/ptr_iterator.h"
29#include "pw_preprocessor/compiler.h"
30#include "pw_string/internal/string_impl.h"
33#define _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY \
34 "The pw::InlineString's capacity is too small to hold the assigned string " \
35 "literal or character array. When assigning a literal or array to a " \
36 "pw::InlineString, the pw::InlineString's capacity must be large enough " \
37 "for the entire string, not counting the null terminator."
39#define _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING \
40 "When assigning one pw::InlineString with known capacity to another, the " \
41 "capacity of the destination pw::InlineString must be at least as large as " \
64template <
typename T,
size_t kCapacity =
string_impl::kGeneric>
80 string_impl::kGeneric>::const_reverse_iterator;
90 Fill(data(), ch, count);
93 template <
size_t kOtherCapacity>
98 CopySubstr(data(), other.data(), other.size(), index, count);
103 Copy(data(),
string, count);
106 template <
typename U,
107 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
110 c_string, string_impl::BoundedStringLength(c_string, kCapacity)) {}
112 template <
size_t kCharArraySize>
116 string_impl::NullTerminatedArrayFitsInString(kCharArraySize, kCapacity),
117 _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY);
118 Copy(data(), array, string_impl::ArrayStringLength(array, max_size()));
121 template <
typename Iterator,
122 typename = containers::internal::EnableIfInputIterator<Iterator>>
125 CopyIterator(data(), start, finish);
133 template <
size_t kOtherCapacity>
137 kOtherCapacity == string_impl::kGeneric || kOtherCapacity <= kCapacity,
138 _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING);
155 typename StringViewLike,
156 string_impl::EnableIfStringViewLikeButNotStringView<T, StringViewLike>* =
165 std::enable_if_t<std::is_same<StringView, string_impl::View<T>>::value>* =
170 template <
typename StringView,
171 typename = string_impl::EnableIfStringViewLike<T, StringView>>
176 const string_impl::View<T> view = string;
177 CopySubstr(data(), view.data(), view.size(), index, count);
188 template <
size_t kOtherCapacity>
191 return assign<kOtherCapacity>(other);
194 template <
size_t kCharArraySize>
196 return assign<kCharArraySize>(array);
200 template <
typename U,
201 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
203 return assign(c_string);
207 static_assert(kCapacity != 0,
208 "Cannot assign a character to pw::InlineString<0>");
209 return assign(1, ch);
216 template <
typename StringView,
217 typename = string_impl::EnableIfStringViewLike<T, StringView>>
219 return assign(
string);
224 template <
size_t kOtherCapacity>
227 return append(
string);
231 push_back(character);
235 template <
size_t kCharArraySize>
237 return append(array);
240 template <
typename U,
241 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
243 return append(c_string);
247 return append(list.begin(), list.size());
250 template <
typename StringView,
251 typename = string_impl::EnableIfStringViewLike<T, StringView>>
253 return append(
string);
262 constexpr pointer data() {
return buffer_; }
263 constexpr const_pointer data()
const {
return buffer_; }
268 constexpr size_t max_size()
const noexcept {
return kCapacity; }
273#include "pw_string/internal/string_common_functions.inc"
292 T buffer_[kCapacity + 1];
301 using value_type = T;
302 using size_type = string_impl::size_type;
303 using difference_type = std::ptrdiff_t;
304 using reference = value_type&;
305 using const_reference =
const value_type&;
306 using pointer = value_type*;
307 using const_pointer =
const value_type*;
312 using reverse_iterator = std::reverse_iterator<iterator>;
313 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
315 static constexpr size_t npos = string_impl::kGeneric;
323 constexpr pointer data()
noexcept {
326 constexpr const_pointer data()
const noexcept {
330 constexpr size_t size()
const noexcept {
return length_; }
331 constexpr size_t max_size()
const noexcept {
return capacity_; }
336#include "pw_string/internal/string_common_functions.inc"
340 : capacity_(string_impl::CheckedCastToSize(capacity)), length_(0) {}
354 constexpr void PushBack(T* data, T ch);
356 constexpr void PopBack(T* data) {
358 SetSizeAndTerminate(data, size() - 1);
364 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count);
368 template <
typename InputIterator>
390 template <
typename InputIterator>
400 constexpr void Resize(T* data,
size_t new_size, T ch);
402 constexpr void set_size(
size_t length) {
403 length_ = string_impl::CheckedCastToSize(length);
405 constexpr void SetSizeAndTerminate(T* data,
size_t length) {
406 PW_ASSERT(length <= max_size());
407 string_impl::char_traits<T>::assign(data[length], T());
412 static_assert(std::is_same_v<char, T> || std::is_same_v<wchar_t, T> ||
414 std::is_same_v<char8_t, T> ||
416 std::is_same_v<char16_t, T> ||
417 std::is_same_v<char32_t, T> || std::is_same_v<std::byte, T>,
418 "Only character types and std::byte are supported");
426 static constexpr size_t kCapacity = string_impl::kGeneric;
434#ifdef __cpp_deduction_guides
447template <
typename T,
size_t kCharArraySize>
457template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
458constexpr bool operator==(
461 return lhs.compare(rhs) == 0;
464template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
465constexpr bool operator!=(
466 const InlineBasicString<T, kLhsCapacity>& lhs,
467 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
468 return lhs.compare(rhs) != 0;
471template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
472constexpr bool operator<(
473 const InlineBasicString<T, kLhsCapacity>& lhs,
474 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
475 return lhs.compare(rhs) < 0;
478template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
479constexpr bool operator<=(
480 const InlineBasicString<T, kLhsCapacity>& lhs,
481 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
482 return lhs.compare(rhs) <= 0;
485template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
486constexpr bool operator>(
487 const InlineBasicString<T, kLhsCapacity>& lhs,
488 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
489 return lhs.compare(rhs) > 0;
492template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
493constexpr bool operator>=(
494 const InlineBasicString<T, kLhsCapacity>& lhs,
495 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
496 return lhs.compare(rhs) >= 0;
499template <
typename T,
size_t kLhsCapacity>
500constexpr bool operator==(
const InlineBasicString<T, kLhsCapacity>& lhs,
502 return lhs.compare(rhs) == 0;
505template <
typename T,
size_t kRhsCapacity>
506constexpr bool operator==(
const T* lhs,
507 const InlineBasicString<T, kRhsCapacity>& rhs) {
508 return rhs.compare(lhs) == 0;
511template <
typename T,
size_t kLhsCapacity>
512constexpr bool operator!=(
const InlineBasicString<T, kLhsCapacity>& lhs,
514 return lhs.compare(rhs) != 0;
517template <
typename T,
size_t kRhsCapacity>
518constexpr bool operator!=(
const T* lhs,
519 const InlineBasicString<T, kRhsCapacity>& rhs) {
520 return rhs.compare(lhs) != 0;
523template <
typename T,
size_t kLhsCapacity>
524constexpr bool operator<(
const InlineBasicString<T, kLhsCapacity>& lhs,
526 return lhs.compare(rhs) < 0;
529template <
typename T,
size_t kRhsCapacity>
530constexpr bool operator<(
const T* lhs,
531 const InlineBasicString<T, kRhsCapacity>& rhs) {
532 return rhs.compare(lhs) >= 0;
535template <
typename T,
size_t kLhsCapacity>
536constexpr bool operator<=(
const InlineBasicString<T, kLhsCapacity>& lhs,
538 return lhs.compare(rhs) <= 0;
541template <
typename T,
size_t kRhsCapacity>
542constexpr bool operator<=(
const T* lhs,
543 const InlineBasicString<T, kRhsCapacity>& rhs) {
544 return rhs.compare(lhs) >= 0;
547template <
typename T,
size_t kLhsCapacity>
548constexpr bool operator>(
const InlineBasicString<T, kLhsCapacity>& lhs,
550 return lhs.compare(rhs) > 0;
553template <
typename T,
size_t kRhsCapacity>
554constexpr bool operator>(
const T* lhs,
555 const InlineBasicString<T, kRhsCapacity>& rhs) {
556 return rhs.compare(lhs) <= 0;
559template <
typename T,
size_t kLhsCapacity>
560constexpr bool operator>=(
const InlineBasicString<T, kLhsCapacity>& lhs,
562 return lhs.compare(rhs) >= 0;
565template <
typename T,
size_t kRhsCapacity>
566constexpr bool operator>=(
const T* lhs,
567 const InlineBasicString<T, kRhsCapacity>& rhs) {
568 return rhs.compare(lhs) <= 0;
577template <
size_t kCapacity =
string_impl::kGeneric>
583template <
size_t kCapacity =
string_impl::kGeneric>
591 PW_ASSERT(size() < max_size());
592 string_impl::char_traits<T>::assign(data[size()], ch);
593 SetSizeAndTerminate(data, size() + 1);
597constexpr InlineBasicString<T, string_impl::kGeneric>&
598InlineBasicString<T, string_impl::kGeneric>::Copy(T* data,
601 PW_ASSERT(new_size <= max_size());
602 string_impl::char_traits<T>::copy(data, source, new_size);
603 SetSizeAndTerminate(data, new_size);
608constexpr InlineBasicString<T, string_impl::kGeneric>&
609InlineBasicString<T, string_impl::kGeneric>::CopySubstr(
610 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count) {
611 PW_ASSERT(index <= source_size);
612 return Copy(data, source + index, std::min(count, source_size - index));
616constexpr InlineBasicString<T, string_impl::kGeneric>&
617InlineBasicString<T, string_impl::kGeneric>::CopyExtend(T* data,
621 PW_ASSERT(index <= size());
622 PW_ASSERT(count <= max_size() - index);
623 string_impl::char_traits<T>::copy(data + index, source, count);
624 SetSizeAndTerminate(data, std::max(size(), index + count));
629constexpr InlineBasicString<T, string_impl::kGeneric>&
630InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr(
637 PW_ASSERT(source_index <= source_size);
638 return CopyExtend(data,
640 source + source_index,
641 std::min(count, source_size - source_index));
646template <
typename InputIterator>
647constexpr InlineBasicString<T, string_impl::kGeneric>&
648InlineBasicString<T, string_impl::kGeneric>::CopyIterator(T* data,
652 string_impl::IteratorCopy(begin, end, data, data + max_size());
653 SetSizeAndTerminate(data, length);
658template <
typename InputIterator>
659constexpr InlineBasicString<T, string_impl::kGeneric>&
660InlineBasicString<T, string_impl::kGeneric>::CopyIteratorExtend(
661 T* data,
size_t index, InputIterator begin, InputIterator end) {
663 string_impl::IteratorCopy(begin, end, data + index, data + max_size());
664 SetSizeAndTerminate(data, std::max(size(), index + length));
669constexpr InlineBasicString<T, string_impl::kGeneric>&
670InlineBasicString<T, string_impl::kGeneric>::Fill(T* data,
673 PW_ASSERT(new_size <= max_size());
674 string_impl::char_traits<T>::assign(data, new_size, fill_char);
675 SetSizeAndTerminate(data, new_size);
680constexpr InlineBasicString<T, string_impl::kGeneric>&
681InlineBasicString<T, string_impl::kGeneric>::FillExtend(T* data,
685 PW_ASSERT(index <= size());
686 PW_ASSERT(count <= max_size() - index);
687 string_impl::char_traits<T>::assign(data + index, count, fill_char);
688 SetSizeAndTerminate(data, std::max(size(), index + count));
693constexpr InlineBasicString<T, string_impl::kGeneric>&
694InlineBasicString<T, string_impl::kGeneric>::MoveExtend(T* data,
697 PW_ASSERT(index <= size());
698 PW_ASSERT(new_index <= max_size());
699 PW_ASSERT(size() - index <= max_size() - new_index);
700 string_impl::char_traits<T>::move(
701 data + new_index, data + index, size() - index);
702 SetSizeAndTerminate(data, size() - index + new_index);
707constexpr void InlineBasicString<T, string_impl::kGeneric>::Resize(
708 T* data,
size_t new_size, T ch) {
709 PW_ASSERT(new_size <= max_size());
711 if (new_size > size()) {
712 string_impl::char_traits<T>::assign(data + size(), new_size - size(), ch);
715 SetSizeAndTerminate(data, new_size);
720#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY
721#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING
pw::InlineBasicString is a fixed-capacity version of std::basic_string. In brief:
Definition: string.h:66
Definition: string_builder.h:87
Definition: ptr_iterator.h:159
Definition: ptr_iterator.h:137
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
StatusWithSize Copy(std::string_view source, Span &&dest)
pw::string::Copy is a safer alternative to std::strncpy as it always null-terminates whenever the des...
Definition: util.h:120