COSA
An Object-Oriented Platform for Arduino Programming
String.cpp
Go to the documentation of this file.
1 
23 #include "Cosa/String.hh"
24 #include <ctype.h>
25 
26 String::String(const char* cstr)
27 {
28  init();
29  if (cstr != NULL) copy(cstr, strlen(cstr));
30 }
31 
32 String::String(const String& value)
33 {
34  init();
35  *this = value;
36 }
37 
39 {
40  init();
41  *this = pstr;
42 }
43 
44 #if (ARDUINO >= 150)
45 String::String(String&& rval)
46 {
47  init();
48  move(rval);
49 }
50 
52 {
53  init();
54  move(rval);
55 }
56 #endif
57 
59 {
60  init();
61  char buf[2];
62  buf[0] = c;
63  buf[1] = 0;
64  *this = buf;
65 }
66 
67 String::String(unsigned char value, unsigned char base)
68 {
69  init();
70  char buf[1 + 8 * sizeof(unsigned char)];
71  utoa(value, buf, base);
72  *this = buf;
73 }
74 
75 String::String(int value, unsigned char base)
76 {
77  init();
78  char buf[2 + 8 * sizeof(int)];
79  itoa(value, buf, base);
80  *this = buf;
81 }
82 
83 String::String(unsigned int value, unsigned char base)
84 {
85  init();
86  char buf[1 + 8 * sizeof(unsigned int)];
87  utoa(value, buf, base);
88  *this = buf;
89 }
90 
91 String::String(long value, unsigned char base)
92 {
93  init();
94  char buf[2 + 8 * sizeof(long)];
95  ltoa(value, buf, base);
96  *this = buf;
97 }
98 
99 String::String(unsigned long value, unsigned char base)
100 {
101  init();
102  char buf[1 + 8 * sizeof(unsigned long)];
103  ultoa(value, buf, base);
104  *this = buf;
105 }
106 
107 String::String(float value, unsigned char decimalPlaces)
108 {
109  init();
110  char buf[33];
111  *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
112 }
113 
114 String::String(double value, unsigned char decimalPlaces)
115 {
116  init();
117  char buf[33];
118  *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
119 }
120 
122 {
123  if (m_buffer != NULL) free(m_buffer);
124 }
125 
126 inline void
128 {
129  m_buffer = NULL;
130  m_capacity = 0;
131  m_length = 0;
132 }
133 
134 void
136 {
137  if (m_buffer != NULL) free(m_buffer);
138  m_buffer = NULL;
139  m_capacity = 0;
140  m_length = 0;
141 }
142 
143 unsigned char
144 String::reserve(unsigned int size)
145 {
146  if ((m_buffer != NULL) && (m_capacity >= size)) return (true);
147  if (!changeBuffer(size)) return (false);
148  if (m_length == 0) m_buffer[0] = 0;
149  return (true);
150 }
151 
152 unsigned char
153 String::changeBuffer(unsigned int maxStrLen)
154 {
155  char* newbuffer = (char*) realloc(m_buffer, maxStrLen + 1);
156  if (newbuffer == NULL) return (false);
157  m_buffer = newbuffer;
158  m_capacity = maxStrLen;
159  return (true);
160 }
161 
162 String&
163 String::copy(const char* cstr, unsigned int length)
164 {
165  if (!reserve(length)) {
166  invalidate();
167  }
168  else {
169  m_length = length;
170  strcpy(m_buffer, cstr);
171  }
172  return (*this);
173 }
174 
175 String&
176 String::copy(str_P pstr, unsigned int length)
177 {
178  if (!reserve(length)) {
179  invalidate();
180  }
181  else {
182  m_length = length;
183  strcpy_P(m_buffer, (PGM_P) pstr);
184  }
185  return *this;
186 }
187 
189 {
190  if (m_buffer != NULL) {
191  if (m_capacity >= rhs.m_length) {
192  strcpy(m_buffer, rhs.m_buffer);
193  m_length = rhs.m_length;
194  rhs.m_length = 0;
195  return;
196  } else {
197  free(m_buffer);
198  }
199  }
200  m_buffer = rhs.m_buffer;
201  m_capacity = rhs.m_capacity;
202  m_length = rhs.m_length;
203  rhs.m_buffer = NULL;
204  rhs.m_capacity = 0;
205  rhs.m_length = 0;
206 }
207 
208 String&
210 {
211  if (this == &rhs) return (*this);
212  if (rhs.m_buffer != NULL)
213  copy(rhs.m_buffer, rhs.m_length);
214  else
215  invalidate();
216  return (*this);
217 }
218 
219 #if (ARDUINO >= 150)
220 String&
222 {
223  if (this != &rval) move(rval);
224  return (*this);
225 }
226 
227 String&
229 {
230  if (this != &rval) move(rval);
231  return (*this);
232 }
233 #endif
234 
235 String&
236 String::operator=(const char* cstr)
237 {
238  if (cstr != NULL) copy(cstr, strlen(cstr));
239  else invalidate();
240  return (*this);
241 }
242 
243 String&
245 {
246  if (pstr != NULL) copy(pstr, strlen_P((PGM_P) pstr));
247  else invalidate();
248  return (*this);
249 }
250 
251 unsigned char
253 {
254  return (concat(s.m_buffer, s.m_length));
255 }
256 
257 unsigned char
258 String::concat(const char* cstr, unsigned int length)
259 {
260  unsigned int newlen = m_length + length;
261  if (cstr == NULL) return (false);
262  if (length == 0) return (true);
263  if (!reserve(newlen)) return (false);
264  strcpy(m_buffer + m_length, cstr);
265  m_length = newlen;
266  return (true);
267 }
268 
269 unsigned char
270 String::concat(const char* cstr)
271 {
272  if (cstr == NULL) return (false);
273  return (concat(cstr, strlen(cstr)));
274 }
275 
276 unsigned char
278 {
279  char buf[2];
280  buf[0] = c;
281  buf[1] = 0;
282  return (concat(buf, 1));
283 }
284 
285 unsigned char
286 String::concat(unsigned char num)
287 {
288  char buf[1 + 3 * sizeof(unsigned char)];
289  itoa(num, buf, 10);
290  return (concat(buf, strlen(buf)));
291 }
292 
293 unsigned char
295 {
296  char buf[2 + 3 * sizeof(int)];
297  itoa(num, buf, 10);
298  return (concat(buf, strlen(buf)));
299 }
300 
301 unsigned char
302 String::concat(unsigned int num)
303 {
304  char buf[1 + 3 * sizeof(unsigned int)];
305  utoa(num, buf, 10);
306  return (concat(buf, strlen(buf)));
307 }
308 
309 unsigned char
310 String::concat(long num)
311 {
312  char buf[2 + 3 * sizeof(long)];
313  ltoa(num, buf, 10);
314  return (concat(buf, strlen(buf)));
315 }
316 
317 unsigned char
318 String::concat(unsigned long num)
319 {
320  char buf[1 + 3 * sizeof(unsigned long)];
321  ultoa(num, buf, 10);
322  return (concat(buf, strlen(buf)));
323 }
324 
325 unsigned char
326 String::concat(float num)
327 {
328  char buf[20];
329  char* string = dtostrf(num, 4, 2, buf);
330  return (concat(string, strlen(string)));
331 }
332 
333 unsigned char
334 String::concat(double num)
335 {
336  char buf[20];
337  char* string = dtostrf(num, 4, 2, buf);
338  return (concat(string, strlen(string)));
339 }
340 
341 unsigned char
343 {
344  if (str == NULL) return (false);
345  int length = strlen_P((const char*) str);
346  if (length == 0) return (true);
347  unsigned int newlen = m_length + length;
348  if (!reserve(newlen)) return (false);
349  strcpy_P(m_buffer + m_length, (const char*) str);
350  m_length = newlen;
351  return (true);
352 }
353 
355 operator+(const __StringSumHelper& lhs, const String& rhs)
356 {
357  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
358  if (!res.concat(rhs.m_buffer, rhs.m_length)) res.invalidate();
359  return (res);
360 }
361 
363 operator+(const __StringSumHelper& lhs, const char* cstr)
364 {
365  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
366  if ((cstr == NULL) || !res.concat(cstr, strlen(cstr))) res.invalidate();
367  return (res);
368 }
369 
371 operator+(const __StringSumHelper& lhs, char c)
372 {
373  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
374  if (!res.concat(c)) res.invalidate();
375  return (res);
376 }
377 
379 operator+(const __StringSumHelper& lhs, unsigned char num)
380 {
381  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
382  if (!res.concat(num)) res.invalidate();
383  return (res);
384 }
385 
387 operator+(const __StringSumHelper& lhs, int num)
388 {
389  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
390  if (!res.concat(num)) res.invalidate();
391  return (res);
392 }
393 
395 operator+(const __StringSumHelper& lhs, unsigned int num)
396 {
397  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
398  if (!res.concat(num)) res.invalidate();
399  return (res);
400 }
401 
403 operator+(const __StringSumHelper& lhs, long num)
404 {
405  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
406  if (!res.concat(num)) res.invalidate();
407  return (res);
408 }
409 
411 operator+(const __StringSumHelper& lhs, unsigned long num)
412 {
413  __StringSumHelper& a = const_cast<__StringSumHelper&>(lhs);
414  if (!a.concat(num)) a.invalidate();
415  return a;
416 }
417 
419 operator+(const __StringSumHelper& lhs, float num)
420 {
421  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
422  if (!res.concat(num)) res.invalidate();
423  return (res);
424 }
425 
427 operator+(const __StringSumHelper& lhs, double num)
428 {
429  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
430  if (!res.concat(num)) res.invalidate();
431  return (res);
432 }
433 
436 {
437  __StringSumHelper& res = const_cast<__StringSumHelper&>(lhs);
438  if (!res.concat(rhs)) res.invalidate();
439  return (res);
440 }
441 
442 int
443 String::compareTo(const String& s) const
444 {
445  if ((m_buffer == NULL) || (s.m_buffer == NULL)) {
446  if ((s.m_buffer != NULL) && (s.m_length > 0))
447  return (0 - *(unsigned char*) s.m_buffer);
448  if ((m_buffer != NULL) && (m_length > 0))
449  return (*(unsigned char*) m_buffer);
450  return (0);
451  }
452  return (strcmp(m_buffer, s.m_buffer));
453 }
454 
455 unsigned char
456 String::equals(const String& s2) const
457 {
458  return ((m_length == s2.m_length) && (compareTo(s2) == 0));
459 }
460 
461 unsigned char
462 String::equals(const char* cstr) const
463 {
464  if (m_length == 0)
465  return ((cstr == NULL) || (*cstr == 0));
466  if (cstr == NULL)
467  return ((m_buffer == NULL) || (m_buffer[0] == 0));
468  return (strcmp(m_buffer, cstr) == 0);
469 }
470 
471 unsigned char
472 String::operator<(const String& rhs) const
473 {
474  return (compareTo(rhs) < 0);
475 }
476 
477 unsigned char
478 String::operator>(const String& rhs) const
479 {
480  return (compareTo(rhs) > 0);
481 }
482 
483 unsigned char
484 String::operator<=(const String& rhs) const
485 {
486  return (compareTo(rhs) <= 0);
487 }
488 
489 unsigned char
490 String::operator>=(const String& rhs) const
491 {
492  return (compareTo(rhs) >= 0);
493 }
494 
495 unsigned char
497 {
498  if (this == &s2) return (true);
499  if (m_length != s2.m_length) return (false);
500  if (m_length == 0) return (true);
501  const char* p1 = m_buffer;
502  const char* p2 = s2.m_buffer;
503  while (*p1 != 0) {
504  if (tolower(*p1++) != tolower(*p2++)) return (false);
505  }
506  return (true);
507 }
508 
509 unsigned char
510 String::startsWith( const String& s2 ) const
511 {
512  if (m_length < s2.m_length) return (false);
513  return (startsWith(s2, 0));
514 }
515 
516 unsigned char
517 String::startsWith( const String& s2, unsigned int offset ) const
518 {
519  if ((offset > (m_length - s2.m_length))
520  || (m_buffer == NULL)
521  || (s2.m_buffer == NULL)) return (false);
522  return (strncmp( &m_buffer[offset], s2.m_buffer, s2.m_length) == 0);
523 }
524 
525 unsigned char
526 String::endsWith( const String& s2 ) const
527 {
528  if ((m_length < s2.m_length)
529  || (m_buffer == NULL)
530  || (s2.m_buffer == NULL)) return (false);
531  return (strcmp(&m_buffer[m_length - s2.m_length], s2.m_buffer) == 0);
532 }
533 
534 char
535 String::charAt(unsigned int loc) const
536 {
537  return (operator[](loc));
538 }
539 
540 void
541 String::setCharAt(unsigned int loc, char c)
542 {
543  if (loc < m_length) m_buffer[loc] = c;
544 }
545 
546 char&
547 String::operator[](unsigned int index)
548 {
549  static char dummy_writable_char;
550  if ((index >= m_length) || (m_buffer == NULL)) {
551  dummy_writable_char = 0;
552  return (dummy_writable_char);
553  }
554  return (m_buffer[index]);
555 }
556 
557 char
558 String::operator[]( unsigned int index ) const
559 {
560  if ((index >= m_length) || (m_buffer == NULL)) return (0);
561  return (m_buffer[index]);
562 }
563 
564 void
565 String::getBytes(unsigned char* buf, unsigned int bufsize, unsigned int index) const
566 {
567  if ((bufsize == 0) || (buf == NULL)) return;
568  if (index >= m_length) {
569  buf[0] = 0;
570  return;
571  }
572  unsigned int n = bufsize - 1;
573  if (n > (m_length - index)) n = m_length - index;
574  strncpy((char*) buf, m_buffer + index, n);
575  buf[n] = 0;
576 }
577 
578 int
579 String::indexOf(char c) const
580 {
581  return (indexOf(c, 0));
582 }
583 
584 int
585 String::indexOf(char ch, unsigned int fromIndex) const
586 {
587  if (fromIndex >= m_length) return -1;
588  const char* temp = strchr(m_buffer + fromIndex, ch);
589  if (temp == NULL) return (-1);
590  return (temp - m_buffer);
591 }
592 
593 int
594 String::indexOf(const String& s2) const
595 {
596  return (indexOf(s2, 0));
597 }
598 
599 int
600 String::indexOf(const String& s2, unsigned int fromIndex) const
601 {
602  if (fromIndex >= m_length) return (-1);
603  const char* found = strstr(m_buffer + fromIndex, s2.m_buffer);
604  if (found == NULL) return (-1);
605  return (found - m_buffer);
606 }
607 
608 int
609 String::lastIndexOf(char theChar) const
610 {
611  return (lastIndexOf(theChar, m_length - 1));
612 }
613 
614 int
615 String::lastIndexOf(char ch, unsigned int fromIndex) const
616 {
617  if (fromIndex >= m_length) return (-1);
618  char tempchar = m_buffer[fromIndex + 1];
619  m_buffer[fromIndex + 1] = '\0';
620  char* temp = strrchr( m_buffer, ch );
621  m_buffer[fromIndex + 1] = tempchar;
622  if (temp == NULL) return (-1);
623  return (temp - m_buffer);
624 }
625 
626 int
627 String::lastIndexOf(const String& s2) const
628 {
629  return (lastIndexOf(s2, m_length - s2.m_length));
630 }
631 
632 int
633 String::lastIndexOf(const String& s2, unsigned int fromIndex) const
634 {
635  if ((s2.m_length == 0)
636  || (m_length == 0)
637  || (s2.m_length > m_length)) return (-1);
638  if (fromIndex >= m_length) fromIndex = m_length - 1;
639  int found = -1;
640  for (char* p = m_buffer; p <= m_buffer + fromIndex; p++) {
641  p = strstr(p, s2.m_buffer);
642  if (p == NULL) break;
643  if ((unsigned int)(p - m_buffer) <= fromIndex) found = p - m_buffer;
644  }
645  return (found);
646 }
647 
648 String
649 String::substring(unsigned int left, unsigned int right) const
650 {
651  if (left > right) {
652  unsigned int temp = right;
653  right = left;
654  left = temp;
655  }
656  String res;
657  if (left > m_length) return (res);
658  if (right > m_length) right = m_length;
659  char temp = m_buffer[right];
660  m_buffer[right] = '\0';
661  res = m_buffer + left;
662  m_buffer[right] = temp;
663  return (res);
664 }
665 
666 void
667 String::replace(char find, char replace)
668 {
669  if (m_buffer == NULL) return;
670  for (char* p = m_buffer; *p != 0; p++) {
671  if (*p == find) *p = replace;
672  }
673 }
674 
675 void
676 String::replace(const String& find, const String& replace)
677 {
678  if ((m_length == 0) || (find.m_length == 0)) return;
679  int diff = replace.m_length - find.m_length;
680  char* readFrom = m_buffer;
681  char* foundAt;
682  if (diff == 0) {
683  while ((foundAt = strstr(readFrom, find.m_buffer)) != NULL) {
684  memcpy(foundAt, replace.m_buffer, replace.m_length);
685  readFrom = foundAt + replace.m_length;
686  }
687  } else if (diff < 0) {
688  char* writeTo = m_buffer;
689  while ((foundAt = strstr(readFrom, find.m_buffer)) != NULL) {
690  unsigned int n = foundAt - readFrom;
691  memcpy(writeTo, readFrom, n);
692  writeTo += n;
693  memcpy(writeTo, replace.m_buffer, replace.m_length);
694  writeTo += replace.m_length;
695  readFrom = foundAt + find.m_length;
696  m_length += diff;
697  }
698  strcpy(writeTo, readFrom);
699  } else {
700  unsigned int size = m_length;
701  while ((foundAt = strstr(readFrom, find.m_buffer)) != NULL) {
702  readFrom = foundAt + find.m_length;
703  size += diff;
704  }
705  if (size == m_length) return;
706  if ((size > m_capacity) && !changeBuffer(size)) return;
707  int index = m_length - 1;
708  while ((index >= 0) && ((index = lastIndexOf(find, index)) >= 0)) {
709  readFrom = m_buffer + index + find.m_length;
710  memmove(readFrom + diff, readFrom, m_length - (readFrom - m_buffer));
711  m_length += diff;
712  m_buffer[m_length] = 0;
713  memcpy(m_buffer + index, replace.m_buffer, replace.m_length);
714  index--;
715  }
716  }
717 }
718 
719 void
720 String::remove(unsigned int index){
721  if (index >= m_length) return;
722  int count = m_length - index;
723  remove(index, count);
724 }
725 
726 void
727 String::remove(unsigned int index, unsigned int count)
728 {
729  if (index >= m_length) return;
730  if (count == 0) return;
731  if (index + count > m_length) { count = m_length - index; }
732  char* writeTo = m_buffer + index;
733  m_length = m_length - count;
734  strncpy(writeTo, m_buffer + index + count,m_length - index);
735  m_buffer[m_length] = 0;
736 }
737 
738 void
740 {
741  if (m_buffer == NULL) return;
742  for (char* p = m_buffer; *p; p++) {
743  *p = tolower(*p);
744  }
745 }
746 
747 void
749 {
750  if (m_buffer == NULL) return;
751  for (char* p = m_buffer; *p; p++) {
752  *p = toupper(*p);
753  }
754 }
755 
756 void
758 {
759  if ((m_buffer == NULL) || (m_length == 0)) return;
760  char* begin = m_buffer;
761  while (isspace(*begin)) begin++;
762  char* end = m_buffer + m_length - 1;
763  while (isspace(*end) && end >= begin) end--;
764  m_length = end + 1 - begin;
765  if (begin > m_buffer) memcpy(m_buffer, begin, m_length);
766  m_buffer[m_length] = 0;
767 }
768 
769 long
770 String::toInt(void) const
771 {
772  if (m_buffer != NULL) return (atol(m_buffer));
773  return (0);
774 }
775 
776 float
777 String::toFloat(void) const
778 {
779  if (m_buffer != NULL) return (float(atof(m_buffer)));
780  return (0.0);
781 }
void init(void)
Definition: String.cpp:127
unsigned char equalsIgnoreCase(const String &s) const
Definition: String.cpp:496
char charAt(unsigned int index) const
Definition: String.cpp:535
String substring(unsigned int beginIndex, unsigned int endIndex) const
Definition: String.cpp:649
int compareTo(const String &s) const
Definition: String.cpp:443
float toFloat(void) const
Definition: String.cpp:777
int lastIndexOf(char ch) const
Definition: String.cpp:609
unsigned char equals(const String &s) const
Definition: String.cpp:456
unsigned char changeBuffer(unsigned int maxStrLen)
Definition: String.cpp:153
void toUpperCase(void)
Definition: String.cpp:748
#define NULL
Definition: Types.h:101
String & operator=(const String &rhs)
Definition: String.cpp:209
unsigned char operator>=(const String &rhs) const
Definition: String.cpp:490
long toInt(void) const
Definition: String.cpp:770
unsigned char reserve(unsigned int size)
Definition: String.cpp:144
unsigned char operator<=(const String &rhs) const
Definition: String.cpp:484
unsigned int m_capacity
the array length minus one (for the &#39;\0&#39;)
Definition: String.hh:228
char operator[](unsigned int index) const
Definition: String.cpp:558
String & copy(const char *cstr, unsigned int length)
Definition: String.cpp:163
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const
Definition: String.cpp:565
String(const char *cstr="")
Definition: String.cpp:26
Definition: String.hh:37
unsigned int length(void) const
Definition: String.hh:83
void remove(unsigned int index)
Definition: String.cpp:720
void move(String &rhs)
Definition: String.cpp:188
unsigned char operator<(const String &rhs) const
Definition: String.cpp:472
const class prog_str * str_P
Definition: Types.h:187
void invalidate(void)
Definition: String.cpp:135
void setCharAt(unsigned int index, char c)
Definition: String.cpp:541
unsigned char endsWith(const String &suffix) const
Definition: String.cpp:526
char * strcpy_P(char *s1, str_P s2)
Definition: Types.h:236
int indexOf(char ch) const
Definition: String.cpp:579
char * m_buffer
the actual char array
Definition: String.hh:227
unsigned int m_length
the String length (not counting the &#39;\0&#39;)
Definition: String.hh:229
void toLowerCase(void)
Definition: String.cpp:739
void trim(void)
Definition: String.cpp:757
unsigned char operator>(const String &rhs) const
Definition: String.cpp:478
unsigned char concat(const String &str)
Definition: String.cpp:252
void replace(char find, char replace)
Definition: String.cpp:667
size_t strlen_P(str_P s)
Definition: Types.h:254
~String(void)
Definition: String.cpp:121
friend __StringSumHelper & operator+(const __StringSumHelper &lhs, const String &rhs)
Definition: String.cpp:355
unsigned char startsWith(const String &prefix) const
Definition: String.cpp:510