FastLED 3.9.15
Loading...
Searching...
No Matches
string_view.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/stdint.h"
4#include "fl/stl/cstring.h"
5#include "fl/stl/noexcept.h"
6
7namespace fl {
8
9// Forward declarations
10class basic_string;
11class string; // IWYU pragma: keep
12
13// string_view: A non-owning view into a contiguous sequence of characters
14// Provides std::string_view-like functionality for embedded environments
15// Does NOT allocate memory or manage ownership
16// Similar to span<const char> but with string-specific operations
18 public:
19 // ======= STANDARD CONTAINER TYPE ALIASES =======
20 using element_type = const char;
21 using value_type = char;
22 using size_type = fl::size;
23 using difference_type = fl::i32;
24 using pointer = const char*;
25 using const_pointer = const char*;
26 using reference = const char&;
27 using const_reference = const char&;
28 using iterator = const char*;
29 using const_iterator = const char*;
30 using reverse_iterator = const char*;
31 using const_reverse_iterator = const char*;
32
33 // Special value to indicate "not found" or "until end"
34 // Using constexpr for C++11 implicit inline semantics - no ODR definition needed
35 static constexpr fl::size npos = static_cast<fl::size>(-1);
36
37 // ======= CONSTRUCTORS =======
38 // Default constructor - empty view
39 constexpr string_view() FL_NOEXCEPT : mData(nullptr), mSize(0) {}
40
41 // Constructor from null-terminated C string
42 constexpr string_view(const char* str) FL_NOEXCEPT
43 : mData(str), mSize(str ? strlen(str) : 0) {}
44
45 // Constructor from pointer and length
46 constexpr string_view(const char* str, fl::size len) FL_NOEXCEPT
47 : mData(str), mSize(len) {}
48
49 // Constructor from C-array
50 template <fl::size N>
51 constexpr string_view(const char (&arr)[N]) FL_NOEXCEPT
52 : mData(arr), mSize(N - 1) {} // Subtract 1 for null terminator
53
54 // Constructor from fl::basic_string (and therefore fl::string).
55 // Defined in basic_string.cpp.hpp where basic_string is complete.
57
58 // Copy constructor
59 string_view(const string_view& other) FL_NOEXCEPT = default;
60
61 // Assignment operator
62 string_view& operator=(const string_view& other) = default;
63
64 // ======= ITERATORS =======
65 constexpr iterator begin() const FL_NOEXCEPT { return mData; }
66 constexpr iterator end() const FL_NOEXCEPT { return mData + mSize; }
67 constexpr const_iterator cbegin() const FL_NOEXCEPT { return mData; }
68 constexpr const_iterator cend() const FL_NOEXCEPT { return mData + mSize; }
69
70 constexpr reverse_iterator rbegin() const FL_NOEXCEPT { return mData + mSize - 1; }
71 constexpr reverse_iterator rend() const FL_NOEXCEPT { return mData - 1; }
72 constexpr const_reverse_iterator crbegin() const FL_NOEXCEPT { return mData + mSize - 1; }
73 constexpr const_reverse_iterator crend() const FL_NOEXCEPT { return mData - 1; }
74
75 // ======= ELEMENT ACCESS =======
76 constexpr const char& operator[](fl::size index) const FL_NOEXCEPT {
77 // No bounds checking in embedded environment
78 return mData[index];
79 }
80
81 constexpr const char& at(fl::size index) const FL_NOEXCEPT {
82 // Basic bounds checking
83 return (index < mSize) ? mData[index] : mData[0];
84 }
85
86 constexpr const char& front() const FL_NOEXCEPT {
87 return mData[0];
88 }
89
90 constexpr const char& back() const FL_NOEXCEPT {
91 return mData[mSize - 1];
92 }
93
94 constexpr const char* data() const FL_NOEXCEPT {
95 return mData;
96 }
97
98 // ======= CAPACITY =======
99 constexpr fl::size size() const FL_NOEXCEPT { return mSize; }
100 constexpr fl::size length() const FL_NOEXCEPT { return mSize; }
101 constexpr fl::size max_size() const FL_NOEXCEPT { return npos - 1; }
102 constexpr bool empty() const FL_NOEXCEPT { return mSize == 0; }
103
104 // ======= MODIFIERS (modify the view, not the data) =======
105 void remove_prefix(fl::size n) FL_NOEXCEPT {
106 if (n > mSize) n = mSize;
107 mData += n;
108 mSize -= n;
109 }
110
111 void remove_suffix(fl::size n) FL_NOEXCEPT {
112 if (n > mSize) n = mSize;
113 mSize -= n;
114 }
115
117 const char* tmp_data = mData;
118 fl::size tmp_size = mSize;
119 mData = other.mData;
120 mSize = other.mSize;
121 other.mData = tmp_data;
122 other.mSize = tmp_size;
123 }
124
125 // ======= STRING OPERATIONS =======
126 // Copy substring to buffer
127 fl::size copy(char* dest, fl::size count, fl::size pos = 0) const FL_NOEXCEPT {
128 if (!dest || pos >= mSize) {
129 return 0;
130 }
131 fl::size actual_count = count;
132 if (actual_count > mSize - pos) {
133 actual_count = mSize - pos;
134 }
135 if (actual_count > 0) {
136 fl::memcpy(dest, mData + pos, actual_count);
137 }
138 return actual_count;
139 }
140
141 // Substring operations
142 string_view substr(fl::size pos = 0, fl::size count = npos) const FL_NOEXCEPT {
143 if (pos >= mSize) {
144 return string_view();
145 }
146 fl::size actual_count = count;
147 if (actual_count == npos || pos + actual_count > mSize) {
148 actual_count = mSize - pos;
149 }
150 return string_view(mData + pos, actual_count);
151 }
152
153 // ======= COMPARISON OPERATIONS =======
154 int compare(string_view other) const FL_NOEXCEPT {
155 fl::size min_len = (mSize < other.mSize) ? mSize : other.mSize;
156 for (fl::size i = 0; i < min_len; ++i) {
157 if (mData[i] < other.mData[i]) return -1;
158 if (mData[i] > other.mData[i]) return 1;
159 }
160 if (mSize < other.mSize) return -1;
161 if (mSize > other.mSize) return 1;
162 return 0;
163 }
164
165 int compare(fl::size pos1, fl::size count1, string_view other) const FL_NOEXCEPT {
166 return substr(pos1, count1).compare(other);
167 }
168
169 int compare(fl::size pos1, fl::size count1, string_view other,
170 fl::size pos2, fl::size count2) const FL_NOEXCEPT {
171 return substr(pos1, count1).compare(other.substr(pos2, count2));
172 }
173
174 int compare(const char* s) const FL_NOEXCEPT {
175 return compare(string_view(s));
176 }
177
178 int compare(fl::size pos1, fl::size count1, const char* s) const FL_NOEXCEPT {
179 return substr(pos1, count1).compare(string_view(s));
180 }
181
182 int compare(fl::size pos1, fl::size count1, const char* s, fl::size count2) const FL_NOEXCEPT {
183 return substr(pos1, count1).compare(string_view(s, count2));
184 }
185
186 // ======= SEARCH OPERATIONS =======
187 // Find character
188 fl::size find(char ch, fl::size pos = 0) const FL_NOEXCEPT {
189 if (pos >= mSize) return npos;
190 for (fl::size i = pos; i < mSize; ++i) {
191 if (mData[i] == ch) {
192 return i;
193 }
194 }
195 return npos;
196 }
197
198 // Find substring
199 fl::size find(string_view sv, fl::size pos = 0) const FL_NOEXCEPT {
200 if (sv.empty()) return pos;
201 if (pos >= mSize || sv.mSize > mSize - pos) return npos;
202
203 for (fl::size i = pos; i <= mSize - sv.mSize; ++i) {
204 bool match = true;
205 for (fl::size j = 0; j < sv.mSize; ++j) {
206 if (mData[i + j] != sv.mData[j]) {
207 match = false;
208 break;
209 }
210 }
211 if (match) return i;
212 }
213 return npos;
214 }
215
216 fl::size find(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
217 return find(string_view(s, count), pos);
218 }
219
220 fl::size find(const char* s, fl::size pos = 0) const FL_NOEXCEPT {
221 return find(string_view(s), pos);
222 }
223
224 // Reverse find
225 fl::size rfind(char ch, fl::size pos = npos) const FL_NOEXCEPT {
226 if (mSize == 0) return npos;
227 fl::size search_pos = (pos >= mSize || pos == npos) ? (mSize - 1) : pos;
228 for (fl::size i = search_pos + 1; i > 0; --i) {
229 if (mData[i - 1] == ch) {
230 return i - 1;
231 }
232 }
233 return npos;
234 }
235
236 fl::size rfind(string_view sv, fl::size pos = npos) const FL_NOEXCEPT {
237 if (sv.empty()) return (pos > mSize) ? mSize : pos;
238 if (sv.mSize > mSize) return npos;
239
240 fl::size max_start = mSize - sv.mSize;
241 fl::size search_start = (pos >= mSize || pos == npos) ? max_start : pos;
242 if (search_start + sv.mSize > mSize) {
243 search_start = max_start;
244 }
245
246 for (fl::size i = search_start + 1; i > 0; --i) {
247 fl::size idx = i - 1;
248 if (idx + sv.mSize > mSize) continue;
249 bool match = true;
250 for (fl::size j = 0; j < sv.mSize; ++j) {
251 if (mData[idx + j] != sv.mData[j]) {
252 match = false;
253 break;
254 }
255 }
256 if (match) return idx;
257 }
258 return npos;
259 }
260
261 fl::size rfind(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
262 return rfind(string_view(s, count), pos);
263 }
264
265 fl::size rfind(const char* s, fl::size pos = npos) const FL_NOEXCEPT {
266 return rfind(string_view(s), pos);
267 }
268
269 // Find first of any character in set
270 fl::size find_first_of(string_view sv, fl::size pos = 0) const FL_NOEXCEPT {
271 if (pos >= mSize || sv.empty()) return npos;
272 for (fl::size i = pos; i < mSize; ++i) {
273 for (fl::size j = 0; j < sv.mSize; ++j) {
274 if (mData[i] == sv.mData[j]) {
275 return i;
276 }
277 }
278 }
279 return npos;
280 }
281
282 fl::size find_first_of(char ch, fl::size pos = 0) const FL_NOEXCEPT {
283 return find(ch, pos);
284 }
285
286 fl::size find_first_of(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
287 return find_first_of(string_view(s, count), pos);
288 }
289
290 fl::size find_first_of(const char* s, fl::size pos = 0) const FL_NOEXCEPT {
291 return find_first_of(string_view(s), pos);
292 }
293
294 // Find last of any character in set
295 fl::size find_last_of(string_view sv, fl::size pos = npos) const FL_NOEXCEPT {
296 if (mSize == 0 || sv.empty()) return npos;
297 fl::size search_pos = (pos >= mSize || pos == npos) ? (mSize - 1) : pos;
298 for (fl::size i = search_pos + 1; i > 0; --i) {
299 for (fl::size j = 0; j < sv.mSize; ++j) {
300 if (mData[i - 1] == sv.mData[j]) {
301 return i - 1;
302 }
303 }
304 }
305 return npos;
306 }
307
308 fl::size find_last_of(char ch, fl::size pos = npos) const FL_NOEXCEPT {
309 return rfind(ch, pos);
310 }
311
312 fl::size find_last_of(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
313 return find_last_of(string_view(s, count), pos);
314 }
315
316 fl::size find_last_of(const char* s, fl::size pos = npos) const FL_NOEXCEPT {
317 return find_last_of(string_view(s), pos);
318 }
319
320 // Find first not of any character in set
321 fl::size find_first_not_of(string_view sv, fl::size pos = 0) const FL_NOEXCEPT {
322 if (pos >= mSize) return npos;
323 for (fl::size i = pos; i < mSize; ++i) {
324 bool found = false;
325 for (fl::size j = 0; j < sv.mSize; ++j) {
326 if (mData[i] == sv.mData[j]) {
327 found = true;
328 break;
329 }
330 }
331 if (!found) return i;
332 }
333 return npos;
334 }
335
336 fl::size find_first_not_of(char ch, fl::size pos = 0) const FL_NOEXCEPT {
337 if (pos >= mSize) return npos;
338 for (fl::size i = pos; i < mSize; ++i) {
339 if (mData[i] != ch) return i;
340 }
341 return npos;
342 }
343
344 fl::size find_first_not_of(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
345 return find_first_not_of(string_view(s, count), pos);
346 }
347
348 fl::size find_first_not_of(const char* s, fl::size pos = 0) const FL_NOEXCEPT {
350 }
351
352 // Find last not of any character in set
353 fl::size find_last_not_of(string_view sv, fl::size pos = npos) const FL_NOEXCEPT {
354 if (mSize == 0) return npos;
355 fl::size search_pos = (pos >= mSize || pos == npos) ? (mSize - 1) : pos;
356 for (fl::size i = search_pos + 1; i > 0; --i) {
357 bool found = false;
358 for (fl::size j = 0; j < sv.mSize; ++j) {
359 if (mData[i - 1] == sv.mData[j]) {
360 found = true;
361 break;
362 }
363 }
364 if (!found) return i - 1;
365 }
366 return npos;
367 }
368
369 fl::size find_last_not_of(char ch, fl::size pos = npos) const FL_NOEXCEPT {
370 if (mSize == 0) return npos;
371 fl::size search_pos = (pos >= mSize || pos == npos) ? (mSize - 1) : pos;
372 for (fl::size i = search_pos + 1; i > 0; --i) {
373 if (mData[i - 1] != ch) return i - 1;
374 }
375 return npos;
376 }
377
378 fl::size find_last_not_of(const char* s, fl::size pos, fl::size count) const FL_NOEXCEPT {
379 return find_last_not_of(string_view(s, count), pos);
380 }
381
382 fl::size find_last_not_of(const char* s, fl::size pos = npos) const FL_NOEXCEPT {
383 return find_last_not_of(string_view(s), pos);
384 }
385
386 // ======= C++20/C++23 CONVENIENCE METHODS =======
388 if (sv.mSize > mSize) return false;
389 for (fl::size i = 0; i < sv.mSize; ++i) {
390 if (mData[i] != sv.mData[i]) return false;
391 }
392 return true;
393 }
394
395 bool starts_with(char ch) const FL_NOEXCEPT {
396 return !empty() && mData[0] == ch;
397 }
398
399 bool starts_with(const char* s) const FL_NOEXCEPT {
400 return starts_with(string_view(s));
401 }
402
404 if (sv.mSize > mSize) return false;
405 for (fl::size i = 0; i < sv.mSize; ++i) {
406 if (mData[mSize - sv.mSize + i] != sv.mData[i]) return false;
407 }
408 return true;
409 }
410
411 bool ends_with(char ch) const FL_NOEXCEPT {
412 return !empty() && mData[mSize - 1] == ch;
413 }
414
415 bool ends_with(const char* s) const FL_NOEXCEPT {
416 return ends_with(string_view(s));
417 }
418
420 return find(sv) != npos;
421 }
422
423 bool contains(char ch) const FL_NOEXCEPT {
424 return find(ch) != npos;
425 }
426
427 bool contains(const char* s) const FL_NOEXCEPT {
428 return find(s) != npos;
429 }
430
431 private:
432 const char* mData;
433 fl::size mSize;
434};
435
436// ======= COMPARISON OPERATORS =======
438 return lhs.compare(rhs) == 0;
439}
440
442 return lhs.compare(rhs) != 0;
443}
444
446 return lhs.compare(rhs) < 0;
447}
448
450 return lhs.compare(rhs) <= 0;
451}
452
454 return lhs.compare(rhs) > 0;
455}
456
458 return lhs.compare(rhs) >= 0;
459}
460
461// ======= OUTPUT HELPER =======
462// Inline hash function for string_view
464 // FNV-1a 32-bit hash algorithm
465 u32 hash = 2166136261u;
466 for (fl::size i = 0; i < sv.size(); ++i) {
467 hash ^= static_cast<u32>(sv[i]);
468 hash *= 16777619u;
469 }
470 return hash;
471}
472
473} // namespace fl
uint8_t pos
Definition Blur.ino:11
Concrete type-erased string class.
constexpr bool empty() const FL_NOEXCEPT
constexpr string_view(const char *str, fl::size len) FL_NOEXCEPT
Definition string_view.h:46
bool starts_with(char ch) const FL_NOEXCEPT
fl::size find_first_not_of(string_view sv, fl::size pos=0) const FL_NOEXCEPT
constexpr iterator end() const FL_NOEXCEPT
Definition string_view.h:66
int compare(fl::size pos1, fl::size count1, string_view other, fl::size pos2, fl::size count2) const FL_NOEXCEPT
const char * mData
int compare(fl::size pos1, fl::size count1, const char *s, fl::size count2) const FL_NOEXCEPT
bool contains(const char *s) const FL_NOEXCEPT
fl::i32 difference_type
Definition string_view.h:23
fl::size find_first_not_of(const char *s, fl::size pos=0) const FL_NOEXCEPT
fl::size find_last_of(char ch, fl::size pos=npos) const FL_NOEXCEPT
constexpr reverse_iterator rend() const FL_NOEXCEPT
Definition string_view.h:71
fl::size find_first_of(char ch, fl::size pos=0) const FL_NOEXCEPT
int compare(fl::size pos1, fl::size count1, string_view other) const FL_NOEXCEPT
static constexpr fl::size npos
Definition string_view.h:35
bool contains(char ch) const FL_NOEXCEPT
constexpr const_reverse_iterator crbegin() const FL_NOEXCEPT
Definition string_view.h:72
fl::size find_first_of(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
bool ends_with(string_view sv) const FL_NOEXCEPT
constexpr string_view(const char *str) FL_NOEXCEPT
Definition string_view.h:42
constexpr iterator begin() const FL_NOEXCEPT
Definition string_view.h:65
fl::size rfind(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
fl::size find_last_not_of(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
void remove_suffix(fl::size n) FL_NOEXCEPT
bool starts_with(const char *s) const FL_NOEXCEPT
const char & reference
Definition string_view.h:26
constexpr const_iterator cend() const FL_NOEXCEPT
Definition string_view.h:68
constexpr fl::size max_size() const FL_NOEXCEPT
int compare(string_view other) const FL_NOEXCEPT
const char * const_iterator
Definition string_view.h:29
const char & const_reference
Definition string_view.h:27
fl::size find_first_not_of(char ch, fl::size pos=0) const FL_NOEXCEPT
constexpr fl::size size() const FL_NOEXCEPT
Definition string_view.h:99
constexpr const char & front() const FL_NOEXCEPT
Definition string_view.h:86
constexpr const_reverse_iterator crend() const FL_NOEXCEPT
Definition string_view.h:73
const char * const_reverse_iterator
Definition string_view.h:31
fl::size find_first_not_of(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
constexpr string_view(const char(&arr)[N]) FL_NOEXCEPT
Definition string_view.h:51
const char * pointer
Definition string_view.h:24
fl::size rfind(string_view sv, fl::size pos=npos) const FL_NOEXCEPT
const char * reverse_iterator
Definition string_view.h:30
fl::size find(char ch, fl::size pos=0) const FL_NOEXCEPT
fl::size find(const char *s, fl::size pos=0) const FL_NOEXCEPT
bool ends_with(char ch) const FL_NOEXCEPT
string_view(const string_view &other) FL_NOEXCEPT=default
constexpr const char & operator[](fl::size index) const FL_NOEXCEPT
Definition string_view.h:76
fl::size find_last_not_of(const char *s, fl::size pos=npos) const FL_NOEXCEPT
fl::size size_type
Definition string_view.h:22
fl::size find(string_view sv, fl::size pos=0) const FL_NOEXCEPT
string_view & operator=(const string_view &other)=default
fl::size copy(char *dest, fl::size count, fl::size pos=0) const FL_NOEXCEPT
fl::size rfind(char ch, fl::size pos=npos) const FL_NOEXCEPT
int compare(fl::size pos1, fl::size count1, const char *s) const FL_NOEXCEPT
bool ends_with(const char *s) const FL_NOEXCEPT
fl::size find(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
constexpr fl::size length() const FL_NOEXCEPT
fl::size rfind(const char *s, fl::size pos=npos) const FL_NOEXCEPT
fl::size find_last_of(string_view sv, fl::size pos=npos) const FL_NOEXCEPT
fl::size find_last_not_of(char ch, fl::size pos=npos) const FL_NOEXCEPT
constexpr reverse_iterator rbegin() const FL_NOEXCEPT
Definition string_view.h:70
constexpr const_iterator cbegin() const FL_NOEXCEPT
Definition string_view.h:67
constexpr const char * data() const FL_NOEXCEPT
Definition string_view.h:94
bool contains(string_view sv) const FL_NOEXCEPT
bool starts_with(string_view sv) const FL_NOEXCEPT
constexpr const char & back() const FL_NOEXCEPT
Definition string_view.h:90
const char element_type
Definition string_view.h:20
const char * const_pointer
Definition string_view.h:25
fl::size find_first_of(string_view sv, fl::size pos=0) const FL_NOEXCEPT
void swap(string_view &other) FL_NOEXCEPT
const char * iterator
Definition string_view.h:28
fl::size find_last_of(const char *s, fl::size pos, fl::size count) const FL_NOEXCEPT
string_view substr(fl::size pos=0, fl::size count=npos) const FL_NOEXCEPT
fl::size find_last_not_of(string_view sv, fl::size pos=npos) const FL_NOEXCEPT
int compare(const char *s) const FL_NOEXCEPT
fl::size find_last_of(const char *s, fl::size pos=npos) const FL_NOEXCEPT
constexpr const char & at(fl::size index) const FL_NOEXCEPT
Definition string_view.h:81
fl::size find_first_of(const char *s, fl::size pos=0) const FL_NOEXCEPT
void remove_prefix(fl::size n) FL_NOEXCEPT
constexpr string_view() FL_NOEXCEPT
Definition string_view.h:39
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
size_t strlen(const char *s) FL_NOEXCEPT
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects do not have the same color data.
Definition crgb.h:739
FASTLED_FORCE_INLINE bool operator<(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than another.
Definition crgb.h:745
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects have the same color data.
Definition crgb.h:733
FASTLED_FORCE_INLINE bool operator>(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than another.
Definition crgb.h:754
FASTLED_FORCE_INLINE bool operator<=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than or equal to another.
Definition crgb.h:772
u32 hash_string_view(string_view sv) FL_NOEXCEPT
FASTLED_FORCE_INLINE bool operator>=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than or equal to another.
Definition crgb.h:763
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT