72 Visitor v{
this,
nullptr};
92 return c_str()[index];
96 static char dummy =
'\0';
105 static char dummy =
'\0';
114 static char dummy =
'\0';
123 if (
empty())
return '\0';
128 if (
empty())
return '\0';
133 if (index >=
mLength)
return '\0';
134 return c_str()[index];
189 fl::size len = view.
length;
235 fl::size existingLen =
mLength;
237 if (existingLen > 0 && existingData) {
246 if (!newData->hasCapacity(newLen)) {
249 if (existingLen > 0 && existingData) {
250 fl::memcpy(newData->data(), existingData, existingLen);
252 fl::memcpy(newData->data() + existingLen, str, n);
253 newData->data()[newLen] =
'\0';
260 if (hasHeapData() && heapData().
get().use_count() <= 1) {
262 if (!heap->hasCapacity(newLen)) {
265 const char* bufStart = heap->data();
266 fl::size grow_length =
fl::max(3, newLen * 3 / 2);
267 if (str >= bufStart && str < bufStart + mLength + 1) {
268 fl::size
offset =
static_cast<fl::size
>(str - bufStart);
269 heap->grow(grow_length);
270 str = heap->data() +
offset;
272 heap->grow(grow_length);
276 if (!heap->hasCapacity(newLen)) {
282 heap->data()[mLength] =
'\0';
284 }
else if (hasHeapData()) {
287 if (!newData->hasCapacity(newLen)) {
292 fl::memcpy(newData->data(), heap->data(), mLength);
293 fl::memcpy(newData->data() + mLength, str, n);
294 newData->data()[newLen] =
'\0';
300 if (newLen + 1 <= mInlineCapacity) {
303 fl::memcpy(inlineBufferPtr() + mLength, str, n);
306 inlineBufferPtr()[mLength] =
'\0';
311 if (!newData->hasCapacity(newLen)) {
315 fl::memcpy(newData->data(), inlineBufferPtr(), mLength);
316 fl::memcpy(newData->data() + mLength, str, n);
317 newData->data()[newLen] =
'\0';
338#if FL_PLATFORM_HAS_LARGE_MEMORY
344 int len =
fl::utoa32(val > 0xFFFFFFFFull ? 0xFFFFFFFFu
345 :
static_cast<fl::u32
>(val),
348 return write(buf, len);
353#if FL_PLATFORM_HAS_LARGE_MEMORY
360 fl::i32 narrow = val > 2147483647LL ? 2147483647
361 : val < -2147483648LL ? -2147483648
362 :
static_cast<fl::i32
>(val);
371 return write(buf, len);
376 int len =
fl::itoa(
static_cast<fl::i32
>(val), buf, 10);
377 return write(buf, len);
417 fl::size len = other.size();
418 if (other.hasHeapData()) {
426 const char* src = other.c_str();
438 fl::size actualCount = count;
442 if (actualCount > 0) {
469 if (
pos >= str.size()) {
473 fl::size actualCount = count;
474 if (actualCount ==
npos ||
pos + actualCount > str.size()) {
475 actualCount = str.size() -
pos;
477 copy(str.c_str() +
pos, actualCount);
491 for (fl::size i = 0; i < count; ++i) {
498 for (fl::size i = 0; i < count; ++i) {
501 ptr->data()[count] =
'\0';
514 if (newCapacity <=
mLength)
return;
519 if (!heap->hasCapacity(newCapacity)) {
520 heap->grow(newCapacity);
523 if (heap->hasCapacity(
mLength)) {
531 if (!newData->hasCapacity(newCapacity)) {
535 newData->data()[
mLength] =
'\0';
553 if (heap->capacity() <=
mLength + 1)
return;
568 for (fl::size i = 0; i <
mLength; ++i) {
575 if (!substr)
return npos;
576 auto begin_ptr =
c_str();
577 const char* found =
fl::strstr(begin_ptr, substr);
578 if (found)
return found - begin_ptr;
584 for (fl::size i = start_pos; i <
mLength; ++i) {
592 auto begin_ptr =
c_str() + start_pos;
593 const char* found =
fl::strstr(begin_ptr, substr);
594 if (found)
return found -
c_str();
606 const char* str =
c_str();
607 for (fl::size i = searchPos + 1; i > 0; --i) {
608 if (str[i - 1] == c)
return i - 1;
614 if (!s || count == 0) {
619 fl::size maxStart =
mLength - count;
621 if (searchStart + count >
mLength) searchStart = maxStart;
622 const char* str =
c_str();
623 for (fl::size i = searchStart + 1; i > 0; --i) {
624 fl::size idx = i - 1;
625 if (idx + count >
mLength)
continue;
627 for (fl::size j = 0; j < count; ++j) {
628 if (str[idx + j] != s[j]) { match =
false;
break; }
630 if (match)
return idx;
645 if (!s || count == 0)
return npos;
647 const char* str =
c_str();
649 for (fl::size j = 0; j < count; ++j) {
650 if (str[i] == s[j])
return i;
667 if (!s || count == 0)
return npos;
670 const char* str =
c_str();
671 for (fl::size i = searchPos + 1; i > 0; --i) {
672 for (fl::size j = 0; j < count; ++j) {
673 if (str[i - 1] == s[j])
return i - 1;
691 const char* str =
c_str();
693 if (str[i] != c)
return i;
701 const char* str =
c_str();
703 bool found_in_set =
false;
704 for (fl::size j = 0; j < count; ++j) {
705 if (str[i] == s[j]) { found_in_set =
true;
break; }
707 if (!found_in_set)
return i;
724 const char* str =
c_str();
725 for (fl::size i = searchPos + 1; i > 0; --i) {
726 if (str[i - 1] != c)
return i - 1;
732 if (!s || count == 0) {
739 const char* str =
c_str();
740 for (fl::size i = searchPos + 1; i > 0; --i) {
741 bool found_in_set =
false;
742 for (fl::size j = 0; j < count; ++j) {
743 if (str[i - 1] == s[j]) { found_in_set =
true;
break; }
745 if (!found_in_set)
return i - 1;
770 if (!prefix)
return true;
772 if (prefix_len >
mLength)
return false;
777 if (!suffix)
return true;
779 if (suffix_len >
mLength)
return false;
806 if (count == 0)
return *
this;
813 fl::size newLen =
mLength + count;
820 for (fl::size i = 0; i < count; ++i) newData->data()[
pos + i] = ch;
822 newData->data()[newLen] =
'\0';
841 if (canInsertInPlace) {
843 canInsertInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
844 if (canInsertInPlace) {
845 char*
data = heap->data();
847 for (fl::size i = 0; i < count; ++i)
data[
pos + i] = ch;
852 if (!canInsertInPlace) {
854 const char* src =
c_str();
856 for (fl::size i = 0; i < count; ++i) newData->data()[
pos + i] = ch;
858 newData->data()[newLen] =
'\0';
866 if (!s)
return *
this;
871 return insert(
pos, str.c_str(), str.size());
875 if (pos2 >= str.size())
return *
this;
876 fl::size actualCount = count;
877 if (actualCount ==
npos || pos2 + actualCount > str.size()) {
878 actualCount = str.size() - pos2;
880 return insert(
pos, str.c_str() + pos2, actualCount);
885 if (!s || count == 0)
return *
this;
892 fl::size newLen =
mLength + count;
901 newData->data()[newLen] =
'\0';
920 if (canInsertInPlace) {
922 canInsertInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
923 if (canInsertInPlace) {
924 char*
data = heap->data();
931 if (!canInsertInPlace) {
933 const char* src =
c_str();
937 newData->data()[newLen] =
'\0';
949 fl::size actualCount = count;
953 if (actualCount == 0)
return *
this;
960 fl::size remainingLen =
mLength -
pos - actualCount;
961 if (remainingLen > 0) {
962 fl::memcpy(newData->data() +
pos, heap->data() +
pos + actualCount, remainingLen);
965 newData->data()[
mLength] =
'\0';
970 fl::size remainingLen =
mLength -
pos - actualCount;
971 if (remainingLen > 0) {
983 return replace(
pos, count, str.c_str(), str.size());
988 if (pos2 >= str.size())
return erase(
pos, count);
989 fl::size actualCount2 = count2;
990 if (actualCount2 ==
npos || pos2 + actualCount2 > str.size()) {
991 actualCount2 = str.size() - pos2;
993 return replace(
pos, count, str.c_str() + pos2, actualCount2);
1005 fl::size actualCount = count;
1009 fl::size newLen =
mLength - actualCount + count2;
1017 fl::size remainingLen =
mLength -
pos - actualCount;
1018 if (remainingLen > 0) {
1019 fl::memcpy(newData->data() +
pos + count2, heap->data() +
pos + actualCount, remainingLen);
1021 newData->data()[newLen] =
'\0';
1029 if (count2 != actualCount) {
1030 fl::size remainingLen =
mLength -
pos - actualCount;
1031 if (remainingLen > 0) {
1043 if (canReplaceInPlace) {
1045 canReplaceInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
1046 if (canReplaceInPlace) {
1047 char*
data = heap->data();
1048 if (count2 != actualCount) {
1049 fl::size remainingLen =
mLength -
pos - actualCount;
1050 if (remainingLen > 0) {
1059 if (!canReplaceInPlace) {
1061 const char* src =
c_str();
1064 fl::size remainingLen =
mLength -
pos - actualCount;
1065 if (remainingLen > 0) {
1066 fl::memcpy(newData->data() +
pos + count2, src +
pos + actualCount, remainingLen);
1068 newData->data()[newLen] =
'\0';
1088 fl::size actualCount = count;
1092 fl::size newLen =
mLength - actualCount + count2;
1099 for (fl::size i = 0; i < count2; ++i) newData->data()[
pos + i] = ch;
1100 fl::size remainingLen =
mLength -
pos - actualCount;
1101 if (remainingLen > 0) {
1102 fl::memcpy(newData->data() +
pos + count2, heap->data() +
pos + actualCount, remainingLen);
1104 newData->data()[newLen] =
'\0';
1112 if (count2 != actualCount) {
1113 fl::size remainingLen =
mLength -
pos - actualCount;
1114 if (remainingLen > 0) {
1126 if (canReplaceInPlace) {
1128 canReplaceInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
1129 if (canReplaceInPlace) {
1130 char*
data = heap->data();
1131 if (count2 != actualCount) {
1132 fl::size remainingLen =
mLength -
pos - actualCount;
1133 if (remainingLen > 0) {
1137 for (fl::size i = 0; i < count2; ++i)
data[
pos + i] = ch;
1142 if (!canReplaceInPlace) {
1144 const char* src =
c_str();
1146 for (fl::size i = 0; i < count2; ++i) newData->data()[
pos + i] = ch;
1147 fl::size remainingLen =
mLength -
pos - actualCount;
1148 if (remainingLen > 0) {
1149 fl::memcpy(newData->data() +
pos + count2, src +
pos + actualCount, remainingLen);
1151 newData->data()[newLen] =
'\0';
1164 return str.empty() ? 0 : -1;
1166 fl::size actualCount1 = count1;
1167 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1168 actualCount1 =
mLength - pos1;
1170 fl::size minLen = (actualCount1 < str.size()) ? actualCount1 : str.size();
1173 if (actualCount1 < str.size())
return -1;
1174 if (actualCount1 > str.size())
return 1;
1180 if (pos1 >
mLength || pos2 >= str.size()) {
1181 if (pos1 >
mLength && pos2 >= str.size())
return 0;
1182 if (pos1 >
mLength)
return -1;
1185 fl::size actualCount1 = count1;
1186 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1187 actualCount1 =
mLength - pos1;
1189 fl::size actualCount2 = count2;
1190 if (actualCount2 ==
npos || pos2 + actualCount2 > str.size()) {
1191 actualCount2 = str.size() - pos2;
1193 fl::size minLen = (actualCount1 < actualCount2) ? actualCount1 : actualCount2;
1196 if (actualCount1 < actualCount2)
return -1;
1197 if (actualCount1 > actualCount2)
return 1;
1202 if (!s)
return mLength > 0 ? 1 : 0;
1208 if (pos1 >=
mLength)
return 0;
1209 fl::size actualCount1 = count1;
1210 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1211 actualCount1 =
mLength - pos1;
1213 return (actualCount1 > 0) ? 1 : 0;
1215 if (pos1 >
mLength)
return (s[0] ==
'\0') ? 0 : -1;
1216 fl::size actualCount1 = count1;
1217 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1218 actualCount1 =
mLength - pos1;
1221 fl::size minLen = (actualCount1 < sLen) ? actualCount1 : sLen;
1224 if (actualCount1 < sLen)
return -1;
1225 if (actualCount1 > sLen)
return 1;
1231 if (pos1 >=
mLength)
return (count2 == 0) ? 0 : -1;
1232 fl::size actualCount1 = count1;
1233 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1234 actualCount1 =
mLength - pos1;
1236 return (actualCount1 > 0) ? 1 : ((count2 == 0) ? 0 : -1);
1238 if (pos1 >
mLength)
return (count2 == 0) ? 0 : -1;
1239 fl::size actualCount1 = count1;
1240 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1241 actualCount1 =
mLength - pos1;
1243 fl::size minLen = (actualCount1 < count2) ? actualCount1 : count2;
1246 if (actualCount1 < count2)
return -1;
1247 if (actualCount1 > count2)
return 1;
1254 if (other.isInline()) {
1263 other.mStorage.reset();
1264 other.inlineBufferPtr()[0] =
'\0';
1268 if (
this == &other)
return;
1269 if (other.isInline()) {
1278 other.mStorage.reset();
1279 other.inlineBufferPtr()[0] =
'\0';
1283 if (
this == &other)
return;
1286 bool otherInline = other.isInline();
1288 if (!thisInline && !otherInline) {
1292 }
else if (thisInline && otherInline) {
1295 bool otherFits =
mLength + 1 <= other.mInlineCapacity;
1296 if (thisFits && otherFits) {
1299 for (fl::size i = 0; i <= maxLen; ++i) {
1302 other.inlineBufferPtr()[i] = tmp;
1312 fl::size otherLen = other.mLength;
1321 other.mStorage.reset();
1322 fl::memcpy(other.inlineBufferPtr(), thisData->data(), thisLen + 1);
1324 other.mStorage = thisData;
1326 other.mLength = thisLen;
1328 }
else if (thisInline) {
1335 other.mStorage.reset();
1336 if (thisLen + 1 <= other.mInlineCapacity) {
1342 other.mLength = thisLen;
1345 other.swapWith(*
this);
1357 if (
data && len > 0) {
1364 if (!holder || holder->length() == 0)
return;
1392 write(
static_cast<fl::u16
>(val));
1406 write(
static_cast<fl::i32
>(val));
1450 return append(
static_cast<float>(val));
1454 write(str.c_str(), str.size());
1491 fl::size additional_chars = count -
mLength;
1496 if (
capacity() <= count) {
return; }
1497 for (fl::size i = 0; i < additional_chars; ++i) {
Concrete type-erased string class operating on a caller- provided buffer (or fl::span<char>).
A fixed-size array implementation similar to std::array.
int compare(const basic_string &str) const FL_NO_EXCEPT
const char * constData() const FL_NO_EXCEPT
char & at(fl::size pos) FL_NO_EXCEPT
bool isNonOwning() const FL_NO_EXCEPT
void materialize() FL_NO_EXCEPT
fl::size find_first_not_of(char c, fl::size pos=0) const FL_NO_EXCEPT
void setSharedHolder(const fl::shared_ptr< StringHolder > &holder) FL_NO_EXCEPT
void clear(bool freeMemory=false) FL_NO_EXCEPT
char * c_str_mutable() FL_NO_EXCEPT
void swapWith(basic_string &other) FL_NO_EXCEPT
bool starts_with(const char *prefix) const FL_NO_EXCEPT
bool operator<=(const basic_string &other) const FL_NO_EXCEPT
void moveFrom(basic_string &&other) FL_NO_EXCEPT
NotNullStringHolderPtr & heapData() FL_NO_EXCEPT
bool operator>=(const basic_string &other) const FL_NO_EXCEPT
char back() const FL_NO_EXCEPT
basic_string & replace(fl::size pos, fl::size count, const basic_string &str) FL_NO_EXCEPT
bool hasHeapData() const FL_NO_EXCEPT
void pop_back() FL_NO_EXCEPT
bool ends_with(const char *suffix) const FL_NO_EXCEPT
basic_string & appendHex(i32 val) FL_NO_EXCEPT
basic_string & appendOct(i32 val) FL_NO_EXCEPT
float toFloat() const FL_NO_EXCEPT
static constexpr fl::size npos
fl::size find(const char &value) const FL_NO_EXCEPT
bool operator==(const basic_string &other) const FL_NO_EXCEPT
void push_back(char c) FL_NO_EXCEPT
void reserve(fl::size newCapacity) FL_NO_EXCEPT
basic_string(char *inlineBuffer, fl::size inlineCapacity) FL_NO_EXCEPT
fl::size rfind(char c, fl::size pos=npos) const FL_NO_EXCEPT
char operator[](fl::size index) const FL_NO_EXCEPT
char * inlineBufferPtr() FL_NO_EXCEPT
char charAt(fl::size index) const FL_NO_EXCEPT
void setView(const char *data, fl::size len) FL_NO_EXCEPT
fl::size find_first_of(char c, fl::size pos=0) const FL_NO_EXCEPT
bool isInline() const FL_NO_EXCEPT
fl::variant< NotNullStringHolderPtr, ConstLiteral, ConstView > mStorage
fl::size find_last_of(char c, fl::size pos=npos) const FL_NO_EXCEPT
bool operator!=(const basic_string &other) const FL_NO_EXCEPT
void setLiteral(const char *literal) FL_NO_EXCEPT
void push_ascii(char c) FL_NO_EXCEPT
bool empty() const FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
bool operator>(const basic_string &other) const FL_NO_EXCEPT
const char * data() const FL_NO_EXCEPT
char front() const FL_NO_EXCEPT
bool operator<(const basic_string &other) const FL_NO_EXCEPT
fl::size write(const fl::u8 *data, fl::size n) FL_NO_EXCEPT
void resize(fl::size count) FL_NO_EXCEPT
void shrink_to_fit() FL_NO_EXCEPT
fl::size find_last_not_of(char c, fl::size pos=npos) const FL_NO_EXCEPT
void moveAssign(basic_string &&other) FL_NO_EXCEPT
~basic_string() FL_DTOR_NOEXCEPT
basic_string & insert(fl::size pos, fl::size count, char ch) FL_NO_EXCEPT
void copy(const char *str) FL_NO_EXCEPT
bool contains(const char *substr) const FL_NO_EXCEPT
void assign(const char *str, fl::size len) FL_NO_EXCEPT
fl::size capacity() const FL_NO_EXCEPT
basic_string & erase(fl::size pos=0, fl::size count=npos) FL_NO_EXCEPT
basic_string & append(const char *str) FL_NO_EXCEPT
Concrete type-erased string class.
constexpr const T & get() const FL_NO_EXCEPT
long use_count() const FL_NO_EXCEPT
constexpr string_view() FL_NO_EXCEPT
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
void replace(Iterator first, Iterator last, const T &old_value, const T &new_value) FL_NO_EXCEPT
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
Iterator find(Iterator first, Iterator last, const T &value) FL_NO_EXCEPT
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
enable_if_t< is_same< T, U >::value > swap(T &a, U &b) FL_NO_EXCEPT
constexpr common_type_t< T, U > max(T a, U b) FL_NO_EXCEPT
int utoa32(u32 value, char *sp, int radix) FL_NO_EXCEPT
Convert unsigned 32-bit integer to string buffer in given radix.
u8 u8 fract8 blur_amount FL_NO_EXCEPT
constexpr int type_rank< T >::value
fl::not_null< StringHolderPtr > NotNullStringHolderPtr
FASTLED_FORCE_INLINE int strcmp(const char *s1, const char *s2) FL_NO_EXCEPT
void clear(CRGB(&arr)[N]) FL_NO_EXCEPT
FASTLED_FORCE_INLINE void * memmove(void *dest, const void *src, size_t n) FL_NO_EXCEPT
int itoa64(i64 value, char *sp, int radix) FL_NO_EXCEPT
Convert signed 64-bit integer to string buffer in given radix.
FASTLED_FORCE_INLINE void * memcpy(void *dest, const void *src, size_t n) FL_NO_EXCEPT
int itoa(i32 value, char *sp, int radix) FL_NO_EXCEPT
Convert signed 32-bit integer to string buffer in given radix.
FASTLED_FORCE_INLINE const char * strstr(const char *haystack, const char *needle) FL_NO_EXCEPT
expected< T, E > result
Alias for expected (Rust-style naming)
int utoa64(u64 value, char *sp, int radix) FL_NO_EXCEPT
Convert unsigned 64-bit integer to string buffer in given radix.
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) FL_NO_EXCEPT
float parseFloat(const char *str, fl::size len) FL_NO_EXCEPT
Parse a floating point number from a character buffer.
void ftoa(float value, char *buffer, int precision) FL_NO_EXCEPT
Convert floating point number to string buffer.
To * bit_cast_ptr(void *storage) FL_NO_EXCEPT
FASTLED_FORCE_INLINE int strncmp(const char *s1, const char *s2, size_t n) FL_NO_EXCEPT
FASTLED_FORCE_INLINE size_t strlen(const char *s) FL_NO_EXCEPT
Base definition for an LED controller.
#define FL_DISABLE_WARNING(warning)
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_POP