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 " \
66template <
typename T,
size_t kCapacity =
string_impl::kGeneric>
82 string_impl::kGeneric>::const_reverse_iterator;
92 Fill(data(), ch, count);
95 template <
size_t kOtherCapacity>
100 CopySubstr(data(), other.data(), other.size(), index, count);
105 Copy(data(),
string, count);
108 template <
typename U,
109 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
112 c_string, string_impl::BoundedStringLength(c_string, kCapacity)) {}
114 template <
size_t kCharArraySize>
118 string_impl::NullTerminatedArrayFitsInString(kCharArraySize, kCapacity),
119 _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY);
120 Copy(data(), array, string_impl::ArrayStringLength(array, max_size()));
123 template <
typename Iterator,
124 typename = containers::internal::EnableIfInputIterator<Iterator>>
127 CopyIterator(data(), start, finish);
135 template <
size_t kOtherCapacity>
139 kOtherCapacity == string_impl::kGeneric || kOtherCapacity <= kCapacity,
140 _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING);
157 typename StringViewLike,
158 string_impl::EnableIfStringViewLikeButNotStringView<T, StringViewLike>* =
167 std::enable_if_t<std::is_same<StringView, string_impl::View<T>>::value>* =
172 template <
typename StringView,
173 typename = string_impl::EnableIfStringViewLike<T, StringView>>
178 const string_impl::View<T> view = string;
179 CopySubstr(data(), view.data(), view.size(), index, count);
190 template <
size_t kOtherCapacity>
193 return assign<kOtherCapacity>(other);
196 template <
size_t kCharArraySize>
198 return assign<kCharArraySize>(array);
202 template <
typename U,
203 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
205 return assign(c_string);
209 static_assert(kCapacity != 0,
210 "Cannot assign a character to pw::InlineString<0>");
211 return assign(1, ch);
218 template <
typename StringView,
219 typename = string_impl::EnableIfStringViewLike<T, StringView>>
221 return assign(
string);
226 template <
size_t kOtherCapacity>
229 return append(
string);
233 push_back(character);
237 template <
size_t kCharArraySize>
239 return append(array);
242 template <
typename U,
243 typename = string_impl::EnableIfNonArrayCharPointer<T, U>>
245 return append(c_string);
249 return append(list.begin(), list.size());
252 template <
typename StringView,
253 typename = string_impl::EnableIfStringViewLike<T, StringView>>
255 return append(
string);
264 constexpr pointer data() {
return buffer_; }
265 constexpr const_pointer data()
const {
return buffer_; }
270 constexpr size_t max_size()
const noexcept {
return kCapacity; }
275#include "pw_string/internal/string_common_functions.inc"
294 T buffer_[kCapacity + 1];
303 using value_type = T;
304 using size_type = string_impl::size_type;
305 using difference_type = std::ptrdiff_t;
306 using reference = value_type&;
307 using const_reference =
const value_type&;
308 using pointer = value_type*;
309 using const_pointer =
const value_type*;
314 using reverse_iterator = std::reverse_iterator<iterator>;
315 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
317 static constexpr size_t npos = string_impl::kGeneric;
325 constexpr pointer data()
noexcept {
328 constexpr const_pointer data()
const noexcept {
332 constexpr size_t size()
const noexcept {
return length_; }
333 constexpr size_t max_size()
const noexcept {
return capacity_; }
338#include "pw_string/internal/string_common_functions.inc"
342 : capacity_(string_impl::CheckedCastToSize(capacity)), length_(0) {}
356 constexpr void PushBack(T* data, T ch);
358 constexpr void PopBack(T* data) {
360 SetSizeAndTerminate(data, size() - 1);
366 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count);
370 template <
typename InputIterator>
392 template <
typename InputIterator>
402 constexpr void Resize(T* data,
size_t new_size, T ch);
404 constexpr void set_size(
size_t length) {
405 length_ = string_impl::CheckedCastToSize(length);
407 constexpr void SetSizeAndTerminate(T* data,
size_t length) {
408 PW_ASSERT(length <= max_size());
409 string_impl::char_traits<T>::assign(data[length], T());
414 static_assert(std::is_same_v<char, T> || std::is_same_v<wchar_t, T> ||
416 std::is_same_v<char8_t, T> ||
418 std::is_same_v<char16_t, T> ||
419 std::is_same_v<char32_t, T> || std::is_same_v<std::byte, T>,
420 "Only character types and std::byte are supported");
428 static constexpr size_t kCapacity = string_impl::kGeneric;
436#ifdef __cpp_deduction_guides
449template <
typename T,
size_t kCharArraySize>
459template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
460constexpr bool operator==(
463 return lhs.compare(rhs) == 0;
466template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
467constexpr bool operator!=(
468 const InlineBasicString<T, kLhsCapacity>& lhs,
469 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
470 return lhs.compare(rhs) != 0;
473template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
474constexpr bool operator<(
475 const InlineBasicString<T, kLhsCapacity>& lhs,
476 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
477 return lhs.compare(rhs) < 0;
480template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
481constexpr bool operator<=(
482 const InlineBasicString<T, kLhsCapacity>& lhs,
483 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
484 return lhs.compare(rhs) <= 0;
487template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
488constexpr bool operator>(
489 const InlineBasicString<T, kLhsCapacity>& lhs,
490 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
491 return lhs.compare(rhs) > 0;
494template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
495constexpr bool operator>=(
496 const InlineBasicString<T, kLhsCapacity>& lhs,
497 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
498 return lhs.compare(rhs) >= 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;
561template <
typename T,
size_t kLhsCapacity>
562constexpr bool operator>=(
const InlineBasicString<T, kLhsCapacity>& lhs,
564 return lhs.compare(rhs) >= 0;
567template <
typename T,
size_t kRhsCapacity>
568constexpr bool operator>=(
const T* lhs,
569 const InlineBasicString<T, kRhsCapacity>& rhs) {
570 return rhs.compare(lhs) <= 0;
579template <
size_t kCapacity =
string_impl::kGeneric>
585template <
size_t kCapacity =
string_impl::kGeneric>
595 PW_ASSERT(size() < max_size());
596 string_impl::char_traits<T>::assign(data[size()], ch);
597 SetSizeAndTerminate(data, size() + 1);
601constexpr InlineBasicString<T, string_impl::kGeneric>&
602InlineBasicString<T, string_impl::kGeneric>::Copy(T* data,
605 PW_ASSERT(new_size <= max_size());
606 string_impl::char_traits<T>::copy(data, source, new_size);
607 SetSizeAndTerminate(data, new_size);
612constexpr InlineBasicString<T, string_impl::kGeneric>&
613InlineBasicString<T, string_impl::kGeneric>::CopySubstr(
614 T* data,
const T* source,
size_t source_size,
size_t index,
size_t count) {
615 PW_ASSERT(index <= source_size);
616 return Copy(data, source + index, std::min(count, source_size - index));
620constexpr InlineBasicString<T, string_impl::kGeneric>&
621InlineBasicString<T, string_impl::kGeneric>::CopyExtend(T* data,
625 PW_ASSERT(index <= size());
626 PW_ASSERT(count <= max_size() - index);
627 string_impl::char_traits<T>::copy(data + index, source, count);
628 SetSizeAndTerminate(data, std::max(size(), index + count));
633constexpr InlineBasicString<T, string_impl::kGeneric>&
634InlineBasicString<T, string_impl::kGeneric>::CopyExtendSubstr(
641 PW_ASSERT(source_index <= source_size);
642 return CopyExtend(data,
644 source + source_index,
645 std::min(count, source_size - source_index));
650template <
typename InputIterator>
651constexpr InlineBasicString<T, string_impl::kGeneric>&
652InlineBasicString<T, string_impl::kGeneric>::CopyIterator(T* data,
656 string_impl::IteratorCopy(begin, end, data, data + max_size());
657 SetSizeAndTerminate(data, length);
662template <
typename InputIterator>
663constexpr InlineBasicString<T, string_impl::kGeneric>&
664InlineBasicString<T, string_impl::kGeneric>::CopyIteratorExtend(
665 T* data,
size_t index, InputIterator begin, InputIterator end) {
667 string_impl::IteratorCopy(begin, end, data + index, data + max_size());
668 SetSizeAndTerminate(data, std::max(size(), index + length));
673constexpr InlineBasicString<T, string_impl::kGeneric>&
674InlineBasicString<T, string_impl::kGeneric>::Fill(T* data,
677 PW_ASSERT(new_size <= max_size());
678 string_impl::char_traits<T>::assign(data, new_size, fill_char);
679 SetSizeAndTerminate(data, new_size);
684constexpr InlineBasicString<T, string_impl::kGeneric>&
685InlineBasicString<T, string_impl::kGeneric>::FillExtend(T* data,
689 PW_ASSERT(index <= size());
690 PW_ASSERT(count <= max_size() - index);
691 string_impl::char_traits<T>::assign(data + index, count, fill_char);
692 SetSizeAndTerminate(data, std::max(size(), index + count));
697constexpr InlineBasicString<T, string_impl::kGeneric>&
698InlineBasicString<T, string_impl::kGeneric>::MoveExtend(T* data,
701 PW_ASSERT(index <= size());
702 PW_ASSERT(new_index <= max_size());
703 PW_ASSERT(size() - index <= max_size() - new_index);
704 string_impl::char_traits<T>::move(
705 data + new_index, data + index, size() - index);
706 SetSizeAndTerminate(data, size() - index + new_index);
711constexpr void InlineBasicString<T, string_impl::kGeneric>::Resize(
712 T* data,
size_t new_size, T ch) {
713 PW_ASSERT(new_size <= max_size());
715 if (new_size > size()) {
716 string_impl::char_traits<T>::assign(data + size(), new_size - size(), ch);
719 SetSizeAndTerminate(data, new_size);
724#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_ARRAY
725#undef _PW_STRING_CAPACITY_TOO_SMALL_FOR_STRING
pw::InlineBasicString is a fixed-capacity version of std::basic_string. In brief:
Definition: string.h:68
Definition: string_builder.h:89
Definition: ptr_iterator.h:164
Definition: ptr_iterator.h:142
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:122
The Pigweed namespace.
Definition: alignment.h:27