22#include <initializer_list>
26#include "pw_assert/assert.h"
27#include "pw_preprocessor/compiler.h"
28#include "pw_string/internal/string_impl.h"
31#define _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY \
32 "The pw::InlineString's capacity is too small to hold the assigned string " \
33 "literal or character array. When assigning a literal or array to a " \
34 "pw::InlineString, the pw::InlineString's capacity must be large enough " \
35 "for the entire string, not counting the null terminator."
37#define _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING \
38 "When assigning one pw::InlineString with known capacity to another, the " \
39 "capacity of the destination pw::InlineString must be at least as large as " \
62template <
typename T,
size_t kCapacity =
string_impl::kGeneric>
78 string_impl::kGeneric>::const_reverse_iterator;
88 Fill(data(), ch, count);
91 template <
size_t kOtherCapacity>
96 CopySubstr(data(), other.data(), other.size(), index, count);
101 Copy(data(),
string, count);
104 template <
typename U,
105 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
108 c_string, string_impl::BoundedStringLength(c_string, kCapacity)) {}
110 template <
size_t kCharArraySize>
114 string_impl::NullTerminatedArrayFitsInString(kCharArraySize, kCapacity),
115 _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY);
116 Copy(data(), array, string_impl::ArrayStringLength(array, max_size()));
119 template <
typename InputIterator,
120 typename = string_impl::EnableIfInputIterator<InputIterator>>
123 CopyIterator(data(), start, finish);
131 template <
size_t kOtherCapacity>
135 kOtherCapacity == string_impl::kGeneric || kOtherCapacity <= kCapacity,
136 _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING);
153 typename StringViewLike,
154 string_impl::EnableIfStringViewLikeButNotStringView<T, StringViewLike>* =
163 std::enable_if_t<std::is_same<StringView, string_impl::View<T>>::value>* =
168 template <
typename StringView,
169 typename = string_impl::EnableIfStringViewLike<T, StringView>>
174 const string_impl::View<T> view = string;
175 CopySubstr(data(), view.data(), view.size(), index, count);
186 template <
size_t kOtherCapacity>
189 return assign<kOtherCapacity>(other);
192 template <
size_t kCharArraySize>
194 return assign<kCharArraySize>(array);
198 template <
typename U,
199 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
201 return assign(c_string);
205 static_assert(kCapacity != 0,
206 "Cannot assign a character to pw::InlineString<0>");
207 return assign(1, ch);
214 template <
typename StringView,
215 typename = string_impl::EnableIfStringViewLike<T, StringView>>
217 return assign(
string);
222 template <
size_t kOtherCapacity>
225 return append(
string);
229 push_back(character);
233 template <
size_t kCharArraySize>
235 return append(array);
238 template <
typename U,
239 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
241 return append(c_string);
245 return append(list.begin(), list.size());
248 template <
typename StringView,
249 typename = string_impl::EnableIfStringViewLike<T, StringView>>
251 return append(
string);
260 constexpr pointer data() {
return buffer_; }
261 constexpr const_pointer data()
const {
return buffer_; }
266 constexpr size_t max_size()
const noexcept {
return kCapacity; }
271#include "pw_string/internal/string_common_functions.inc"
290 T buffer_[kCapacity + 1];
299 using value_type = T;
300 using size_type = string_impl::size_type;
301 using difference_type = std::ptrdiff_t;
302 using reference = value_type&;
303 using const_reference =
const value_type&;
304 using pointer = value_type*;
305 using const_pointer =
const value_type*;
306 using iterator = value_type*;
307 using const_iterator =
const value_type*;
308 using reverse_iterator = std::reverse_iterator<iterator>;
309 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
311 static constexpr size_t npos = string_impl::kGeneric;
319 constexpr pointer data()
noexcept {
322 constexpr const_pointer data()
const noexcept {
326 constexpr size_t size()
const noexcept {
return length_; }
327 constexpr size_t max_size()
const noexcept {
return capacity_; }
332#include "pw_string/internal/string_common_functions.inc"
336 : capacity_(string_impl::CheckedCastToSize(capacity)), length_(0) {}
344 constexpr void PushBack(T* data, T ch);
346 constexpr void PopBack(T* data) {
348 SetSizeAndTerminate(data, size() - 1);
354 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count);
358 template <
typename InputIterator>
380 template <
typename InputIterator>
390 constexpr void Resize(T* data,
size_t new_size, T ch);
392 constexpr void set_size(
size_t length) {
393 length_ = string_impl::CheckedCastToSize(length);
395 constexpr void SetSizeAndTerminate(T* data,
size_t length) {
396 PW_ASSERT(length <= max_size());
397 string_impl::char_traits<T>::assign(data[length], T());
402 static_assert(std::is_same_v<char, T> || std::is_same_v<wchar_t, T> ||
404 std::is_same_v<char8_t, T> ||
406 std::is_same_v<char16_t, T> ||
407 std::is_same_v<char32_t, T> || std::is_same_v<std::byte, T>,
408 "Only character types and std::byte are supported");
416 static constexpr size_t kCapacity = string_impl::kGeneric;
424#ifdef __cpp_deduction_guides
437template <
typename T,
size_t kCharArraySize>
447template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
448constexpr bool operator==(
451 return lhs.compare(rhs) == 0;
454template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
455constexpr bool operator!=(
456 const InlineBasicString<T, kLhsCapacity>& lhs,
457 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
458 return lhs.compare(rhs) != 0;
461template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
462constexpr bool operator<(
463 const InlineBasicString<T, kLhsCapacity>& lhs,
464 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
465 return lhs.compare(rhs) < 0;
468template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
469constexpr bool operator<=(
470 const InlineBasicString<T, kLhsCapacity>& lhs,
471 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
472 return lhs.compare(rhs) <= 0;
475template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
476constexpr bool operator>(
477 const InlineBasicString<T, kLhsCapacity>& lhs,
478 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
479 return lhs.compare(rhs) > 0;
482template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
483constexpr bool operator>=(
484 const InlineBasicString<T, kLhsCapacity>& lhs,
485 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
486 return lhs.compare(rhs) >= 0;
489template <
typename T,
size_t kLhsCapacity>
490constexpr bool operator==(
const InlineBasicString<T, kLhsCapacity>& lhs,
492 return lhs.compare(rhs) == 0;
495template <
typename T,
size_t kRhsCapacity>
496constexpr bool operator==(
const T* lhs,
497 const InlineBasicString<T, kRhsCapacity>& rhs) {
498 return rhs.compare(lhs) == 0;
501template <
typename T,
size_t kLhsCapacity>
502constexpr bool operator!=(
const InlineBasicString<T, kLhsCapacity>& lhs,
504 return lhs.compare(rhs) != 0;
507template <
typename T,
size_t kRhsCapacity>
508constexpr bool operator!=(
const T* lhs,
509 const InlineBasicString<T, kRhsCapacity>& rhs) {
510 return rhs.compare(lhs) != 0;
513template <
typename T,
size_t kLhsCapacity>
514constexpr bool operator<(
const InlineBasicString<T, kLhsCapacity>& lhs,
516 return lhs.compare(rhs) < 0;
519template <
typename T,
size_t kRhsCapacity>
520constexpr bool operator<(
const T* lhs,
521 const InlineBasicString<T, kRhsCapacity>& rhs) {
522 return rhs.compare(lhs) >= 0;
525template <
typename T,
size_t kLhsCapacity>
526constexpr bool operator<=(
const InlineBasicString<T, kLhsCapacity>& lhs,
528 return lhs.compare(rhs) <= 0;
531template <
typename T,
size_t kRhsCapacity>
532constexpr bool operator<=(
const T* lhs,
533 const InlineBasicString<T, kRhsCapacity>& rhs) {
534 return rhs.compare(lhs) >= 0;
537template <
typename T,
size_t kLhsCapacity>
538constexpr bool operator>(
const InlineBasicString<T, kLhsCapacity>& lhs,
540 return lhs.compare(rhs) > 0;
543template <
typename T,
size_t kRhsCapacity>
544constexpr bool operator>(
const T* lhs,
545 const InlineBasicString<T, kRhsCapacity>& rhs) {
546 return rhs.compare(lhs) <= 0;
549template <
typename T,
size_t kLhsCapacity>
550constexpr bool operator>=(
const InlineBasicString<T, kLhsCapacity>& lhs,
552 return lhs.compare(rhs) >= 0;
555template <
typename T,
size_t kRhsCapacity>
556constexpr bool operator>=(
const T* lhs,
557 const InlineBasicString<T, kRhsCapacity>& rhs) {
558 return rhs.compare(lhs) <= 0;
567template <
size_t kCapacity =
string_impl::kGeneric>
573template <
size_t kCapacity =
string_impl::kGeneric>
581 PW_ASSERT(size() < max_size());
582 string_impl::char_traits<T>::assign(data[size()], ch);
583 SetSizeAndTerminate(data, size() + 1);
587constexpr InlineBasicString<T, string_impl::kGeneric>&
588InlineBasicString<T, string_impl::kGeneric>::Copy(T* data,
591 PW_ASSERT(new_size <= max_size());
592 string_impl::char_traits<T>::copy(data, source, new_size);
593 SetSizeAndTerminate(data, new_size);
598constexpr InlineBasicString<T, string_impl::kGeneric>&
599InlineBasicString<T, string_impl::kGeneric>::CopySubstr(
600 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count) {
601 PW_ASSERT(index <= source_size);
602 return Copy(data, source + index, std::min(count, source_size - index));
606constexpr InlineBasicString<T, string_impl::kGeneric>&
607InlineBasicString<T, string_impl::kGeneric>::CopyExtend(T* data,
611 PW_ASSERT(index <= size());
612 PW_ASSERT(count <= max_size() - index);
613 string_impl::char_traits<T>::copy(data + index, source, count);
614 SetSizeAndTerminate(data, std::max(size(), index + count));
619constexpr InlineBasicString<T, string_impl::kGeneric>&
620InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr(
627 PW_ASSERT(source_index <= source_size);
628 return CopyExtend(data,
630 source + source_index,
631 std::min(count, source_size - source_index));
636template <
typename InputIterator>
637constexpr InlineBasicString<T, string_impl::kGeneric>&
638InlineBasicString<T, string_impl::kGeneric>::CopyIterator(T* data,
642 string_impl::IteratorCopy(begin, end, data, data + max_size());
643 SetSizeAndTerminate(data, length);
648template <
typename InputIterator>
649constexpr InlineBasicString<T, string_impl::kGeneric>&
650InlineBasicString<T, string_impl::kGeneric>::CopyIteratorExtend(
651 T* data,
size_t index, InputIterator begin, InputIterator end) {
653 string_impl::IteratorCopy(begin, end, data + index, data + max_size());
654 SetSizeAndTerminate(data, std::max(size(), index + length));
659constexpr InlineBasicString<T, string_impl::kGeneric>&
660InlineBasicString<T, string_impl::kGeneric>::Fill(T* data,
663 PW_ASSERT(new_size <= max_size());
664 string_impl::char_traits<T>::assign(data, new_size, fill_char);
665 SetSizeAndTerminate(data, new_size);
670constexpr InlineBasicString<T, string_impl::kGeneric>&
671InlineBasicString<T, string_impl::kGeneric>::FillExtend(T* data,
675 PW_ASSERT(index <= size());
676 PW_ASSERT(count <= max_size() - index);
677 string_impl::char_traits<T>::assign(data + index, count, fill_char);
678 SetSizeAndTerminate(data, std::max(size(), index + count));
683constexpr InlineBasicString<T, string_impl::kGeneric>&
684InlineBasicString<T, string_impl::kGeneric>::MoveExtend(T* data,
687 PW_ASSERT(index <= size());
688 PW_ASSERT(new_index <= max_size());
689 PW_ASSERT(size() - index <= max_size() - new_index);
690 string_impl::char_traits<T>::move(
691 data + new_index, data + index, size() - index);
692 SetSizeAndTerminate(data, size() - index + new_index);
697constexpr void InlineBasicString<T, string_impl::kGeneric>::Resize(
698 T* data,
size_t new_size, T ch) {
699 PW_ASSERT(new_size <= max_size());
701 if (new_size > size()) {
702 string_impl::char_traits<T>::assign(data + size(), new_size - size(), ch);
705 SetSizeAndTerminate(data, new_size);
710#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY
711#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING
pw::InlineBasicString is a fixed-capacity version of std::basic_string. In brief:
Definition: string.h:64
Definition: string_builder.h:87
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