FastLED 3.9.15
Loading...
Searching...
No Matches
str.h
Go to the documentation of this file.
1#pragma once
2
4// fl::string has inlined memory and copy on write semantics.
5
6
7#include "fl/int.h"
8#include <string.h>
9
10#ifdef __EMSCRIPTEN__
11#include <string>
12#endif
13
14#include "fl/geometry.h"
15#include "fl/math_macros.h"
16#include "fl/namespace.h"
17#include "fl/memory.h"
18#include "fl/optional.h"
19#include "fl/type_traits.h"
20#include "fl/vector.h"
21#include "fl/span.h"
22#include "fl/force_inline.h"
23
24#ifndef FASTLED_STR_INLINED_SIZE
25#define FASTLED_STR_INLINED_SIZE 64
26#endif
27
29struct CRGB;
31
32namespace fl { // Mandatory namespace for this class since it has name
33 // collisions.
34
35class string;
36using Str = fl::string; // backwards compatibility
37class Tile2x2_u8_wrap;
38class JsonUiInternal;
39
40// Forward declarations for JSON types
41struct JsonValue;
42class Json;
43
44template <typename T> struct rect;
45template <typename T> struct vec2;
46template <typename T> struct vec3;
47template <typename T> class Slice;
48template <typename T, typename Allocator> class HeapVector;
49template <typename T, fl::size N> class InlinedVector;
50template <typename T, fl::size N> class FixedVector;
51template <fl::size N> class StrN;
52
53template <typename T> class WeakPtr;
54template <typename T> class Ptr;
55
56template <typename T> struct Hash;
57
58template <typename T> struct EqualTo;
59
60template <typename Key, typename Hash, typename KeyEqual> class HashSet;
61
62template <fl::u32 N> class BitsetFixed;
63class bitset_dynamic;
64template <fl::u32 N> class BitsetInlined;
65
66class XYMap;
67
68struct FFTBins;
69
70// A copy on write string class. Fast to copy from another
71// Str object as read only pointers are shared. If the size
72// of the string is below FASTLED_STR_INLINED_SIZE then the
73// the entire string fits in the object and no heap allocation occurs.
74// When the string is large enough it will overflow into heap
75// allocated memory. Copy on write means that if the Str has
76// a heap buffer that is shared with another Str object, then
77// a copy is made and then modified in place.
78// If write() or append() is called then the internal data structure
79// will grow to accomodate the new data with extra space for future,
80// like a vector.
81
82
84// Implementation details.
85
87
89 public:
90 static void append(i32 val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
91 static void append(u32 val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
92 static void append(uint64_t val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
93 static void append(i16 val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
94 static void append(u16 val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
95 static bool isSpace(char c) {
96 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
97 }
98 static float parseFloat(const char *str, fl::size len);
99 static int parseInt(const char *str, fl::size len);
100 static int parseInt(const char *str);
101 static bool isDigit(char c) { return c >= '0' && c <= '9'; }
102 static void appendFloat(const float &val, StrN<FASTLED_STR_INLINED_SIZE> *dst);
103 static void appendFloat(const float &val, StrN<FASTLED_STR_INLINED_SIZE> *dst, int precision);
104};
105
107 public:
108 StringHolder(const char *str);
109 StringHolder(fl::size length);
110 StringHolder(const char *str, fl::size length);
111 StringHolder(const StringHolder &other) = delete;
112 StringHolder &operator=(const StringHolder &other) = delete;
114
115
116 void grow(fl::size newLength);
117 bool hasCapacity(fl::size newLength) const { return newLength <= mCapacity; }
118 const char *data() const { return mData; }
119 char *data() { return mData; }
120 fl::size length() const { return mLength; }
121 fl::size capacity() const { return mCapacity; }
122 bool copy(const char *str, fl::size len) {
123 if ((len + 1) > mCapacity) {
124 return false;
125 }
126 memcpy(mData, str, len);
127 mData[len] = '\0';
128 mLength = len;
129 return true;
130 }
131
132 private:
133 char *mData = nullptr;
134 fl::size mLength = 0;
135 fl::size mCapacity = 0;
136};
137
138template <fl::size SIZE = FASTLED_STR_INLINED_SIZE> class StrN {
139 protected:
140 fl::size mLength = 0;
141 char mInlineData[SIZE] = {0};
142 StringHolderPtr mHeapData;
143
144 public:
145 // Static constants (like std::string)
146 static constexpr fl::size npos = static_cast<fl::size>(-1);
147
148 // Constructors
149 StrN() = default;
150
151 // cppcheck-suppress-begin [operatorEqVarError]
152 template <fl::size M> StrN(const StrN<M> &other) { copy(other); }
153 StrN(const char *str) {
154 fl::size len = strlen(str);
155 mLength = len; // Length is without null terminator
156 if (len + 1 <= SIZE) { // Check capacity including null
157 memcpy(mInlineData, str, len + 1); // Copy including null
158 mHeapData.reset();
159 } else {
161 }
162 }
163 StrN(const StrN &other) { copy(other); }
164 void copy(const char *str) {
165 fl::size len = strlen(str);
166 mLength = len;
167 if (len + 1 <= SIZE) {
168 memcpy(mInlineData, str, len + 1);
169 mHeapData.reset();
170 } else {
171 if (mHeapData && mHeapData.use_count() <= 1) {
172 // We are the sole owners of this data so we can modify it
173 mHeapData->copy(str, len);
174 return;
175 }
176 mHeapData.reset();
178 }
179 }
180
181 template <int N> StrN(const char (&str)[N]) {
182 copy(str, N - 1); // Subtract 1 to not count null terminator
183 }
184 template <int N> StrN &operator=(const char (&str)[N]) {
185 assign(str, N);
186 return *this;
187 }
188 StrN &operator=(const StrN &other) {
189 copy(other);
190 return *this;
191 }
192 template <fl::size M> StrN &operator=(const StrN<M> &other) {
193 copy(other);
194 return *this;
195 }
196 // cppcheck-suppress-end
197
198 void assign(const char* str, fl::size len) {
199 mLength = len;
200 if (len + 1 <= SIZE) {
201 memcpy(mInlineData, str, len + 1);
202 mHeapData.reset();
203 } else {
205 mHeapData->copy(str, len);
206 mHeapData->data()[len] = '\0';
207 }
208 }
209
210 bool operator==(const StrN &other) const {
211 return strcmp(c_str(), other.c_str()) == 0;
212 }
213
214 bool operator!=(const StrN &other) const {
215 return strcmp(c_str(), other.c_str()) != 0;
216 }
217
218 void copy(const char *str, fl::size len) {
219 mLength = len;
220 if (len + 1 <= SIZE) {
221 fl::memcopy(mInlineData, str, len); // Copy only len characters, not len+1
222 mInlineData[len] = '\0'; // Add null terminator manually
223 mHeapData.reset();
224 } else {
226 }
227 }
228
229 template <fl::size M> void copy(const StrN<M> &other) {
230 fl::size len = other.size();
231 if (len + 1 <= SIZE) {
232 memcpy(mInlineData, other.c_str(), len + 1);
233 mHeapData.reset();
234 } else {
235 if (other.mHeapData) {
236 mHeapData = other.mHeapData;
237 } else {
239 }
240 }
241 mLength = len;
242 }
243
244 fl::size capacity() const { return mHeapData ? mHeapData->capacity() : SIZE; }
245
246 fl::size write(const u8 *data, fl::size n) {
247 const char *str = fl::bit_cast_ptr<const char>(static_cast<const void*>(data));
248 return write(str, n);
249 }
250
251 fl::size write(const char *str, fl::size n) {
252 fl::size newLen = mLength + n;
253 if (mHeapData && mHeapData.use_count() <= 1) {
254 if (!mHeapData->hasCapacity(newLen)) {
255 fl::size grow_length = MAX(3, newLen * 3 / 2);
256 mHeapData->grow(grow_length); // Grow by 50%
257 }
258 memcpy(mHeapData->data() + mLength, str, n);
259 mLength = newLen;
260 mHeapData->data()[mLength] = '\0';
261 return mLength;
262 }
263 if (newLen + 1 <= SIZE) {
264 memcpy(mInlineData + mLength, str, n);
265 mLength = newLen;
266 mInlineData[mLength] = '\0';
267 return mLength;
268 }
269 mHeapData.reset();
270 StringHolderPtr newData = fl::make_shared<StringHolder>(newLen);
271 if (newData) {
272 memcpy(newData->data(), c_str(), mLength);
273 memcpy(newData->data() + mLength, str, n);
274 newData->data()[newLen] = '\0';
275 mHeapData = newData;
276 mLength = newLen;
277 }
278 mHeapData = newData;
279 return mLength;
280 }
281
282 fl::size write(char c) { return write(&c, 1); }
283
284 fl::size write(u8 c) {
285 const char *str = fl::bit_cast_ptr<const char>(static_cast<const void*>(&c));
286 return write(str, 1);
287 }
288
289 fl::size write(const u16 &n) {
291 StringFormatter::append(n, &dst); // Inlined size should suffice
292 return write(dst.c_str(), dst.size());
293 }
294
295 fl::size write(const u32 &val) {
297 StringFormatter::append(val, &dst); // Inlined size should suffice
298 return write(dst.c_str(), dst.size());
299 }
300
301 fl::size write(const uint64_t &val) {
303 StringFormatter::append(val, &dst); // Inlined size should suffice
304 return write(dst.c_str(), dst.size());
305 }
306
307 fl::size write(const i32 &val) {
309 StringFormatter::append(val, &dst); // Inlined size should suffice
310 return write(dst.c_str(), dst.size());
311 }
312
313 fl::size write(const i8 val) {
316 &dst); // Inlined size should suffice
317 return write(dst.c_str(), dst.size());
318 }
319
320 // Destructor
321 ~StrN() {}
322
323 // Accessors
324 fl::size size() const { return mLength; }
325 fl::size length() const { return size(); }
326 const char *c_str() const {
327 return mHeapData ? mHeapData->data() : mInlineData;
328 }
329
331 return mHeapData ? mHeapData->data() : mInlineData;
332 }
333
334 char &operator[](fl::size index) {
335 if (index >= mLength) {
336 static char dummy = '\0';
337 return dummy;
338 }
339 return c_str_mutable()[index];
340 }
341
342 char operator[](fl::size index) const {
343 if (index >= mLength) {
344 static char dummy = '\0';
345 return dummy;
346 }
347 return c_str()[index];
348 }
349
350 bool empty() const { return mLength == 0; }
351
352 // Iterator support for range-based for loops
353 char* begin() { return c_str_mutable(); }
354 char* end() { return c_str_mutable() + mLength; }
355 const char* begin() const { return c_str(); }
356 const char* end() const { return c_str() + mLength; }
357 const char* cbegin() const { return c_str(); }
358 const char* cend() const { return c_str() + mLength; }
359
360 // Append method
361
362 bool operator<(const StrN &other) const {
363 return strcmp(c_str(), other.c_str()) < 0;
364 }
365
366 template <fl::size M> bool operator<(const StrN<M> &other) const {
367 return strcmp(c_str(), other.c_str()) < 0;
368 }
369
370 void reserve(fl::size newCapacity) {
371 // If capacity is less than current length, do nothing
372 if (newCapacity <= mLength) {
373 return;
374 }
375
376 // If new capacity fits in inline buffer, no need to allocate
377 if (newCapacity + 1 <= SIZE) {
378 return;
379 }
380
381 // If we already have unshared heap data with sufficient capacity, do
382 // nothing
383 if (mHeapData && mHeapData.use_count() <= 1 &&
384 mHeapData->hasCapacity(newCapacity)) {
385 return;
386 }
387
388 // Need to allocate new storage
389 StringHolderPtr newData = fl::make_shared<StringHolder>(newCapacity);
390 if (newData) {
391 // Copy existing content
392 memcpy(newData->data(), c_str(), mLength);
393 newData->data()[mLength] = '\0';
394 mHeapData = newData;
395 }
396 }
397
398 void clear(bool freeMemory = false) {
399 mLength = 0;
400 if (freeMemory && mHeapData) {
401 mHeapData.reset();
402 }
403 }
404
405
406
407 // Find single character
408 fl::size find(const char &value) const {
409 for (fl::size i = 0; i < mLength; ++i) {
410 if (c_str()[i] == value) {
411 return i;
412 }
413 }
414 return npos;
415 }
416
417 // Find substring (string literal support)
418 fl::size find(const char* substr) const {
419 if (!substr) {
420 return npos;
421 }
422 auto begin = c_str();
423 const char* found = strstr(begin, substr);
424 if (found) {
425 return found - begin;
426 }
427 return npos;
428 }
429
430 // Find another string
431 template<fl::size M>
432 fl::size find(const StrN<M>& other) const {
433 return find(other.c_str());
434 }
435
436 // Find single character starting from position (like std::string)
437 fl::size find(const char &value, fl::size start_pos) const {
438 if (start_pos >= mLength) {
439 return npos;
440 }
441 for (fl::size i = start_pos; i < mLength; ++i) {
442 if (c_str()[i] == value) {
443 return i;
444 }
445 }
446 return npos;
447 }
448
449 // Find substring starting from position (like std::string)
450 fl::size find(const char* substr, fl::size start_pos) const {
451 if (!substr || start_pos >= mLength) {
452 return npos;
453 }
454 auto begin = c_str() + start_pos;
455 const char* found = strstr(begin, substr);
456 if (found) {
457 return found - c_str();
458 }
459 return npos;
460 }
461
462 // Find another string starting from position (like std::string)
463 template<fl::size M>
464 fl::size find(const StrN<M>& other, fl::size start_pos) const {
465 return find(other.c_str(), start_pos);
466 }
467
468 // Contains methods for C++23 compatibility
469 bool contains(const char* substr) const {
470 return find(substr) != npos;
471 }
472
473 bool contains(char c) const {
474 return find(c) != npos;
475 }
476
477 template<fl::size M>
478 bool contains(const StrN<M>& other) const {
479 return find(other.c_str()) != npos;
480 }
481
482 // Starts with methods for C++20 compatibility
483 bool starts_with(const char* prefix) const {
484 if (!prefix) {
485 return true; // Empty prefix matches any string
486 }
487 fl::size prefix_len = strlen(prefix);
488 if (prefix_len > mLength) {
489 return false;
490 }
491 return strncmp(c_str(), prefix, prefix_len) == 0;
492 }
493
494 bool starts_with(char c) const {
495 return mLength > 0 && c_str()[0] == c;
496 }
497
498 template<fl::size M>
499 bool starts_with(const StrN<M>& prefix) const {
500 return starts_with(prefix.c_str());
501 }
502
503 // Ends with methods for C++20 compatibility
504 bool ends_with(const char* suffix) const {
505 if (!suffix) {
506 return true; // Empty suffix matches any string
507 }
508 fl::size suffix_len = strlen(suffix);
509 if (suffix_len > mLength) {
510 return false;
511 }
512 return strncmp(c_str() + mLength - suffix_len, suffix, suffix_len) == 0;
513 }
514
515 bool ends_with(char c) const {
516 return mLength > 0 && c_str()[mLength - 1] == c;
517 }
518
519 template<fl::size M>
520 bool ends_with(const StrN<M>& suffix) const {
521 return ends_with(suffix.c_str());
522 }
523
524 StrN substring(fl::size start, fl::size end) const {
525 // short cut, it's the same string
526 if (start == 0 && end == mLength) {
527 return *this;
528 }
529 if (start >= mLength) {
530 return StrN();
531 }
532 if (end > mLength) {
533 end = mLength;
534 }
535 if (start >= end) {
536 return StrN();
537 }
538 StrN out;
539 out.copy(c_str() + start, end - start);
540 return out;
541 }
542
543 StrN substr(fl::size start, fl::size length) const {
544 // Standard substr(pos, length) behavior - convert to substring(start, end)
545 fl::size end = start + length;
546 if (end > mLength) {
547 end = mLength;
548 }
549 return substring(start, end);
550 }
551
552 StrN substr(fl::size start) const {
553 auto end = mLength;
554 return substring(start, end);
555 }
556
557 void push_back(char c) {
558 write(c);
559 }
560
561 // Push ASCII character without numeric conversion for display
562 void push_ascii(char c) {
563 write(c);
564 }
565
566 void pop_back() {
567 if (mLength > 0) {
568 mLength--;
569 c_str_mutable()[mLength] = '\0';
570 }
571 }
572
573 StrN trim() const {
574 StrN out;
575 fl::size start = 0;
576 fl::size end = mLength;
577 while (start < mLength && StringFormatter::isSpace(c_str()[start])) {
578 start++;
579 }
580 while (end > start && StringFormatter::isSpace(c_str()[end - 1])) {
581 end--;
582 }
583 return substring(start, end);
584 }
585
586 float toFloat() const {
588 }
589
590 private:
591 StringHolderPtr mData;
592};
593
594class string : public StrN<FASTLED_STR_INLINED_SIZE> {
595 public:
596 // Standard string npos constant for compatibility
597 static const fl::size npos = static_cast<fl::size>(-1);
598
599 static int strcmp(const string& a, const string& b);
600
601 string() : StrN<FASTLED_STR_INLINED_SIZE>() {}
602 string(const char *str) : StrN<FASTLED_STR_INLINED_SIZE>(str) {}
603 string(const char *str, fl::size len) : StrN<FASTLED_STR_INLINED_SIZE>() {
604 copy(str, len);
605 }
606 string(fl::size len, char c) : StrN<FASTLED_STR_INLINED_SIZE>() {
607 resize(len, c);
608 }
609 string(const string &other) : StrN<FASTLED_STR_INLINED_SIZE>(other) {}
610 template <fl::size M>
611 string(const StrN<M> &other) : StrN<FASTLED_STR_INLINED_SIZE>(other) {}
612 string &operator=(const string &other) {
613 copy(other);
614 return *this;
615 }
616
617 string &operator=(const char *str) {
618 copy(str, strlen(str));
619 return *this;
620 }
621
622#ifdef __EMSCRIPTEN__
623 string(const std::string &str) {
624 copy(str.c_str(), str.size());
625 }
626 string &operator=(const std::string &str) {
627 copy(str.c_str(), str.size());
628 return *this;
629 }
630 // append
631 string &append(const std::string &str) {
632 write(str.c_str(), str.size());
633 return *this;
634 }
635#endif
636
637
638
639
640 bool operator>(const string &other) const {
641 return strcmp(c_str(), other.c_str()) > 0;
642 }
643
644 bool operator>=(const string &other) const {
645 return strcmp(c_str(), other.c_str()) >= 0;
646 }
647
648 bool operator<(const string &other) const {
649 return strcmp(c_str(), other.c_str()) < 0;
650 }
651
652 bool operator<=(const string &other) const {
653 return strcmp(c_str(), other.c_str()) <= 0;
654 }
655
656 bool operator==(const string &other) const {
657 return strcmp(c_str(), other.c_str()) == 0;
658 }
659
660 bool operator!=(const string &other) const {
661 return strcmp(c_str(), other.c_str()) != 0;
662 }
663
664 string &operator+=(const string &other) {
665 append(other.c_str(), other.size());
666 return *this;
667 }
668
669 template <typename T> string &operator+=(const T &val) {
670 append(val);
671 return *this;
672 }
673
674 template <fl::u32 N>
675 string &append(const BitsetFixed<N> &bs) {
676 bs.to_string(this);
677 return *this;
678 }
679
680 string &append(const bitset_dynamic &bs) {
681 bs.to_string(this);
682 return *this;
683 }
684
685 template <fl::u32 N>
686 string &append(const BitsetInlined<N> &bs) {
687 bs.to_string(this);
688 return *this;
689 }
690
691 char front() const {
692 if (empty()) {
693 return '\0';
694 }
695 return c_str()[0];
696 }
697 char back() const {
698 if (empty()) {
699 return '\0';
700 }
701 return c_str()[size() - 1];
702 }
703
704 // Push ASCII character without numeric conversion for display
705 void push_ascii(char c) {
706 write(c);
707 }
708
709 // Generic integral append: only enabled if T is an integral type. This is
710 // needed because on some platforms type(int) is not one of the integral
711 // types like i8, i16, i32, int64_t etc. In such a has just case
712 // the value to i32 and then append it.
713 template <typename T, typename = fl::enable_if_t<fl::is_integral<T>::value>>
714 string &append(const T &val) {
715 write(i32(val));
716 return *this;
717 }
718
719 template <typename T> string &append(const fl::span<T> &slice) {
720 append("[");
721 for (fl::size i = 0; i < slice.size(); ++i) {
722 if (i > 0) {
723 append(", ");
724 }
725 append(slice[i]);
726 }
727 append("]");
728 return *this;
729 }
730
731 template <typename T> string &append(const fl::HeapVector<T> &vec) {
732 fl::span<const T> slice(vec.data(), vec.size());
733 append(slice);
734 return *this;
735 }
736
737 template <typename T, fl::size N>
738 string &append(const fl::InlinedVector<T, N> &vec) {
739 fl::span<const T> slice(vec.data(), vec.size());
740 append(slice);
741 return *this;
742 }
743
744 string &append(const char *str) {
745 write(str, strlen(str));
746 return *this;
747 }
748 string &append(const char *str, fl::size len) {
749 write(str, len);
750 return *this;
751 }
752 string &append(long long val) {
753 write(i32(val));
754 return *this;
755 }
756 // string& append(char c) { write(&c, 1); return *this; }
757 string &append(const i8 &c) {
758 const char *str = fl::bit_cast_ptr<const char>(static_cast<const void*>(&c));
759 write(str, 1);
760 return *this;
761 }
762 string &append(const u8 &c) {
763 write(static_cast<u32>(c));
764 return *this;
765 }
766 string &append(const u16 &val) {
767 write(val);
768 return *this;
769 }
770 string &append(const i16 &val) {
771 write(i32(val));
772 return *this;
773 }
774 string &append(const u32 &val) {
775 write(val);
776 return *this;
777 }
778 string &append(const uint64_t &val) {
779 write(val);
780 return *this;
781 }
782 string &append(const i32 &c) {
783 write(c);
784 return *this;
785 }
786
787 string &append(const bool &val) {
788 if (val) {
789 return append("true");
790 } else {
791 return append("false");
792 }
793 }
794
795 template <typename T> string &append(const rect<T> &rect) {
796 append(rect.mMin.x);
797 append(",");
798 append(rect.mMin.y);
799 append(",");
800 append(rect.mMax.x);
801 append(",");
802 append(rect.mMax.y);
803 return *this;
804 }
805
806 template <typename T> string &append(const vec2<T> &pt) {
807 append("(");
808 append(pt.x);
809 append(",");
810 append(pt.y);
811 append(")");
812 return *this;
813 }
814
815 template <typename T> string &append(const vec3<T> &pt) {
816 append("(");
817 append(pt.x);
818 append(",");
819 append(pt.y);
820 append(",");
821 append(pt.z);
822 append(")");
823 return *this;
824 }
825
826
827 template <typename T> string &append(const WeakPtr<T> &val) {
828 fl::shared_ptr<T> ptr = val.lock();
829 append(ptr);
830 return *this;
831 }
832
833 template <typename T> string &append(const fl::shared_ptr<T>& val) {
834 // append(val->toString());
835 if (!val) {
836 append("shared_ptr(null)");
837 } else {
838 T* ptr = val.get();
839 append("shared_ptr(");
840 append(*ptr);
841 append(")");
842 }
843 return *this;
844 }
845
846 string &append(const JsonUiInternal& val);
847
848 // JSON type append methods - implementations in str.cpp
849 string &append(const JsonValue& val);
850 string &append(const Json& val);
851
852 template <typename T, fl::size N>
853 string &append(const fl::FixedVector<T, N> &vec) {
854 fl::span<const T> slice(vec.data(), vec.size());
855 append(slice);
856 return *this;
857 }
858
859 string &append(const CRGB &c);
860
861 string &append(const float &_val) {
862 // round to nearest hundredth
864 return *this;
865 }
866
867 string &append(const float &_val, int precision) {
868 StringFormatter::appendFloat(_val, this, precision);
869 return *this;
870 }
871
872 string &append(const double &val) { return append(float(val)); }
873
874 string &append(const StrN &str) {
875 write(str.c_str(), str.size());
876 return *this;
877 }
878
879 string &append(const FFTBins &str);
880
881 string &append(const XYMap &map);
882
883 string &append(const Tile2x2_u8_wrap &tile);
884
885 template <typename Key, typename Hash, typename KeyEqual>
887 append("{");
888 for (auto it = set.begin(); it != set.end(); ++it) {
889 if (it != set.begin()) {
890 append(", ");
891 }
892 auto p = *it;
893 append(p.first);
894 }
895 append("}");
896 return *this;
897 }
898
899 // Support for fl::optional<T> types
900 template <typename T>
901 string &append(const fl::optional<T> &opt) {
902 if (opt.has_value()) {
903 append(*opt);
904 } else {
905 append("nullopt");
906 }
907 return *this;
908 }
909
910 const char *data() const { return c_str(); }
911
912 void swap(string &other);
913
914 // Resize methods to match std::string interface
915 void resize(fl::size count) {
916 resize(count, char());
917 }
918
919 void resize(fl::size count, char ch) {
920 if (count < mLength) {
921 // Truncate the string
922 mLength = count;
923 c_str_mutable()[mLength] = '\0';
924 } else if (count > mLength) {
925 // Extend the string with the specified character
926 fl::size additional_chars = count - mLength;
927 reserve(count); // Ensure enough capacity
928 char* data_ptr = c_str_mutable();
929 for (fl::size i = 0; i < additional_chars; ++i) {
930 data_ptr[mLength + i] = ch;
931 }
932 mLength = count;
933 data_ptr[mLength] = '\0';
934 }
935 // If count == mLength, do nothing
936 }
937
938 private:
939 enum {
940 // Bake the size into the string class so we can issue a compile time
941 // check
942 // to make sure the user doesn't do something funny like try to change
943 // the
944 // size of the inlined string via an included defined instead of a build
945 // define.
946 kStrInlineSize = FASTLED_STR_INLINED_SIZE,
947 };
948
949 static void compileTimeAssertions();
950};
951
952// to_string template function for converting values to fl::string
953// This provides std::to_string equivalent functionality using fl::string
954// Delegates to fl::string::append which handles all type conversions
955
956template<typename T>
957inline string to_string(T value) {
958 string result;
959 result.append(value);
960 return result;
961}
962
963// Specialized to_string for float with precision
964inline string to_string(float value, int precision) {
965 string result;
966 result.append(value, precision);
967 return result;
968}
969
970// Free operator+ functions for string concatenation
971// These allow expressions like: fl::string val = "string" + fl::to_string(5)
972
973// String literal + fl::string
974inline string operator+(const char* lhs, const string& rhs) {
975 string result(lhs);
976 result += rhs;
977 return result;
978}
979
980// fl::string + string literal
981inline string operator+(const string& lhs, const char* rhs) {
982 string result(lhs);
983 result += rhs;
984 return result;
985}
986
987// fl::string + fl::string
988inline string operator+(const string& lhs, const string& rhs) {
989 string result(lhs);
990 result += rhs;
991 return result;
992}
993
994// String literal + any type that can be converted to string
995template<typename T>
996inline string operator+(const char* lhs, const T& rhs) {
997 string result(lhs);
998 result += rhs;
999 return result;
1000}
1001
1002// Any type that can be converted to string + string literal
1003template<typename T>
1004inline string operator+(const T& lhs, const char* rhs) {
1005 string result;
1006 result.append(lhs);
1007 result += rhs;
1008 return result;
1009}
1010
1011// fl::string + any type that can be converted to string
1012template<typename T>
1013inline string operator+(const string& lhs, const T& rhs) {
1014 string result(lhs);
1015 result += rhs;
1016 return result;
1017}
1018
1019// Any type that can be converted to string + fl::string
1020template<typename T>
1021inline string operator+(const T& lhs, const string& rhs) {
1022 string result;
1023 result.append(lhs);
1024 result += rhs;
1025 return result;
1026}
1027
1028} // namespace fl
iterator data()
Definition vector.h:306
constexpr fl::size size() const
Definition vector.h:157
fl::size size() const
Definition vector.h:545
fl::size size() const
Definition vector.h:1008
bool has_value() const
Definition optional.h:30
Definition ptr.h:114
fl::size size() const
Definition slice.h:142
StrN & operator=(const StrN &other)
Definition str.h:188
StrN & operator=(const StrN< M > &other)
Definition str.h:192
fl::size find(const StrN< M > &other, fl::size start_pos) const
Definition str.h:464
fl::size size() const
Definition str.h:324
bool ends_with(const StrN< M > &suffix) const
Definition str.h:520
void copy(const StrN< M > &other)
Definition str.h:229
StrN(const StrN &other)
Definition str.h:163
bool operator<(const StrN &other) const
Definition str.h:362
fl::size write(const uint64_t &val)
Definition str.h:301
fl::size find(const StrN< M > &other) const
Definition str.h:432
bool empty() const
Definition str.h:350
static constexpr fl::size npos
Definition str.h:146
StrN & operator=(const char(&str)[N])
Definition str.h:184
StrN substr(fl::size start, fl::size length) const
Definition str.h:543
char * c_str_mutable()
Definition str.h:330
StringHolderPtr mData
Definition str.h:591
void reserve(fl::size newCapacity)
Definition str.h:370
bool starts_with(char c) const
Definition str.h:494
~StrN()
Definition str.h:321
const char * end() const
Definition str.h:356
fl::size find(const char &value) const
Definition str.h:408
bool ends_with(const char *suffix) const
Definition str.h:504
char * begin()
Definition str.h:353
bool contains(const StrN< M > &other) const
Definition str.h:478
fl::size write(const char *str, fl::size n)
Definition str.h:251
char * end()
Definition str.h:354
fl::size find(const char *substr) const
Definition str.h:418
bool starts_with(const StrN< M > &prefix) const
Definition str.h:499
void copy(const char *str, fl::size len)
Definition str.h:218
bool operator!=(const StrN &other) const
Definition str.h:214
const char * c_str() const
Definition str.h:326
StrN(const char *str)
Definition str.h:153
void clear(bool freeMemory=false)
Definition str.h:398
bool starts_with(const char *prefix) const
Definition str.h:483
fl::size write(u8 c)
Definition str.h:284
fl::size write(const i32 &val)
Definition str.h:307
bool contains(const char *substr) const
Definition str.h:469
fl::size find(const char &value, fl::size start_pos) const
Definition str.h:437
fl::size capacity() const
Definition str.h:244
StringHolderPtr mHeapData
Definition str.h:142
fl::size write(const u16 &n)
Definition str.h:289
fl::size write(const u32 &val)
Definition str.h:295
bool ends_with(char c) const
Definition str.h:515
StrN substring(fl::size start, fl::size end) const
Definition str.h:524
char & operator[](fl::size index)
Definition str.h:334
StrN(const char(&str)[N])
Definition str.h:181
fl::size length() const
Definition str.h:325
fl::size write(const u8 *data, fl::size n)
Definition str.h:246
void assign(const char *str, fl::size len)
Definition str.h:198
StrN(const StrN< M > &other)
Definition str.h:152
fl::size write(char c)
Definition str.h:282
fl::size find(const char *substr, fl::size start_pos) const
Definition str.h:450
fl::size write(const i8 val)
Definition str.h:313
StrN trim() const
Definition str.h:573
void copy(const char *str)
Definition str.h:164
char operator[](fl::size index) const
Definition str.h:342
char mInlineData[SIZE]
Definition str.h:141
bool operator==(const StrN &other) const
Definition str.h:210
bool contains(char c) const
Definition str.h:473
const char * begin() const
Definition str.h:355
void push_back(char c)
Definition str.h:557
const char * cbegin() const
Definition str.h:357
float toFloat() const
Definition str.h:586
StrN()=default
void push_ascii(char c)
Definition str.h:562
StrN substr(fl::size start) const
Definition str.h:552
const char * cend() const
Definition str.h:358
fl::size mLength
Definition str.h:140
void pop_back()
Definition str.h:566
bool operator<(const StrN< M > &other) const
Definition str.h:366
static void append(u16 val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static void appendFloat(const float &val, StrN< FASTLED_STR_INLINED_SIZE > *dst, int precision)
static void append(u32 val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static void append(i32 val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static void append(uint64_t val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static int parseInt(const char *str, fl::size len)
Definition str.cpp:300
static float parseFloat(const char *str, fl::size len)
Definition str.cpp:296
static bool isSpace(char c)
Definition str.h:95
static void appendFloat(const float &val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static void append(i16 val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
static bool isDigit(char c)
Definition str.h:101
fl::size capacity() const
Definition str.h:121
char * mData
Definition str.h:133
bool hasCapacity(fl::size newLength) const
Definition str.h:117
fl::size length() const
Definition str.h:120
StringHolder(const StringHolder &other)=delete
StringHolder(const char *str)
Definition str.cpp:235
void grow(fl::size newLength)
Definition str.cpp:269
fl::size mLength
Definition str.h:134
const char * data() const
Definition str.h:118
fl::size mCapacity
Definition str.h:135
bool copy(const char *str, fl::size len)
Definition str.h:122
StringHolder & operator=(const StringHolder &other)=delete
char * data()
Definition str.h:119
Ptr< T > lock() const
Definition ptr_impl.h:202
FL_DISABLE_WARNING_POP void to_string(string *dst) const
Definition bitset.cpp:24
A dynamic bitset implementation that can be resized at runtime.
Result type for promise operations.
const_iterator begin() const
Definition set.h:306
const_iterator end() const
Definition set.h:307
Definition set.h:278
T * get() const noexcept
Definition shared_ptr.h:271
string & append(long long val)
Definition str.h:752
string(const char *str, fl::size len)
Definition str.h:603
string & append(const i8 &c)
Definition str.h:757
string & append(const bitset_dynamic &bs)
Definition str.h:680
string(const char *str)
Definition str.h:602
string & append(const char *str)
Definition str.h:744
string & append(const HashSet< Key, Hash, KeyEqual > &set)
Definition str.h:886
bool operator==(const string &other) const
Definition str.h:656
void swap(string &other)
Definition str.cpp:359
string & append(const fl::span< T > &slice)
Definition str.h:719
string & append(const u16 &val)
Definition str.h:766
bool operator>(const string &other) const
Definition str.h:640
string & append(const fl::InlinedVector< T, N > &vec)
Definition str.h:738
@ kStrInlineSize
Definition str.h:946
string & operator=(const char *str)
Definition str.h:617
string & append(const vec2< T > &pt)
Definition str.h:806
string & operator=(const string &other)
Definition str.h:612
void push_ascii(char c)
Definition str.h:705
string & append(const u8 &c)
Definition str.h:762
string & append(const i32 &c)
Definition str.h:782
string & append(const double &val)
Definition str.h:872
string & append(const float &_val, int precision)
Definition str.h:867
bool operator>=(const string &other) const
Definition str.h:644
string & append(const BitsetFixed< N > &bs)
Definition str.h:675
bool operator<=(const string &other) const
Definition str.h:652
string & append(const fl::optional< T > &opt)
Definition str.h:901
string & append(const fl::shared_ptr< T > &val)
Definition str.h:833
string & append(const char *str, fl::size len)
Definition str.h:748
void resize(fl::size count, char ch)
Definition str.h:919
string()
Definition str.h:601
string & append(const vec3< T > &pt)
Definition str.h:815
string(const string &other)
Definition str.h:609
string(const StrN< M > &other)
Definition str.h:611
bool operator!=(const string &other) const
Definition str.h:660
string & append(const bool &val)
Definition str.h:787
string & append(const uint64_t &val)
Definition str.h:778
string & append(const WeakPtr< T > &val)
Definition str.h:827
static void compileTimeAssertions()
Definition str.cpp:370
string & operator+=(const T &val)
Definition str.h:669
string & append(const BitsetInlined< N > &bs)
Definition str.h:686
string & append(const fl::HeapVector< T > &vec)
Definition str.h:731
bool operator<(const string &other) const
Definition str.h:648
static int strcmp(const string &a, const string &b)
Definition str.cpp:309
char front() const
Definition str.h:691
string(fl::size len, char c)
Definition str.h:606
static const fl::size npos
Definition str.h:597
char back() const
Definition str.h:697
string & append(const rect< T > &rect)
Definition str.h:795
string & append(const fl::FixedVector< T, N > &vec)
Definition str.h:853
string & operator+=(const string &other)
Definition str.h:664
string & append(const float &_val)
Definition str.h:861
string & append(const u32 &val)
Definition str.h:774
const char * data() const
Definition str.h:910
void resize(fl::size count)
Definition str.h:915
string & append(const StrN &str)
Definition str.h:874
string & append(const i16 &val)
Definition str.h:770
string & append(const T &val)
Definition str.h:714
#define MAX(a, b)
Definition math_macros.h:37
#define FASTLED_NAMESPACE_END
Definition namespace.h:23
#define FASTLED_NAMESPACE_BEGIN
Definition namespace.h:22
Implements the FastLED namespace macros.
unsigned char u8
Definition int.h:17
To * bit_cast_ptr(void *storage) noexcept
Definition bit_cast.h:54
void * memcopy(void *dst, const void *src, fl::size num)
Definition memfill.h:30
Slice< T > span
Definition span.h:8
Optional< T > optional
Definition optional.h:14
string to_string(T value)
Definition str.h:957
shared_ptr< T > make_shared(Args &&... args)
Definition shared_ptr.h:348
string operator+(const char *lhs, const string &rhs)
Definition str.h:974
signed char i8
Definition int.h:16
fl::string Str
Definition str.h:36
IMPORTANT!
Definition crgb.h:20
#define FASTLED_SMART_PTR(type)
Definition ptr.h:33
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86
vec2< T > mMax
Definition geometry.h:420
vec2< T > mMin
Definition geometry.h:419
value_type y
Definition geometry.h:191
value_type x
Definition geometry.h:190