libDaisy
Hardware Library for Daisy
Loading...
Searching...
No Matches
FixedCapStr.h
Go to the documentation of this file.
1
5#pragma once
6
7#include <string_view>
8#include <algorithm>
9
10namespace daisy
11{
12template <class CharType = char>
14{
15 public:
16 constexpr FixedCapStrBase(CharType* buffer, size_t capacity)
17 : capacity_(capacity), buffer_(buffer)
18 {
19 }
20
21 constexpr FixedCapStrBase(const FixedCapStrBase& other) = delete;
22
24 {
25 size_ = std::min(str.Size(), capacity_);
26 Copy_(str.Data(), str.Data() + size_, buffer_);
27 buffer_[size_] = 0;
28 return *this;
29 }
30
32 {
33 size_ = std::min(strlen(str), capacity_);
35 buffer_[size_] = 0;
36 return *this;
37 }
38
39 constexpr operator const CharType*() const noexcept { return buffer_; }
40 constexpr const CharType* Cstr() const noexcept { return buffer_; }
41 constexpr const CharType* Data() const noexcept { return buffer_; }
42 constexpr CharType* Data() noexcept { return buffer_; }
43
44 constexpr auto Size() const noexcept { return size_; }
45 constexpr auto UpdateSize() noexcept
46 {
47 size_ = std::min(strlen(buffer_), capacity_);
48 buffer_[size_] = 0;
49 }
50
51 constexpr auto Capacity() const noexcept { return capacity_; }
52
53 constexpr auto Empty() const noexcept { return size_ == 0; }
54
55 constexpr void Clear() noexcept
56 {
57 size_ = 0;
58 buffer_[0] = '\0';
59 }
60
61 constexpr void Reset(const CharType* str)
62 {
63 size_ = std::min(strlen(str), capacity_);
65 }
66
67 constexpr void Reset(const CharType* str, std::size_t length)
68 {
69 size_ = std::min(length, capacity_);
71 }
72
73 constexpr void ResetAt(const CharType* str, std::size_t writePosition)
74 {
76 return;
77 const auto strLen = strlen(str);
78 const auto newSize
79 = std::max(std::min(strLen + writePosition, capacity_), size_);
80 const auto numCharsToWrite = std::min(newSize - writePosition, strLen);
81 size_ = newSize;
83 }
84
85 constexpr void Append(const CharType singleChar)
86 {
87 if(size_ < capacity_)
88 {
90 buffer_[size_ + 1] = '\0';
91 size_++;
92 }
93 }
94
95 constexpr void Append(const CharType* str)
96 {
97 auto to_copy = std::min(strlen(str), (capacity_ - size_));
99 }
100
101 constexpr void Append(const CharType* str, std::size_t length)
102 {
103 auto to_copy = std::min(length, (capacity_ - size_));
105 }
106
107 template <typename IntType>
108 constexpr void AppendInt(IntType value, bool alwaysIncludeSign = false)
109 {
110 if(value == 0)
111 {
113 Append('+');
114 Append("0");
115 return;
116 }
117
118 if(value < 0)
119 {
120 value = -value;
121 Append('-');
122 }
123 else if(alwaysIncludeSign)
124 Append('+');
125
126 const auto firstDigit = Size();
127 while(value != 0)
128 {
129 const auto rem = value % 10;
130 value = value / 10;
131 Append(rem + '0');
132 }
133 const auto lastDigit = Size() - 1;
135 }
136
137 constexpr void AppendFloat(float value,
138 int maxNumDigits = 2,
139 bool omitTrailingZeros = false,
140 bool alwaysIncludeSign = false)
141 {
142 if(value == 0.0f)
143 {
145 Append('+');
146 Append("0");
147 if((!omitTrailingZeros) && (maxNumDigits > 0))
148 {
149 Append(".");
150 for(int i = 0; i < maxNumDigits; i++)
151 Append("0");
152 }
153 return;
154 }
155
156 if(value < 0)
157 {
158 value = -value;
159 Append('-');
160 }
161 else if(alwaysIncludeSign)
162 Append('+');
163
164 float factor = 1;
165 constexpr int tableSize = 10;
166 // clang-format off
167 constexpr float powTable[tableSize] = {
168 1.0f,
169 10.0f,
170 100.0f,
171 1000.0f,
172 10000.0f,
173 100000.0f,
174 1000000.0f,
175 10000000.0f,
176 100000000.0f,
177 1000000000.0f
178 };
179 constexpr float roundOffsTable[tableSize] = {
180 0.5f,
181 0.05f,
182 0.005f,
183 0.0005f,
184 0.00005f,
185 0.000005f,
186 0.0000005f,
187 0.00000005f,
188 0.000000005f,
189 };
190 // clang-format on
192 {
195 }
196 else
197 {
198 float roundOffs = 0.5f;
199 for(int i = 0; i < maxNumDigits; i++)
200 {
201 factor *= 10.0f;
202 roundOffs /= 10.0f;
203 }
204 value += roundOffs;
205 }
206
207 int beforeDecPt = int(value);
208 int afterDecPt = int(value * factor);
209
210 const auto firstDigit = Size();
211 // print digits after the decimal point
212 for(int i = 0; i < maxNumDigits; i++)
213 {
214 const auto rem = afterDecPt % 10;
215 afterDecPt = afterDecPt / 10;
216 if((rem == 0) && (omitTrailingZeros))
217 continue;
218 Append(rem + '0');
219 }
220 // print decimal point
221 if(Size() != firstDigit)
222 Append('.');
223 // print digits before the decimal point
224 if(beforeDecPt == 0)
225 Append('0');
226 else
227 {
228 while(beforeDecPt != 0)
229 {
230 const auto rem = beforeDecPt % 10;
232 Append(rem + '0');
233 }
234 }
235 const auto lastDigit = Size() - 1;
237 }
238
239 constexpr bool StartsWith(const CharType* pattern) const noexcept
240 {
241 const CharType* ptr = buffer_;
242 while(*pattern)
243 {
244 if(*ptr != *pattern)
245 return false;
246 pattern++;
247 ptr++;
248 }
249 return true;
250 }
251
252 constexpr bool
254 {
255 const CharType* ptr = buffer_;
256 while(*pattern)
257 {
258 if(ToUpper_(*ptr) != ToUpper_(*pattern))
259 return false;
260 pattern++;
261 ptr++;
262 }
263 return true;
264 }
265
266 constexpr bool EndsWith(const CharType* pattern) const noexcept
267 {
268 const CharType* ptr = &buffer_[size_ - 1];
269 const auto patternLength = strlen(pattern);
271 while(patternPtr > pattern)
272 {
273 if(*ptr != *patternPtr)
274 return false;
275 patternPtr--;
276 ptr--;
277 }
278 return *ptr == *patternPtr;
279 }
280
281 constexpr bool EndsWithIgnoringCase(const CharType* pattern) const noexcept
282 {
283 const CharType* ptr = &buffer_[size_ - 1];
284 const auto patternLength = strlen(pattern);
286 while(patternPtr > pattern)
287 {
288 if(ToUpper_(*ptr) != ToUpper_(*patternPtr))
289 return false;
290 patternPtr--;
291 ptr--;
292 }
293 return ToUpper_(*ptr) == ToUpper_(*patternPtr);
294 }
295
296 constexpr void RemovePrefix(std::size_t length)
297 {
298 Copy_(buffer_ + length, buffer_ + size_, buffer_);
299 size_ -= length;
300 buffer_[size_] = '\0';
301 }
302
303 constexpr void RemoveSuffix(std::size_t length) noexcept
304 {
305 size_ = size_ - length;
306 buffer_[size_] = '\0';
307 }
308
309 constexpr void ReverseSection(std::size_t firstIdx, std::size_t lastIdx)
310 {
311 firstIdx = clamp(firstIdx, 0, size_ - 1);
312 lastIdx = clamp(lastIdx, 0, size_ - 1);
313 while(firstIdx < lastIdx)
314 {
318 firstIdx++;
319 lastIdx--;
320 }
321 }
322
323 constexpr bool operator==(const CharType* rhs) const
324 {
325 const CharType* ptr = buffer_;
326 while(*rhs && *ptr) // abort on first string end
327 {
328 if(*ptr != *rhs)
329 return false;
330 rhs++;
331 ptr++;
332 }
333
334 return *rhs == *ptr; // both strings ended at the same '0'?
335 }
336
337 constexpr bool operator!=(const CharType* rhs) const
338 {
339 return !(*this == rhs);
340 }
341
342 constexpr bool operator<(const CharType* other) const
343 {
344 auto ptr = buffer_;
345 while(*ptr && *other && (*ptr == *other))
346 {
347 ptr++;
348 other++;
349 }
350 return *ptr < *other;
351 }
352
353 constexpr bool operator<=(const CharType* other) const
354 {
355 return (*this == other) || (*this < other);
356 }
357
358 constexpr bool operator>(const CharType* other) const
359 {
360 auto ptr = buffer_;
361 while(*ptr && *other && (*ptr == *other))
362 {
363 ptr++;
364 other++;
365 }
366 return *ptr > *other;
367 }
368
369 constexpr bool operator>=(const CharType* other) const
370 {
371 return (*this == other) || (*this > other);
372 }
373
374 constexpr void Swap(FixedCapStrBase& rhs) noexcept
375 {
376 auto tmp = size_;
377 size_ = rhs.size_;
378 rhs.size_ = tmp;
379
380 Swap_(buffer_, rhs.buffer_, std::max(size_, rhs.size_));
381 }
382
383 protected:
384 static constexpr std::size_t strlen(const CharType* string)
385 {
386 std::size_t result = 0;
387 while(*string++ != '\0')
388 result++;
389 return result;
390 }
391
392 constexpr void Reset_(const CharType* str, std::size_t length)
393 {
394 Copy_(str, str + length, buffer_);
395 buffer_[length] = '\0';
396 }
397
398 constexpr void
399 ResetAt_(const CharType* str, std::size_t strLen, std::size_t writePosition)
400 {
403 buffer_[writePosition + strLen] = '\0';
404 }
405
406 constexpr void Append_(const CharType* str, std::size_t to_copy)
407 {
409 size_ += to_copy;
410 buffer_[size_] = '\0';
411 }
412
413 static constexpr void
415 {
416 while(src != srcEnd)
417 {
418 *dest = *src;
419 src++;
420 dest++;
421 }
422 }
423
424 static constexpr void Swap_(CharType* a, CharType* b, size_t length)
425 {
426 for(size_t i = 0; i < length; i++)
427 {
428 CharType tmp = *a;
429 *a = *b;
430 *b = tmp;
431 a++;
432 b++;
433 }
434 }
435
436 // TODO: add wstring version
437 static constexpr char ToUpper_(char c) noexcept
438 {
439 switch(c)
440 {
441 default: return c;
442 case 'a': return 'A';
443 case 'b': return 'B';
444 case 'c': return 'C';
445 case 'd': return 'D';
446 case 'e': return 'E';
447 case 'f': return 'F';
448 case 'g': return 'G';
449 case 'h': return 'H';
450 case 'i': return 'I';
451 case 'j': return 'J';
452 case 'k': return 'K';
453 case 'l': return 'L';
454 case 'm': return 'M';
455 case 'n': return 'N';
456 case 'o': return 'O';
457 case 'p': return 'P';
458 case 'q': return 'Q';
459 case 'r': return 'R';
460 case 's': return 'S';
461 case 't': return 'T';
462 case 'u': return 'U';
463 case 'v': return 'V';
464 case 'w': return 'W';
465 case 'x': return 'X';
466 case 'y': return 'Y';
467 case 'z': return 'Z';
468 }
469 }
470
471 std::size_t clamp(std::size_t val, std::size_t min, std::size_t max)
472 {
473 return (val < min) ? min : ((val > max) ? max : val);
474 }
475
476 std::size_t size_{0};
477 const size_t capacity_;
479};
480
488template <std::size_t capacity, class CharType = char>
489class FixedCapStr : public FixedCapStrBase<CharType>
490{
491 public:
493 : FixedCapStrBase<CharType>(buffer_, capacity)
494 {
495 }
496
498 : FixedCapStrBase<CharType>(buffer_, capacity)
499 {
500 this->size_ = std::min(str.Size(), capacity);
501 this->Copy_(str.Data(), str.Data() + this->size_, buffer_);
502 }
503
504 template <size_t otherSize>
506 : FixedCapStrBase<CharType>(buffer_, capacity)
507 {
508 this->size_ = std::min(str.Size(), capacity);
509 this->Copy_(str.Data(), str.Data() + this->size_, buffer_);
510 }
511
513 : FixedCapStrBase<CharType>(buffer_, capacity)
514 {
515 this->size_ = std::min(this->strlen(str), capacity);
516 this->Copy_(str, str + this->size_, buffer_);
517 }
518
519 constexpr FixedCapStr(const CharType* str, std::size_t length) noexcept
520 : FixedCapStrBase<CharType>(buffer_, capacity)
521 {
522 this->size_ = std::min(length, capacity);
523 this->Copy_(str, str + this->size_, buffer_);
524 }
525
526 constexpr FixedCapStr& operator=(const FixedCapStr& str) noexcept
527 {
528 *static_cast<FixedCapStrBase<CharType>*>(this) = str;
529 return *this;
530 }
531
532 private:
533 CharType buffer_[capacity + 1]{};
534};
535
536template <class CharType, std::size_t capacity>
537inline constexpr void Swap(const FixedCapStr<capacity, CharType>& lhs,
538 const FixedCapStr<capacity, CharType>& rhs) noexcept
539{
540 rhs.Swap(lhs);
541}
542
543} // namespace daisy
Definition FixedCapStr.h:14
constexpr bool StartsWithIgnoringCase(const CharType *pattern) const noexcept
Definition FixedCapStr.h:253
constexpr CharType * Data() noexcept
Definition FixedCapStr.h:42
constexpr bool operator>(const CharType *other) const
Definition FixedCapStr.h:358
constexpr bool operator==(const CharType *rhs) const
Definition FixedCapStr.h:323
constexpr void Append(const CharType *str)
Definition FixedCapStr.h:95
constexpr void AppendFloat(float value, int maxNumDigits=2, bool omitTrailingZeros=false, bool alwaysIncludeSign=false)
Definition FixedCapStr.h:137
static constexpr std::size_t strlen(const CharType *string)
Definition FixedCapStr.h:384
constexpr void RemovePrefix(std::size_t length)
Definition FixedCapStr.h:296
constexpr void Reset_(const CharType *str, std::size_t length)
Definition FixedCapStr.h:392
constexpr FixedCapStrBase(CharType *buffer, size_t capacity)
Definition FixedCapStr.h:16
constexpr void ResetAt(const CharType *str, std::size_t writePosition)
Definition FixedCapStr.h:73
constexpr void Reset(const CharType *str, std::size_t length)
Definition FixedCapStr.h:67
constexpr FixedCapStrBase(const FixedCapStrBase &other)=delete
constexpr const CharType * Data() const noexcept
Definition FixedCapStr.h:41
constexpr FixedCapStrBase & operator=(const FixedCapStrBase &str)
Definition FixedCapStr.h:23
CharType * buffer_
Definition FixedCapStr.h:478
const size_t capacity_
Definition FixedCapStr.h:477
constexpr void Append_(const CharType *str, std::size_t to_copy)
Definition FixedCapStr.h:406
constexpr auto Capacity() const noexcept
Definition FixedCapStr.h:51
constexpr bool operator<=(const CharType *other) const
Definition FixedCapStr.h:353
constexpr bool EndsWith(const CharType *pattern) const noexcept
Definition FixedCapStr.h:266
constexpr void AppendInt(IntType value, bool alwaysIncludeSign=false)
Definition FixedCapStr.h:108
static constexpr void Copy_(const CharType *src, const CharType *srcEnd, CharType *dest)
Definition FixedCapStr.h:414
constexpr auto Empty() const noexcept
Definition FixedCapStr.h:53
constexpr bool EndsWithIgnoringCase(const CharType *pattern) const noexcept
Definition FixedCapStr.h:281
constexpr void Reset(const CharType *str)
Definition FixedCapStr.h:61
constexpr auto Size() const noexcept
Definition FixedCapStr.h:44
constexpr bool operator>=(const CharType *other) const
Definition FixedCapStr.h:369
std::size_t clamp(std::size_t val, std::size_t min, std::size_t max)
Definition FixedCapStr.h:471
static constexpr void Swap_(CharType *a, CharType *b, size_t length)
Definition FixedCapStr.h:424
constexpr void RemoveSuffix(std::size_t length) noexcept
Definition FixedCapStr.h:303
constexpr void Append(const CharType singleChar)
Definition FixedCapStr.h:85
constexpr const CharType * Cstr() const noexcept
Definition FixedCapStr.h:40
constexpr void Swap(FixedCapStrBase &rhs) noexcept
Definition FixedCapStr.h:374
constexpr void Append(const CharType *str, std::size_t length)
Definition FixedCapStr.h:101
static constexpr char ToUpper_(char c) noexcept
Definition FixedCapStr.h:437
constexpr bool operator<(const CharType *other) const
Definition FixedCapStr.h:342
constexpr bool StartsWith(const CharType *pattern) const noexcept
Definition FixedCapStr.h:239
constexpr void Clear() noexcept
Definition FixedCapStr.h:55
constexpr FixedCapStrBase & operator=(const CharType *str)
Definition FixedCapStr.h:31
constexpr bool operator!=(const CharType *rhs) const
Definition FixedCapStr.h:337
constexpr void ResetAt_(const CharType *str, std::size_t strLen, std::size_t writePosition)
Definition FixedCapStr.h:399
constexpr void ReverseSection(std::size_t firstIdx, std::size_t lastIdx)
Definition FixedCapStr.h:309
constexpr auto UpdateSize() noexcept
Definition FixedCapStr.h:45
std::size_t size_
Definition FixedCapStr.h:476
Definition FixedCapStr.h:490
constexpr FixedCapStr & operator=(const FixedCapStr &str) noexcept
Definition FixedCapStr.h:526
constexpr FixedCapStr(const FixedCapStr &str) noexcept
Definition FixedCapStr.h:497
constexpr FixedCapStr(const CharType *str) noexcept
Definition FixedCapStr.h:512
constexpr FixedCapStr(const FixedCapStr< otherSize > &str) noexcept
Definition FixedCapStr.h:505
constexpr FixedCapStr(const CharType *str, std::size_t length) noexcept
Definition FixedCapStr.h:519
constexpr FixedCapStr() noexcept
Definition FixedCapStr.h:492
Definition leddriver.h:33
Hardware defines and helpers for daisy field platform.
Definition index.h:2
constexpr void Swap(const FixedCapStr< capacity, CharType > &lhs, const FixedCapStr< capacity, CharType > &rhs) noexcept
Definition FixedCapStr.h:537