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;
447template <
typename T,
size_t kCharArraySize>
455template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
456constexpr bool operator==(
459 return lhs.compare(rhs) == 0;
462template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
463constexpr bool operator!=(
464 const InlineBasicString<T, kLhsCapacity>& lhs,
465 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
466 return lhs.compare(rhs) != 0;
469template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
470constexpr bool operator<(
471 const InlineBasicString<T, kLhsCapacity>& lhs,
472 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
473 return lhs.compare(rhs) < 0;
476template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
477constexpr bool operator<=(
478 const InlineBasicString<T, kLhsCapacity>& lhs,
479 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
480 return lhs.compare(rhs) <= 0;
483template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
484constexpr bool operator>(
485 const InlineBasicString<T, kLhsCapacity>& lhs,
486 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
487 return lhs.compare(rhs) > 0;
490template <
typename T,
size_t kLhsCapacity,
size_t kRhsCapacity>
491constexpr bool operator>=(
492 const InlineBasicString<T, kLhsCapacity>& lhs,
493 const InlineBasicString<T, kRhsCapacity>& rhs)
noexcept {
494 return lhs.compare(rhs) >= 0;
497template <
typename T,
size_t kLhsCapacity>
498constexpr bool operator==(
const InlineBasicString<T, kLhsCapacity>& lhs,
500 return lhs.compare(rhs) == 0;
503template <
typename T,
size_t kRhsCapacity>
504constexpr bool operator==(
const T* lhs,
505 const InlineBasicString<T, kRhsCapacity>& rhs) {
506 return rhs.compare(lhs) == 0;
509template <
typename T,
size_t kLhsCapacity>
510constexpr bool operator!=(
const InlineBasicString<T, kLhsCapacity>& lhs,
512 return lhs.compare(rhs) != 0;
515template <
typename T,
size_t kRhsCapacity>
516constexpr bool operator!=(
const T* lhs,
517 const InlineBasicString<T, kRhsCapacity>& rhs) {
518 return rhs.compare(lhs) != 0;
521template <
typename T,
size_t kLhsCapacity>
522constexpr bool operator<(
const InlineBasicString<T, kLhsCapacity>& lhs,
524 return lhs.compare(rhs) < 0;
527template <
typename T,
size_t kRhsCapacity>
528constexpr bool operator<(
const T* lhs,
529 const InlineBasicString<T, kRhsCapacity>& rhs) {
530 return rhs.compare(lhs) >= 0;
533template <
typename T,
size_t kLhsCapacity>
534constexpr bool operator<=(
const InlineBasicString<T, kLhsCapacity>& lhs,
536 return lhs.compare(rhs) <= 0;
539template <
typename T,
size_t kRhsCapacity>
540constexpr bool operator<=(
const T* lhs,
541 const InlineBasicString<T, kRhsCapacity>& rhs) {
542 return rhs.compare(lhs) >= 0;
545template <
typename T,
size_t kLhsCapacity>
546constexpr bool operator>(
const InlineBasicString<T, kLhsCapacity>& lhs,
548 return lhs.compare(rhs) > 0;
551template <
typename T,
size_t kRhsCapacity>
552constexpr bool operator>(
const T* lhs,
553 const InlineBasicString<T, kRhsCapacity>& rhs) {
554 return rhs.compare(lhs) <= 0;
557template <
typename T,
size_t kLhsCapacity>
558constexpr bool operator>=(
const InlineBasicString<T, kLhsCapacity>& lhs,
560 return lhs.compare(rhs) >= 0;
563template <
typename T,
size_t kRhsCapacity>
564constexpr bool operator>=(
const T* lhs,
565 const InlineBasicString<T, kRhsCapacity>& rhs) {
566 return rhs.compare(lhs) <= 0;
575template <
size_t kCapacity =
string_impl::kGeneric>
581template <
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:68
Definition: string_builder.h:86
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:110
The Pigweed namespace.
Definition: alignment.h:27