FastLED 3.9.15
Loading...
Searching...
No Matches
str.cpp
Go to the documentation of this file.
1#include <stdlib.h>
2#include <string.h> // ok include - for strcmp
3#include "fl/str.h"
4
5#include "crgb.h"
6#include "fl/fft.h"
7#include "fl/namespace.h"
8#include "fl/unused.h"
9#include "fl/xymap.h"
10#include "fl/json.h"
11#include "fl/tile2x2.h"
12#include "fl/compiler_control.h"
13// UI dependency moved to separate compilation unit to break dependency chain
14
15#ifdef FASTLED_TESTING
16#include <cstdio> // ok include
17#endif
18
19namespace fl {
20
21// Define static const member for npos (only for string class)
22const fl::size string::npos;
23
24// Explicit template instantiations for commonly used sizes
25template class StrN<64>;
26
28
29static void ftoa(float value, char *buffer, int precision = 2) {
30
31#ifdef FASTLED_TESTING
32 // use snprintf during testing with precision
33 snprintf(buffer, 64, "%.*f", precision, value);
34 return;
35
36#else
37 // Handle negative values
38 if (value < 0) {
39 *buffer++ = '-';
40 value = -value;
41 }
42
43 // Extract integer part
44 u32 intPart = (u32)value;
45
46 // Convert integer part to string (reversed)
47 char intBuf[12]; // Enough for 32-bit integers
48 int i = 0;
49 do {
50 intBuf[i++] = '0' + (intPart % 10);
51 intPart /= 10;
52 } while (intPart);
53
54 // Write integer part in correct order
55 while (i--) {
56 *buffer++ = intBuf[i];
57 }
58
59 *buffer++ = '.'; // Decimal point
60
61 // Extract fractional part
62 float fracPart = value - (u32)value;
63 for (int j = 0; j < precision; ++j) {
64 fracPart *= 10.0f;
65 int digit = (int)fracPart;
66 *buffer++ = '0' + digit;
67 fracPart -= digit;
68 }
69
70 *buffer = '\0'; // Null-terminate
71#endif
72}
73
74static int itoa(int value, char *sp, int radix) {
75 char tmp[16]; // be careful with the length of the buffer
76 char *tp = tmp;
77 int i;
78 unsigned v;
79
80 int sign = (radix == 10 && value < 0);
81 if (sign)
82 v = -value;
83 else
84 v = (unsigned)value;
85
86 while (v || tp == tmp) {
87 i = v % radix;
88 v = radix ? v / radix : 0;
89 if (i < 10)
90 *tp++ = i + '0';
91 else
92 *tp++ = i + 'a' - 10;
93 }
94
95 int len = tp - tmp;
96
97 if (sign) {
98 *sp++ = '-';
99 len++;
100 }
101
102 while (tp > tmp)
103 *sp++ = *--tp;
104
105 return len;
106}
107
108static int utoa32(uint32_t value, char *sp, int radix) {
109 char tmp[16]; // be careful with the length of the buffer
110 char *tp = tmp;
111 int i;
112 uint32_t v = value;
113
114 while (v || tp == tmp) {
115 i = v % radix;
116 v = radix ? v / radix : 0;
117 if (i < 10)
118 *tp++ = i + '0';
119 else
120 *tp++ = i + 'a' - 10;
121 }
122
123 int len = tp - tmp;
124
125 while (tp > tmp)
126 *sp++ = *--tp;
127
128 return len;
129}
130
131static int utoa64(uint64_t value, char *sp, int radix) {
132 char tmp[32]; // larger buffer for 64-bit values
133 char *tp = tmp;
134 int i;
135 uint64_t v = value;
136
137 while (v || tp == tmp) {
138 i = v % radix;
139 v = radix ? v / radix : 0;
140 if (i < 10)
141 *tp++ = i + '0';
142 else
143 *tp++ = i + 'a' - 10;
144 }
145
146 int len = tp - tmp;
147
148 while (tp > tmp)
149 *sp++ = *--tp;
150
151 return len;
152}
153
154static float atoff(const char *str, fl::size len) {
155 float result = 0.0f; // The resulting number
156 float sign = 1.0f; // Positive or negative
157 float fraction = 0.0f; // Fractional part
158 float divisor = 1.0f; // Divisor for the fractional part
159 int isFractional = 0; // Whether the current part is fractional
160
161 fl::size pos = 0; // Current position in the string
162
163 // Handle empty input
164 if (len == 0) {
165 return 0.0f;
166 }
167
168 // Skip leading whitespace (manual check instead of isspace)
169 while (pos < len &&
170 (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\n' ||
171 str[pos] == '\r' || str[pos] == '\f' || str[pos] == '\v')) {
172 pos++;
173 }
174
175 // Handle optional sign
176 if (pos < len && str[pos] == '-') {
177 sign = -1.0f;
178 pos++;
179 } else if (pos < len && str[pos] == '+') {
180 pos++;
181 }
182
183 // Main parsing loop
184 while (pos < len) {
185 if (str[pos] >= '0' && str[pos] <= '9') {
186 if (isFractional) {
187 divisor *= 10.0f;
188 fraction += (str[pos] - '0') / divisor;
189 } else {
190 result = result * 10.0f + (str[pos] - '0');
191 }
192 } else if (str[pos] == '.' && !isFractional) {
193 isFractional = 1;
194 } else {
195 // Stop parsing at invalid characters
196 break;
197 }
198 pos++;
199 }
200
201 // Combine integer and fractional parts
202 result = result + fraction;
203
204 // Apply the sign
205 return sign * result;
206}
207
208} // namespace string_functions
209
210void StringFormatter::append(i32 val, StrN<64> *dst) {
211 char buf[63] = {0};
212 string_functions::itoa(val, buf, 10);
213 dst->write(buf, strlen(buf));
214}
215
216void StringFormatter::append(u32 val, StrN<64> *dst) {
217 char buf[63] = {0};
218 string_functions::utoa32(val, buf, 10);
219 dst->write(buf, strlen(buf));
220}
221
222void StringFormatter::append(uint64_t val, StrN<64> *dst) {
223 char buf[63] = {0};
224 string_functions::utoa64(val, buf, 10);
225 dst->write(buf, strlen(buf));
226}
227
228void StringFormatter::append(i16 val, StrN<64> *dst) {
229 append(static_cast<i32>(val), dst);
230}
231
232void StringFormatter::append(u16 val, StrN<64> *dst) {
233 append(static_cast<u32>(val), dst);
234}
236 mLength = strlen(str); // Don't include null terminator in length
237 mCapacity = mLength + 1; // Capacity includes null terminator
238 mData = new char[mCapacity];
239 memcpy(mData, str, mLength);
240 mData[mLength] = '\0';
241}
243 mData = (char *)malloc(length + 1);
244 if (mData) {
245 mLength = length;
246 mData[mLength] = '\0';
247 } else {
248 mLength = 0;
249 }
251}
252
253StringHolder::StringHolder(const char *str, fl::size length) {
254 mData = (char *)malloc(length + 1);
255 if (mData) {
256 mLength = length;
257 memcpy(mData, str, mLength);
258 mData[mLength] = '\0';
259 } else {
260 mLength = 0;
261 }
263}
264
266 free(mData); // Release the memory
267}
268
269void StringHolder::grow(fl::size newLength) {
270 if (newLength <= mCapacity) {
271 // New length must be greater than current length
272 mLength = newLength;
273 return;
274 }
275 char *newData = (char *)realloc(mData, newLength + 1);
276 if (newData) {
277 mData = newData;
278 mLength = newLength;
279 mCapacity = newLength;
280 mData[mLength] = '\0'; // Ensure null-termination
281 } else {
282 // handle re-allocation failure.
283 char *newData = (char *)malloc(newLength + 1);
284 if (newData) {
285 memcpy(newData, mData, mLength + 1);
286 free(mData);
287 mData = newData;
288 mLength = newLength;
290 } else {
291 // memory failure.
292 }
293 }
294}
295
296float StringFormatter::parseFloat(const char *str, fl::size len) {
297 return string_functions::atoff(str, len);
298}
299
300int StringFormatter::parseInt(const char *str, fl::size len) {
301 float f = parseFloat(str, len);
302 return static_cast<int>(f);
303}
304
305int StringFormatter::parseInt(const char *str) {
306 return parseInt(str, strlen(str));
307}
308
309int string::strcmp(const string& a, const string& b) {
310 return ::strcmp(a.c_str(), b.c_str());
311}
312
313string &string::append(const FFTBins &str) {
314 append("\n FFTImpl Bins:\n ");
315 append(str.bins_raw);
316 append("\n");
317 append(" FFTImpl Bins DB:\n ");
318 append(str.bins_db);
319 append("\n");
320 return *this;
321}
322
323string &string::append(const XYMap &map) {
324 append("XYMap(");
325 append(map.getWidth());
326 append(",");
327 append(map.getHeight());
328 append(")");
329 return *this;
330}
331
332string &string::append(const Tile2x2_u8_wrap &tile) {
334 tile.at(0, 0),
335 tile.at(0, 1),
336 tile.at(1, 0),
337 tile.at(1, 1),
338 };
339
340 append("Tile2x2_u8_wrap(");
341 for (int i = 0; i < 4; i++) {
342 vec2<u16> pos = data[i].first;
343 u8 alpha = data[i].second;
344 append("(");
345 append(pos.x);
346 append(",");
347 append(pos.y);
348 append(",");
349 append(alpha);
350 append(")");
351 if (i < 3) {
352 append(",");
353 }
354 }
355 append(")");
356 return *this;
357}
358
359void string::swap(string &other) {
360 if (this != &other) {
361 fl::swap(mLength, other.mLength);
362 char temp[FASTLED_STR_INLINED_SIZE];
363 memcpy(temp, mInlineData, FASTLED_STR_INLINED_SIZE);
364 memcpy(mInlineData, other.mInlineData, FASTLED_STR_INLINED_SIZE);
365 memcpy(other.mInlineData, temp, FASTLED_STR_INLINED_SIZE);
367 }
368}
369
371 static_assert(FASTLED_STR_INLINED_SIZE > 0,
372 "FASTLED_STR_INLINED_SIZE must be greater than 0");
373 static_assert(FASTLED_STR_INLINED_SIZE == kStrInlineSize,
374 "If you want to change the FASTLED_STR_INLINED_SIZE, then it "
375 "must be through a build define and not an include define.");
376}
377
378string &string::append(const CRGB &rgb) {
379 append("CRGB(");
380 append(rgb.r);
381 append(",");
382 append(rgb.g);
383 append(",");
384 append(rgb.b);
385 append(")");
386 return *this;
387}
388
389void StringFormatter::appendFloat(const float &val, StrN<64> *dst) {
390 char buf[64] = {0};
391 string_functions::ftoa(val, buf);
392 dst->write(buf, strlen(buf));
393}
394
395void StringFormatter::appendFloat(const float &val, StrN<64> *dst, int precision) {
396 char buf[64] = {0};
397 string_functions::ftoa(val, buf, precision);
398 dst->write(buf, strlen(buf));
399}
400
401// JsonUiInternal append implementation moved to str_ui.cpp to break dependency chain
402
403// JSON type append implementations
404// NOTE: These use forward declarations to avoid circular dependency with json.h
405string &string::append(const JsonValue& val) {
406 // Use the JsonValue's to_string method if available
407 // For now, just append a placeholder to avoid compilation errors
408 FL_UNUSED(val);
409 append("<JsonValue>");
410 return *this;
411}
412
413string &string::append(const Json& val) {
414 // Use the Json's to_string method if available
415 // For now, just append a placeholder to avoid compilation errors
416 //append("<Json>");
417 append("Json(");
418 append(val.to_string());
419 append(")");
420 return *this;
421}
422
423} // namespace fl
uint8_t pos
Definition Blur.ino:11
fl::string to_string() const
Definition json.h:2120
const char * c_str() const
Definition str.h:326
fl::size write(const u8 *data, fl::size n)
Definition str.h:246
static void append(i32 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 void appendFloat(const float &val, StrN< FASTLED_STR_INLINED_SIZE > *dst)
char * mData
Definition str.h:133
fl::size length() const
Definition str.h:120
StringHolder(const char *str)
Definition str.cpp:235
void grow(fl::size newLength)
Definition str.cpp:269
fl::size mLength
Definition str.h:134
fl::size mCapacity
Definition str.h:135
Entry & at(u16 x, u16 y)
Definition tile2x2.cpp:65
fl::pair< vec2< u16 >, u8 > Entry
Definition tile2x2.h:108
u16 getWidth() const
Definition xymap.cpp:122
u16 getHeight() const
Definition xymap.cpp:124
Result type for promise operations.
void swap(string &other)
Definition str.cpp:359
@ kStrInlineSize
Definition str.h:946
string & append(const BitsetFixed< N > &bs)
Definition str.h:675
static void compileTimeAssertions()
Definition str.cpp:370
static int strcmp(const string &a, const string &b)
Definition str.cpp:309
static const fl::size npos
Definition str.h:597
const char * data() const
Definition str.h:910
Defines the red, green, and blue (RGB) pixel struct.
FastLED's Elegant JSON Library: fl::Json
Implements the FastLED namespace macros.
static int utoa64(uint64_t value, char *sp, int radix)
Definition str.cpp:131
static float atoff(const char *str, fl::size len)
Definition str.cpp:154
static void ftoa(float value, char *buffer, int precision=2)
Definition str.cpp:29
static int itoa(int value, char *sp, int radix)
Definition str.cpp:74
static int utoa32(uint32_t value, char *sp, int radix)
Definition str.cpp:108
unsigned char u8
Definition int.h:17
void swap(array< T, N > &lhs, array< T, N > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition array.h:156
int snprintf(char *buffer, fl::size size, const char *format, const Args &... args)
Snprintf-like formatting function that writes to a buffer.
Definition printf.h:422
IMPORTANT!
Definition crgb.h:20
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86
fl::vector< float > bins_raw
Definition fft.h:53
fl::vector< float > bins_db
Definition fft.h:55
#define FL_UNUSED(x)
Definition unused.h:8