arduino-audio-tools
Str.h
1 #pragma once
2 
3 #include <stdio.h>
4 #include <string.h>
5 
6 #include "AudioTools/AudioLogger.h"
7 
16 namespace audio_tools {
17 
27 class Str {
28  public:
29  Str() = default;
30 
32  Str(const char* chars) {
33  if (chars != nullptr) {
34  int len = strlen(chars);
35  set((char*)chars, len, len, true);
36  } else {
37  this->is_const = true;
38  clear();
39  }
40  }
41 
43  Str(char chars[], int maxlen, int len = 0) { set(chars, maxlen, len, false); }
44 
46  virtual void set(const char* alt) {
47  if (alt == nullptr) {
48  this->len = 0;
49  } else {
50  int new_len = strlen(alt);
51  grow(new_len);
52  this->len = new_len;
53  if (this->isConst()) {
55  this->maxlen = this->len;
56  this->chars = (char*)alt;
57  } else {
59  strncpy(this->chars, alt, this->maxlen);
60  this->chars[len] = 0;
61  }
62  }
63  }
65  virtual void set(const Str& alt) {
66  grow(alt.len);
67  this->len = alt.len;
68 
69  if (this->isConst()) {
71  this->chars = alt.chars;
72  } else {
74  strncpy(this->chars, alt.chars, this->maxlen);
75  this->chars[len] = 0;
76  }
77  }
78 
79  virtual void set(const char c) {
80  clear();
81  add(c);
82  }
83 
84  virtual void set(int value) {
85  clear();
86  add(value);
87  }
88 
89  virtual void set(double value, int precision = 2, int withd = 0) {
90  clear();
91  add(value);
92  }
93 
94  virtual void swap(Str& str) {
95  char* cpy_chars = chars;
96  ;
97  bool cpy_is_const = is_const;
98  int cpy_len = len;
99  int cpy_maxlen = maxlen;
100 
101  chars = str.chars;
102  is_const = str.is_const;
103  len = str.len;
104  maxlen = str.maxlen;
105 
106  str.chars = cpy_chars;
107  str.is_const = cpy_is_const;
108  str.len = cpy_len;
109  str.maxlen = cpy_maxlen;
110  }
111 
113  virtual void set(char chars[], int maxlen, int len = 0,
114  bool isConst = false) {
115  this->chars = chars;
116  this->maxlen = maxlen;
117  this->len = len;
118  this->is_const = isConst;
119  if (len == 0 && !isConst) {
120  this->chars[0] = 0;
121  }
122  }
123 
125  virtual void add(int value) {
126  if (!this->isConst()) {
127  grow(this->length() + 11);
128  snprintf(this->chars + len, 10, "%d", value);
129  len = strlen(chars);
130  }
131  }
132 
134  virtual void add(double value, int precision = 2, int withd = 0) {
135  if (!this->isConst()) {
136  grow(this->length() + 20);
137  floatToString(this->chars + len, value, precision, withd);
138  len = strlen(chars);
139  }
140  }
141 
143  virtual void add(const char* append) {
144  if (!isConst() && append != nullptr) {
145  int append_len = strlen(append);
146  grow(this->length() + append_len + 1);
147  int n = (len + append_len) < maxlen - 1 ? append_len : maxlen - len - 1;
148  strncat(chars, append, n);
149  chars[len + n] = 0;
150  len = strlen(chars);
151  }
152  }
153 
155  virtual void add(const char c) {
156  if (!isConst() && len < maxlen - 1) {
157  grow(this->length() + 1);
158  chars[len] = c;
159  chars[++len] = 0;
160  }
161  }
162 
164  virtual bool equals(const char* str) {
165  if (str == nullptr) return false;
166  return strcmp(this->chars, str) == 0;
167  }
168 
170  virtual bool startsWith(const char* str) {
171  if (str == nullptr) return false;
172  int len = strlen(str);
173  return strncmp(this->chars, str, len) == 0;
174  }
175 
177  virtual bool endsWith(const char* str) {
178  if (str == nullptr) return false;
179  int endlen = strlen(str);
180  return strncmp(this->chars + (len - endlen), str, endlen) == 0;
181  }
182 
184  virtual bool endsWithIgnoreCase(const char* str) {
185  if (str == nullptr) return false;
186  int endlen = strlen(str);
187  return strncmp_i(this->chars + (len - endlen), str, endlen) == 0;
188  }
189 
201 
204  virtual bool matches(const char* pattern) {
207  int wildcard = 0;
208  const char* line = this->chars;
209 
210  const char* last_pattern_start = 0;
211  const char* last_line_start = 0;
212  do {
213  if (*pattern == *line) {
214  if (wildcard == 1) last_line_start = line + 1;
215 
216  line++;
217  pattern++;
218  wildcard = 0;
219  } else if (*pattern == '?') {
220  if (*(line) == '\0')
221  return 0;
222  if (wildcard == 1) last_line_start = line + 1;
223  line++;
224  pattern++;
225  wildcard = 0;
226  } else if (*pattern == '*') {
227  if (*(pattern + 1) == '\0') {
228  return 1;
229  }
230 
231  last_pattern_start = pattern;
232  // last_line_start = line + 1;
233  wildcard = 1;
234 
235  pattern++;
236  } else if (wildcard) {
237  if (*line == *pattern) {
238  wildcard = 0;
239  line++;
240  pattern++;
241  last_line_start = line + 1;
242  } else {
243  line++;
244  }
245  } else {
246  if ((*pattern) == '\0' && (*line) == '\0')
247  return 1;
248  else {
249  if (last_pattern_start != 0)
250  {
251  pattern = last_pattern_start;
252  line = last_line_start;
253  last_line_start = 0;
254  } else {
255  return false;
256  }
257  }
258  }
259 
260  } while (*line);
261 
262  if (*pattern == '\0') {
263  return true;
264  } else {
265  return false;
266  }
267  }
268 
271  virtual int indexOf(const char c, int start = 0) {
272  for (int j = start; j < len; j++) {
273  if (c == chars[j]) {
274  return j;
275  }
276  }
277  return -1;
278  }
279 
281  virtual bool contains(const char* str) { return indexOf(str) != -1; }
282 
285  virtual int indexOf(const char* cont, int start = 0) {
286  if (chars == nullptr || cont == nullptr) return -1;
287  int contLen = strlen(cont);
288  for (int j = start; j < len; j++) {
289  char* pt = chars + j;
290  if (strncmp(pt, cont, contLen) == 0) {
291  return j;
292  }
293  }
294  return -1;
295  }
296 
298  virtual int lastIndexOf(const char* cont) {
299  if (cont == nullptr) return -1;
300  int contLen = strlen(cont);
301  for (int j = (len - contLen); j >= 0; j--) {
302  if (strncmp(cont, chars + j, contLen) == 0) {
303  return j;
304  }
305  }
306  return -1;
307  }
308 
310  virtual void operator=(const char* str) { set(str); }
311 
313  virtual void operator=(char* str) { set(str); }
314 
316  virtual void operator=(char c) { set(c); }
317 
319  virtual void operator=(double val) { set(val); }
320 
322  virtual void operator=(int value) { set(value); }
323 
325  virtual void operator<<(int n) {
326  if (isConst()) {
327  this->chars += n;
328  this->len -= n;
329  } else {
330  memmove(this->chars, this->chars + n, len + 1);
331  }
332  }
333 
334  virtual char operator[](int index) { return chars[index]; }
335 
337  virtual void operator+=(const char* str) { add(str); }
338 
340  virtual void operator+=(int value) { add(value); }
341 
343  virtual void operator+=(double value) { add(value); }
344 
346  virtual void operator+=(const char value) { add(value); }
347 
349  virtual bool operator==(const Str& alt) const {
350  if (this->len != alt.len) return false;
351  return strncmp(this->chars, alt.chars, this->len) == 0;
352  }
353 
355  virtual bool operator==(const char* alt) const {
356  return strncmp(this->chars, alt, this->len) == 0;
357  }
358 
360  virtual bool operator!=(const Str& alt) const {
361  return strncmp(this->chars, alt.chars, this->len) != 0;
362  }
363 
365  virtual bool operator!=(const char* alt) const {
366  return strncmp(this->chars, alt, this->len) != 0;
367  }
368 
370  virtual const char* c_str() { return chars; }
371 
374  virtual int length() { return len; }
375 
377  virtual bool isEmpty() { return len == 0; }
378 
380  virtual int maxLength() { return maxlen; }
381 
383  virtual bool replace(const char* toReplace, const char* replaced) {
384  bool result = false;
385  if (toReplace == nullptr || replaced == nullptr) {
386  return result;
387  }
388  if (!isConst()) {
389  int pos = indexOf(toReplace);
390  int old_len = length();
391  int insert_len = 0;
392  if (pos >= 0) {
393  int len_replaced = strlen(replaced);
394  int len_to_replace = strlen(toReplace);
395  insert_len = len_replaced - len_to_replace;
396  grow(this->length() + insert_len);
397  // save remainder and create gap
398  memmove(this->chars + pos + len_replaced,
399  this->chars + pos + len_to_replace,
400  old_len - pos - len_to_replace + 1);
401  // move new string into gap
402  memmove(this->chars + pos, replaced, len_replaced);
403  result = true;
404  len += insert_len;
405  }
406  }
407  return result;
408  }
409 
411  virtual bool replaceAll(const char* toReplace, const char* replaced) {
412  if (indexOf(toReplace) == -1) {
413  return false;
414  }
415  while (replace(toReplace, replaced));
416  return true;
417  }
418 
420  virtual void remove(const char* toRemove) {
421  if (!isConst() && chars != nullptr) {
422  int removeLen = strlen(toRemove);
423  int pos = indexOf(toRemove);
424  if (pos >= 0) {
425  memmove((void*)(chars + pos), (void*)(chars + pos + removeLen),
426  len - (pos + removeLen) + 1);
427  len -= removeLen;
428  }
429  }
430  }
431 
433  virtual void removeAll(const char* toRemove) {
434  if (!isConst() && chars != nullptr) {
435  int removeLen = strlen(toRemove);
436  while (true) {
437  int pos = indexOf(toRemove);
438  if (pos == -1) {
439  break;
440  }
441  memmove((void*)(chars + pos), (void*)(chars + pos + removeLen),
442  len - (pos + removeLen) + 1);
443  len -= removeLen;
444  }
445  }
446  }
447 
449  virtual void setLength(int len, bool addZero = true) {
450  if (!isConst() && addZero) {
451  this->savedChar = chars[len];
452  this->savedLen = len;
453  this->len = len;
454  chars[len] = 0;
455  }
456  }
457 
459  virtual void setLengthUndo() {
460  if (savedLen >= 0) {
461  chars[len] = savedChar;
462  this->len = savedLen;
463  savedLen = -1;
464  }
465  }
466 
468  virtual void substring(Str& from, int start, int end) {
469  if (end > start) {
470  int len = end - start;
471  grow(len);
472  if (this->chars != nullptr) {
473  len = len < this->maxlen ? len : this->maxlen;
474  strncpy(this->chars, from.chars + start, len);
475  this->len = len;
476  this->chars[len] = 0;
477  }
478  }
479  }
480 
482  virtual void substring(const char* from, int start, int end) {
483  if (end > start) {
484  int len = end - start;
485  grow(len);
486  if (this->chars != nullptr) {
487  strncpy(this->chars, from + start, len);
488  this->chars[len] = 0;
489  this->len = len;
490  }
491  }
492  }
493 
495  virtual void trim() {
496  if (chars == nullptr) return;
497  rtrim();
498  ltrim();
499  }
500 
502  virtual int count(char c, int startPos) {
503  for (int j = startPos; j < len; j++) {
504  if (chars[j] != c) {
505  return j;
506  }
507  }
508  return 0;
509  }
510 
512  virtual void ltrim() {
513  if (chars == nullptr) return;
514  int n = count(' ', 0);
515  if (n > 0) *this << n;
516  }
517 
519  virtual void rtrim() {
520  if (chars == nullptr) return;
521  if (!isConst()) {
522  while (isspace(chars[len])) {
523  len--;
524  chars[len] = 0;
525  }
526  }
527  }
528 
530  virtual void clear() {
531  if (chars != nullptr && !isConst()) {
532  chars[0] = 0;
533  }
534  len = 0;
535  }
536 
538  virtual bool isOnHeap() { return false; }
539 
541  virtual bool isConst() { return is_const; }
542 
544  virtual void insert(int pos, const char* str) {
545  if (!isConst()) {
546  int insert_len = strlen(str);
547  grow(this->length() + insert_len);
548  int move_len = this->len - pos + 1;
549  memmove(chars + pos + insert_len, chars + pos, move_len);
550  strncpy(chars + pos, str, insert_len);
551  }
552  }
553 
555  virtual bool equalsIgnoreCase(const char* alt) const {
556  if ((size_t)len != strlen(alt)) {
557  return false;
558  }
559  for (int j = 0; j < len; j++) {
560  if (tolower(chars[j]) != tolower(alt[j])) return false;
561  }
562  return true;
563  }
564 
566  int toInt() {
567  int result = 0;
568  if (!isEmpty()) {
569  result = atoi(chars);
570  }
571  return result;
572  }
573 
575  long toLong() {
576  long result = 0;
577  if (!isEmpty()) {
578  result = atol(chars);
579  }
580  return result;
581  }
582 
584  double toDouble() {
585  double result = 0;
586  char* eptr;
587  if (!isEmpty()) {
588  result = strtod(chars, &eptr);
589  }
590  return result;
591  }
592 
594  void toLowerCase() {
595  if (chars != nullptr) {
596  for (int j = 0; j < len; j++) {
597  chars[j] = tolower(chars[j]);
598  }
599  }
600  }
601 
603  void toUpperCase() {
604  if (chars != nullptr) {
605  for (int j = 0; j < len; j++) {
606  chars[j] = toupper(chars[j]);
607  }
608  }
609  }
610 
612  static const char* toBinary(void const* const ptr, size_t const size) {
613  static char result[160];
614  unsigned char* b = (unsigned char*)ptr;
615  unsigned char byte;
616  int i, j, idx = 0;
617 
618  for (i = size - 1; i >= 0; i--) {
619  for (j = 7; j >= 0; j--) {
620  byte = (b[i] >> j) & 1;
621  result[idx++] = byte ? '1' : '0';
622  }
623  }
624  result[idx] = 0;
625  return result;
626  }
627 
628  bool containsNumber() {
629  for (int j = 0; j < len; j++) {
630  if (isdigit(chars[j])) {
631  return true;
632  }
633  }
634  return false;
635  }
636 
638  bool isInteger() {
639  bool result = containsNumber();
640  int minus_count = 0;
641  for (int j = 0; j < len; j++) {
642  char c = chars[j];
643  if (!isdigit(c)) {
644  switch (c) {
645  case '-':
646  minus_count++;
647  if (minus_count > 1) {
648  result = false;
649  }
650  break;
651  default:
652  result = false;
653  break;
654  }
655  }
656  }
657  return result;
658  }
659 
662  int result = 0;
663  int pos = indexOf(".");
664  if (pos >= 0) {
665  for (int j = pos + 1; j < len; j++) {
666  if (isdigit(chars[j])) {
667  pos++;
668  } else {
669  break;
670  }
671  }
672  }
673  return result;
674  }
675 
676  // Returns true if the string is a number
677  bool isNumber() {
678  bool result = containsNumber();
679  int dot_count = 0;
680  int minus_count = 0;
681  for (int j = 0; j < len; j++) {
682  char c = chars[j];
683  if (!isdigit(c)) {
684  switch (c) {
685  case '-':
686  minus_count++;
687  if (minus_count > 1) {
688  result = false;
689  }
690  break;
691  case '.':
692  dot_count++;
693  if (dot_count > 1) {
694  result = false;
695  }
696  break;
697  default:
698  result = false;
699  break;
700  }
701  }
702  }
703  return result;
704  }
705 
706  protected:
707  char* chars = nullptr;
708  bool is_const = false;
709  int len = 0;
710  int maxlen = 0;
711  int savedLen = -1;
712  char savedChar;
713 
715  virtual bool grow(int newMaxLen) { return false; }
716 
717  static char* itoa(int n, char s[]) {
718  int i, sign;
719  if ((sign = n) < 0) /* record sign */
720  n = -n; /* make n positive */
721  i = 0;
722  do { /* generate digits in reverse order */
723  s[i++] = n % 10 + '0'; /* get next digit */
724  } while ((n /= 10) > 0); /* delete it */
725  if (sign < 0) s[i++] = '-';
726  s[i] = '\0';
727  reverse(s);
728  return s;
729  }
730 
731  static void reverse(char s[]) {
732  int i, j;
733  char c;
734 
735  for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
736  c = s[i];
737  s[i] = s[j];
738  s[j] = c;
739  }
740  }
741 
742  static char* floatToString(char* outstr, double val, int precision,
743  int widthp) {
744  char temp[16];
745  int i;
746 
748  double roundingFactor = 0.5;
749  unsigned long mult = 1;
750  for (i = 0; i < precision; i++) {
751  roundingFactor /= 10.0;
752  mult *= 10;
753  }
754 
755  temp[0] = '\0';
756  outstr[0] = '\0';
757 
758  if (val < 0.0) {
759  strcpy(outstr, "-\0");
760  val = -val;
761  }
762 
763  val += roundingFactor;
764 
765  strcat(outstr, itoa(int(val), temp)); // prints the int part
766  if (precision > 0) {
767  strcat(outstr, ".\0");
768  unsigned long frac;
769  unsigned long mult = 1;
770  int padding = precision - 1;
771  while (precision--) mult *= 10;
772 
773  if (val >= 0)
774  frac = (val - int(val)) * mult;
775  else
776  frac = (int(val) - val) * mult;
777  unsigned long frac1 = frac;
778 
779  while (frac1 /= 10) padding--;
780 
781  while (padding--) strcat(outstr, "0\0");
782 
783  strcat(outstr, itoa(frac, temp));
784  }
785 
787  if ((widthp != 0) && ((size_t)widthp >= strlen(outstr))) {
788  int J = 0;
789  J = widthp - strlen(outstr);
790 
791  for (i = 0; i < J; i++) {
792  temp[i] = ' ';
793  }
794 
795  temp[i++] = '\0';
796  strcat(temp, outstr);
797  strcpy(outstr, temp);
798  }
799 
800  return outstr;
801  }
802 
803  static int strncmp_i(const char* s1, const char* s2, int n) {
804  if (n == 0) return (0);
805  do {
806  if (tolower(*s1) != tolower(*s2++))
807  return (*(unsigned char*)s1 - *(unsigned char*)--s2);
808  if (*s1++ == 0) break;
809  } while (--n != 0);
810  return (0);
811  }
812 };
813 
814 } // namespace audio_tools
A simple wrapper to provide string functions on char*. If the underlying char* is a const we do not a...
Definition: Str.h:27
virtual bool operator!=(const Str &alt) const
checks if the indicated string is different from the current string
Definition: Str.h:360
virtual void operator=(char *str)
we can assign a char*
Definition: Str.h:313
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition: Str.h:164
virtual bool grow(int newMaxLen)
only supported in subclasses
Definition: Str.h:715
virtual void operator=(char c)
we can assign a char
Definition: Str.h:316
virtual void operator+=(const char *str)
adds a substring at the end of the string
Definition: Str.h:337
virtual bool endsWith(const char *str)
checks if the string ends with the indicated substring
Definition: Str.h:177
virtual bool equalsIgnoreCase(const char *alt) const
Compares the string ignoring the case.
Definition: Str.h:555
virtual void substring(const char *from, int start, int end)
copies a substring into the current string
Definition: Str.h:482
bool isInteger()
Returns true if the string is an integer.
Definition: Str.h:638
virtual int length()
Definition: Str.h:374
static const char * toBinary(void const *const ptr, size_t const size)
provides a binary string represntation
Definition: Str.h:612
virtual void operator=(double val)
we can assign a double
Definition: Str.h:319
virtual void set(char chars[], int maxlen, int len=0, bool isConst=false)
assigns a memory buffer
Definition: Str.h:113
virtual int maxLength()
provides the maximum length of the string
Definition: Str.h:380
virtual bool isOnHeap()
checks if the string is on the heap
Definition: Str.h:538
virtual bool startsWith(const char *str)
checks if the string starts with the indicated substring
Definition: Str.h:170
virtual bool operator==(const char *alt) const
checks if the indicated string is equal to the current string
Definition: Str.h:355
virtual void operator+=(double value)
adds a double at the end of the string
Definition: Str.h:343
virtual bool isEmpty()
checks if the string is empty
Definition: Str.h:377
virtual void add(const char c)
adds a character
Definition: Str.h:155
virtual void operator+=(int value)
adds a int at the end of the string
Definition: Str.h:340
double toDouble()
Converts the string to a double.
Definition: Str.h:584
virtual bool contains(const char *str)
checks if the string contains a substring
Definition: Str.h:281
virtual int lastIndexOf(const char *cont)
provides the position of the last occurrence of the indicated substring
Definition: Str.h:298
virtual void rtrim()
remove trailing spaces
Definition: Str.h:519
virtual bool replaceAll(const char *toReplace, const char *replaced)
Replaces all instances of toReplace with replaced.
Definition: Str.h:411
virtual void add(const char *append)
adds a string
Definition: Str.h:143
static char * floatToString(char *outstr, double val, int precision, int widthp)
Definition: Str.h:742
virtual bool operator==(const Str &alt) const
checks if the indicated string is equal to the current string
Definition: Str.h:349
virtual int count(char c, int startPos)
count number of indicated characters as position
Definition: Str.h:502
int numberOfDecimals()
Determines the number of decimals in the number string.
Definition: Str.h:661
virtual void setLength(int len, bool addZero=true)
limits the length of the string (by adding a delimiting 0)
Definition: Str.h:449
virtual void trim()
remove leading and traling spaces
Definition: Str.h:495
virtual void operator=(int value)
we can assign an int
Definition: Str.h:322
virtual void set(const char *alt)
assigs a value
Definition: Str.h:46
virtual const char * c_str()
provides the string value as const char*
Definition: Str.h:370
virtual void operator+=(const char value)
adds a character
Definition: Str.h:346
virtual void operator=(const char *str)
we can assign a const char*
Definition: Str.h:310
virtual bool replace(const char *toReplace, const char *replaced)
Replaces the first instance of toReplace with replaced.
Definition: Str.h:383
virtual void clear()
clears the string by setting the terminating 0 at the beginning
Definition: Str.h:530
long toLong()
Converts the string to an long.
Definition: Str.h:575
virtual void ltrim()
remove leading spaces
Definition: Str.h:512
virtual void set(const Str &alt)
assigs from another Str value
Definition: Str.h:65
virtual bool matches(const char *pattern)
Definition: Str.h:204
virtual void removeAll(const char *toRemove)
removes the indicated substring from the string
Definition: Str.h:433
Str(const char *chars)
Creates a Str for string constant.
Definition: Str.h:32
virtual void operator<<(int n)
shift characters to the right -> we just move the pointer
Definition: Str.h:325
virtual bool endsWithIgnoreCase(const char *str)
checks if the string ends with the indicated substring
Definition: Str.h:184
int toInt()
Converts the string to an int.
Definition: Str.h:566
virtual void substring(Str &from, int start, int end)
copies a substring into the current string
Definition: Str.h:468
virtual void add(double value, int precision=2, int withd=0)
adds a double value
Definition: Str.h:134
virtual int indexOf(const char *cont, int start=0)
Definition: Str.h:285
virtual void remove(const char *toRemove)
removes the indicated substring from the string
Definition: Str.h:420
virtual bool isConst()
checks if the string is a constant that must not be changed
Definition: Str.h:541
virtual void insert(int pos, const char *str)
inserts a substring into the string
Definition: Str.h:544
virtual int indexOf(const char c, int start=0)
Definition: Str.h:271
virtual void add(int value)
adds a int value
Definition: Str.h:125
Str(char chars[], int maxlen, int len=0)
Creates a Str with the indicated buffer.
Definition: Str.h:43
void toLowerCase()
Converts the string to lowercase letters.
Definition: Str.h:594
virtual void setLengthUndo()
undo the last setLength call
Definition: Str.h:459
void toUpperCase()
Converts the string to uppercase letters.
Definition: Str.h:603
virtual bool operator!=(const char *alt) const
checks if the indicated string is different from the current string
Definition: Str.h:365
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10