71 Visitor v{
this,
nullptr};
91 return c_str()[index];
95 static char dummy =
'\0';
104 static char dummy =
'\0';
113 static char dummy =
'\0';
122 if (
empty())
return '\0';
127 if (
empty())
return '\0';
132 if (index >=
mLength)
return '\0';
133 return c_str()[index];
188 fl::size len = view.
length;
215 return write(str, n);
222 return write(str, 1);
233 if (existingLen > 0 && existingData) {
242 if (existingLen > 0 && existingData) {
243 fl::memcpy(newData->data(), existingData, existingLen);
245 fl::memcpy(newData->data() + existingLen, str, n);
246 newData->data()[newLen] =
'\0';
255 if (!heap->hasCapacity(newLen)) {
258 const char* bufStart = heap->data();
259 fl::size grow_length =
fl::max(3, newLen * 3 / 2);
260 if (str >= bufStart && str < bufStart +
mLength + 1) {
261 fl::size
offset =
static_cast<fl::size
>(str - bufStart);
262 heap->grow(grow_length);
263 str = heap->data() +
offset;
265 heap->grow(grow_length);
279 newData->data()[newLen] =
'\0';
299 newData->data()[newLen] =
'\0';
308 int len =
fl::utoa32(
static_cast<fl::u32
>(n), buf, 10);
309 return write(buf, len);
315 return write(buf, len);
338 int len =
fl::itoa(
static_cast<fl::i32
>(val), buf, 10);
339 return write(buf, len);
379 fl::size len = other.
size();
388 const char* src = other.
c_str();
400 fl::size actualCount = count;
404 if (actualCount > 0) {
435 fl::size actualCount = count;
436 if (actualCount ==
npos ||
pos + actualCount > str.
size()) {
437 actualCount = str.
size() -
pos;
453 for (fl::size i = 0; i < count; ++i) {
460 for (fl::size i = 0; i < count; ++i) {
463 ptr->data()[count] =
'\0';
476 if (newCapacity <=
mLength)
return;
480 if (heap.
get().
use_count() <= 1 && heap->hasCapacity(newCapacity)) {
486 newData->data()[
mLength] =
'\0';
504 if (heap->capacity() <=
mLength + 1)
return;
519 for (fl::size i = 0; i <
mLength; ++i) {
526 if (!substr)
return npos;
527 auto begin_ptr =
c_str();
528 const char* found =
fl::strstr(begin_ptr, substr);
529 if (found)
return found - begin_ptr;
535 for (fl::size i = start_pos; i <
mLength; ++i) {
543 auto begin_ptr =
c_str() + start_pos;
544 const char* found =
fl::strstr(begin_ptr, substr);
545 if (found)
return found -
c_str();
557 const char* str =
c_str();
558 for (fl::size i = searchPos + 1; i > 0; --i) {
559 if (str[i - 1] == c)
return i - 1;
565 if (!s || count == 0) {
570 fl::size maxStart =
mLength - count;
572 if (searchStart + count >
mLength) searchStart = maxStart;
573 const char* str =
c_str();
574 for (fl::size i = searchStart + 1; i > 0; --i) {
575 fl::size idx = i - 1;
576 if (idx + count >
mLength)
continue;
578 for (fl::size j = 0; j < count; ++j) {
579 if (str[idx + j] != s[j]) { match =
false;
break; }
581 if (match)
return idx;
596 if (!s || count == 0)
return npos;
598 const char* str =
c_str();
600 for (fl::size j = 0; j < count; ++j) {
601 if (str[i] == s[j])
return i;
618 if (!s || count == 0)
return npos;
621 const char* str =
c_str();
622 for (fl::size i = searchPos + 1; i > 0; --i) {
623 for (fl::size j = 0; j < count; ++j) {
624 if (str[i - 1] == s[j])
return i - 1;
642 const char* str =
c_str();
644 if (str[i] != c)
return i;
652 const char* str =
c_str();
654 bool found_in_set =
false;
655 for (fl::size j = 0; j < count; ++j) {
656 if (str[i] == s[j]) { found_in_set =
true;
break; }
658 if (!found_in_set)
return i;
675 const char* str =
c_str();
676 for (fl::size i = searchPos + 1; i > 0; --i) {
677 if (str[i - 1] != c)
return i - 1;
683 if (!s || count == 0) {
690 const char* str =
c_str();
691 for (fl::size i = searchPos + 1; i > 0; --i) {
692 bool found_in_set =
false;
693 for (fl::size j = 0; j < count; ++j) {
694 if (str[i - 1] == s[j]) { found_in_set =
true;
break; }
696 if (!found_in_set)
return i - 1;
721 if (!prefix)
return true;
723 if (prefix_len >
mLength)
return false;
728 if (!suffix)
return true;
730 if (suffix_len >
mLength)
return false;
757 if (count == 0)
return *
this;
764 fl::size newLen =
mLength + count;
771 for (fl::size i = 0; i < count; ++i) newData->data()[
pos + i] = ch;
773 newData->data()[newLen] =
'\0';
792 if (canInsertInPlace) {
794 canInsertInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
795 if (canInsertInPlace) {
796 char*
data = heap->data();
798 for (fl::size i = 0; i < count; ++i)
data[
pos + i] = ch;
803 if (!canInsertInPlace) {
805 const char* src =
c_str();
807 for (fl::size i = 0; i < count; ++i) newData->data()[
pos + i] = ch;
809 newData->data()[newLen] =
'\0';
817 if (!s)
return *
this;
826 if (pos2 >= str.
size())
return *
this;
827 fl::size actualCount = count;
828 if (actualCount ==
npos || pos2 + actualCount > str.
size()) {
829 actualCount = str.
size() - pos2;
836 if (!s || count == 0)
return *
this;
843 fl::size newLen =
mLength + count;
852 newData->data()[newLen] =
'\0';
871 if (canInsertInPlace) {
873 canInsertInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
874 if (canInsertInPlace) {
875 char*
data = heap->data();
882 if (!canInsertInPlace) {
884 const char* src =
c_str();
888 newData->data()[newLen] =
'\0';
900 fl::size actualCount = count;
904 if (actualCount == 0)
return *
this;
911 fl::size remainingLen =
mLength -
pos - actualCount;
912 if (remainingLen > 0) {
913 fl::memcpy(newData->data() +
pos, heap->data() +
pos + actualCount, remainingLen);
916 newData->data()[
mLength] =
'\0';
921 fl::size remainingLen =
mLength -
pos - actualCount;
922 if (remainingLen > 0) {
938 fl::size pos2, fl::size count2) {
940 fl::size actualCount2 = count2;
941 if (actualCount2 ==
npos || pos2 + actualCount2 > str.
size()) {
942 actualCount2 = str.
size() - pos2;
956 fl::size actualCount = count;
960 fl::size newLen =
mLength - actualCount + count2;
968 fl::size remainingLen =
mLength -
pos - actualCount;
969 if (remainingLen > 0) {
970 fl::memcpy(newData->data() +
pos + count2, heap->data() +
pos + actualCount, remainingLen);
972 newData->data()[newLen] =
'\0';
980 if (count2 != actualCount) {
981 fl::size remainingLen =
mLength -
pos - actualCount;
982 if (remainingLen > 0) {
994 if (canReplaceInPlace) {
996 canReplaceInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
997 if (canReplaceInPlace) {
998 char*
data = heap->data();
999 if (count2 != actualCount) {
1000 fl::size remainingLen =
mLength -
pos - actualCount;
1001 if (remainingLen > 0) {
1010 if (!canReplaceInPlace) {
1012 const char* src =
c_str();
1015 fl::size remainingLen =
mLength -
pos - actualCount;
1016 if (remainingLen > 0) {
1017 fl::memcpy(newData->data() +
pos + count2, src +
pos + actualCount, remainingLen);
1019 newData->data()[newLen] =
'\0';
1039 fl::size actualCount = count;
1043 fl::size newLen =
mLength - actualCount + count2;
1050 for (fl::size i = 0; i < count2; ++i) newData->data()[
pos + i] = ch;
1051 fl::size remainingLen =
mLength -
pos - actualCount;
1052 if (remainingLen > 0) {
1053 fl::memcpy(newData->data() +
pos + count2, heap->data() +
pos + actualCount, remainingLen);
1055 newData->data()[newLen] =
'\0';
1063 if (count2 != actualCount) {
1064 fl::size remainingLen =
mLength -
pos - actualCount;
1065 if (remainingLen > 0) {
1077 if (canReplaceInPlace) {
1079 canReplaceInPlace = heap.
get().
use_count() <= 1 && heap->hasCapacity(newLen);
1080 if (canReplaceInPlace) {
1081 char*
data = heap->data();
1082 if (count2 != actualCount) {
1083 fl::size remainingLen =
mLength -
pos - actualCount;
1084 if (remainingLen > 0) {
1088 for (fl::size i = 0; i < count2; ++i)
data[
pos + i] = ch;
1093 if (!canReplaceInPlace) {
1095 const char* src =
c_str();
1097 for (fl::size i = 0; i < count2; ++i) newData->data()[
pos + i] = ch;
1098 fl::size remainingLen =
mLength -
pos - actualCount;
1099 if (remainingLen > 0) {
1100 fl::memcpy(newData->data() +
pos + count2, src +
pos + actualCount, remainingLen);
1102 newData->data()[newLen] =
'\0';
1115 return str.
empty() ? 0 : -1;
1117 fl::size actualCount1 = count1;
1118 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1119 actualCount1 =
mLength - pos1;
1121 fl::size minLen = (actualCount1 < str.
size()) ? actualCount1 : str.
size();
1124 if (actualCount1 < str.
size())
return -1;
1125 if (actualCount1 > str.
size())
return 1;
1130 fl::size pos2, fl::size count2)
const {
1132 if (pos1 >
mLength && pos2 >= str.
size())
return 0;
1133 if (pos1 >
mLength)
return -1;
1136 fl::size actualCount1 = count1;
1137 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1138 actualCount1 =
mLength - pos1;
1140 fl::size actualCount2 = count2;
1141 if (actualCount2 ==
npos || pos2 + actualCount2 > str.
size()) {
1142 actualCount2 = str.
size() - pos2;
1144 fl::size minLen = (actualCount1 < actualCount2) ? actualCount1 : actualCount2;
1147 if (actualCount1 < actualCount2)
return -1;
1148 if (actualCount1 > actualCount2)
return 1;
1153 if (!s)
return mLength > 0 ? 1 : 0;
1159 if (pos1 >=
mLength)
return 0;
1160 fl::size actualCount1 = count1;
1161 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1162 actualCount1 =
mLength - pos1;
1164 return (actualCount1 > 0) ? 1 : 0;
1166 if (pos1 >
mLength)
return (s[0] ==
'\0') ? 0 : -1;
1167 fl::size actualCount1 = count1;
1168 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1169 actualCount1 =
mLength - pos1;
1172 fl::size minLen = (actualCount1 < sLen) ? actualCount1 : sLen;
1175 if (actualCount1 < sLen)
return -1;
1176 if (actualCount1 > sLen)
return 1;
1182 if (pos1 >=
mLength)
return (count2 == 0) ? 0 : -1;
1183 fl::size actualCount1 = count1;
1184 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1185 actualCount1 =
mLength - pos1;
1187 return (actualCount1 > 0) ? 1 : ((count2 == 0) ? 0 : -1);
1189 if (pos1 >
mLength)
return (count2 == 0) ? 0 : -1;
1190 fl::size actualCount1 = count1;
1191 if (actualCount1 ==
npos || pos1 + actualCount1 >
mLength) {
1192 actualCount1 =
mLength - pos1;
1194 fl::size minLen = (actualCount1 < count2) ? actualCount1 : count2;
1197 if (actualCount1 < count2)
return -1;
1198 if (actualCount1 > count2)
return 1;
1205 if (other.isInline()) {
1214 other.mStorage.reset();
1215 other.inlineBufferPtr()[0] =
'\0';
1219 if (
this == &other)
return;
1220 if (other.isInline()) {
1229 other.mStorage.reset();
1230 other.inlineBufferPtr()[0] =
'\0';
1234 if (
this == &other)
return;
1237 bool otherInline = other.
isInline();
1239 if (!thisInline && !otherInline) {
1243 }
else if (thisInline && otherInline) {
1247 if (thisFits && otherFits) {
1250 for (fl::size i = 0; i <= maxLen; ++i) {
1263 fl::size otherLen = other.
mLength;
1279 }
else if (thisInline) {
1308 if (
data && len > 0) {
1315 if (!holder || holder->length() == 0)
return;
1343 write(
static_cast<fl::u16
>(val));
1357 write(
static_cast<fl::i32
>(val));
1401 return append(
static_cast<float>(val));
1442 fl::size additional_chars = count -
mLength;
1445 for (fl::size i = 0; i < additional_chars; ++i) {
Concrete type-erased string class operating on a caller- provided buffer (or fl::span<char>).
bool operator==(const basic_string &other) const FL_NOEXCEPT
basic_string & erase(fl::size pos=0, fl::size count=npos) FL_NOEXCEPT
~basic_string() FL_NOEXCEPT
fl::size find_last_of(char c, fl::size pos=npos) const FL_NOEXCEPT
bool operator>=(const basic_string &other) const FL_NOEXCEPT
void pop_back() FL_NOEXCEPT
bool isNonOwning() const FL_NOEXCEPT
char front() const FL_NOEXCEPT
bool isInline() const FL_NOEXCEPT
bool operator<=(const basic_string &other) const FL_NOEXCEPT
float toFloat() const FL_NOEXCEPT
fl::size write(const fl::u8 *data, fl::size n) FL_NOEXCEPT
bool hasHeapData() const FL_NOEXCEPT
void reserve(fl::size newCapacity) FL_NOEXCEPT
char & at(fl::size pos) FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void swapWith(basic_string &other) FL_NOEXCEPT
bool operator<(const basic_string &other) const FL_NOEXCEPT
void materialize() FL_NOEXCEPT
void copy(const char *str) FL_NOEXCEPT
fl::size find_first_not_of(char c, fl::size pos=0) const FL_NOEXCEPT
void resize(fl::size count) FL_NOEXCEPT
void push_ascii(char c) FL_NOEXCEPT
fl::size find_last_not_of(char c, fl::size pos=npos) const FL_NOEXCEPT
void clear(bool freeMemory=false) FL_NOEXCEPT
void assign(const char *str, fl::size len) FL_NOEXCEPT
NotNullStringHolderPtr & heapData() FL_NOEXCEPT
static constexpr fl::size npos
bool starts_with(const char *prefix) const FL_NOEXCEPT
void shrink_to_fit() FL_NOEXCEPT
fl::size find(const char &value) const FL_NOEXCEPT
basic_string & replace(fl::size pos, fl::size count, const basic_string &str) FL_NOEXCEPT
basic_string & insert(fl::size pos, fl::size count, char ch) FL_NOEXCEPT
const char * data() const FL_NOEXCEPT
fl::variant< NotNullStringHolderPtr, ConstLiteral, ConstView > mStorage
char * c_str_mutable() FL_NOEXCEPT
char back() const FL_NOEXCEPT
void setView(const char *data, fl::size len) FL_NOEXCEPT
char * inlineBufferPtr() FL_NOEXCEPT
basic_string & append(const char *str) FL_NOEXCEPT
basic_string & appendHex(i32 val) FL_NOEXCEPT
basic_string(char *inlineBuffer, fl::size inlineCapacity) FL_NOEXCEPT
bool contains(const char *substr) const FL_NOEXCEPT
int compare(const basic_string &str) const FL_NOEXCEPT
void moveFrom(basic_string &&other) FL_NOEXCEPT
char charAt(fl::size index) const FL_NOEXCEPT
fl::size find_first_of(char c, fl::size pos=0) const FL_NOEXCEPT
void setLiteral(const char *literal) FL_NOEXCEPT
void push_back(char c) FL_NOEXCEPT
fl::size capacity() const FL_NOEXCEPT
bool operator!=(const basic_string &other) const FL_NOEXCEPT
void setSharedHolder(const fl::shared_ptr< StringHolder > &holder) FL_NOEXCEPT
const char * constData() const FL_NOEXCEPT
const char * c_str() const FL_NOEXCEPT
void moveAssign(basic_string &&other) FL_NOEXCEPT
char operator[](fl::size index) const FL_NOEXCEPT
fl::size rfind(char c, fl::size pos=npos) const FL_NOEXCEPT
bool operator>(const basic_string &other) const FL_NOEXCEPT
fl::size size() const FL_NOEXCEPT
basic_string & appendOct(i32 val) FL_NOEXCEPT
bool ends_with(const char *suffix) const FL_NOEXCEPT
Concrete type-erased string class.
constexpr const T & get() const FL_NOEXCEPT
long use_count() const FL_NOEXCEPT
constexpr string_view() FL_NOEXCEPT
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
void swap(T &a, T &b) FL_NOEXCEPT
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
int strncmp(const char *s1, const char *s2, size_t n) FL_NOEXCEPT
constexpr int type_rank< T >::value
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
int itoa(i32 value, char *sp, int radix)
Convert signed 32-bit integer to string buffer in given radix.
fl::not_null< StringHolderPtr > NotNullStringHolderPtr
size_t strlen(const char *s) FL_NOEXCEPT
int utoa64(u64 value, char *sp, int radix)
Convert unsigned 64-bit integer to string buffer in given radix.
int utoa32(u32 value, char *sp, int radix)
Convert unsigned 32-bit integer to string buffer in given radix.
const char * strstr(const char *haystack, const char *needle) FL_NOEXCEPT
int itoa64(i64 value, char *sp, int radix)
Convert signed 64-bit integer to string buffer in given radix.
void * memmove(void *dest, const void *src, size_t n) FL_NOEXCEPT
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
expected< T, E > result
Alias for expected (Rust-style naming)
float parseFloat(const char *str, fl::size len)
Parse a floating point number from a character buffer.
To * bit_cast_ptr(void *storage) FL_NOEXCEPT
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) FL_NOEXCEPT
void ftoa(float value, char *buffer, int precision)
Convert floating point number to string buffer.
int strcmp(const char *s1, const char *s2) FL_NOEXCEPT
Base definition for an LED controller.
#define FL_DISABLE_WARNING(warning)
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_POP