Index

auto-plow / 6cafdd8

A wheelchair motor-propelled battery-powered ESP32-driven remote control snow plow.

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
630 Nov 2018 18:364a63c8cInclude Arduino core filesJoshua17500N

Blob @ auto-plow / include / arduino / WString.cpp

text/plain16989 bytesdownload raw
1/*
2 WString.cpp - String library for Wiring & Arduino
3 ...mostly rewritten by Paul Stoffregen...
4 Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
5 Copyright 2011, Paul Stoffregen, paul@pjrc.com
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#include "WString.h"
23
24/*********************************************/
25/* Constructors */
26/*********************************************/
27
28String::String(const char *cstr)
29{
30 init();
31 if (cstr) copy(cstr, strlen(cstr));
32}
33
34String::String(const String &value)
35{
36 init();
37 *this = value;
38}
39
40String::String(const __FlashStringHelper *pstr)
41{
42 init();
43 *this = pstr;
44}
45
46#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
47String::String(String &&rval)
48{
49 init();
50 move(rval);
51}
52String::String(StringSumHelper &&rval)
53{
54 init();
55 move(rval);
56}
57#endif
58
59String::String(char c)
60{
61 init();
62 char buf[2];
63 buf[0] = c;
64 buf[1] = 0;
65 *this = buf;
66}
67
68String::String(unsigned char value, unsigned char base)
69{
70 init();
71 char buf[1 + 8 * sizeof(unsigned char)];
72 utoa(value, buf, base);
73 *this = buf;
74}
75
76String::String(int value, unsigned char base)
77{
78 init();
79 char buf[2 + 8 * sizeof(int)];
80 itoa(value, buf, base);
81 *this = buf;
82}
83
84String::String(unsigned int value, unsigned char base)
85{
86 init();
87 char buf[1 + 8 * sizeof(unsigned int)];
88 utoa(value, buf, base);
89 *this = buf;
90}
91
92String::String(long value, unsigned char base)
93{
94 init();
95 char buf[2 + 8 * sizeof(long)];
96 ltoa(value, buf, base);
97 *this = buf;
98}
99
100String::String(unsigned long value, unsigned char base)
101{
102 init();
103 char buf[1 + 8 * sizeof(unsigned long)];
104 ultoa(value, buf, base);
105 *this = buf;
106}
107
108String::String(float value, unsigned char decimalPlaces)
109{
110 init();
111 char buf[33];
112 *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
113}
114
115String::String(double value, unsigned char decimalPlaces)
116{
117 init();
118 char buf[33];
119 *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
120}
121
122String::~String()
123{
124 free(buffer);
125}
126
127/*********************************************/
128/* Memory Management */
129/*********************************************/
130
131inline void String::init(void)
132{
133 buffer = NULL;
134 capacity = 0;
135 len = 0;
136}
137
138void String::invalidate(void)
139{
140 if (buffer) free(buffer);
141 buffer = NULL;
142 capacity = len = 0;
143}
144
145unsigned char String::reserve(unsigned int size)
146{
147 if (buffer && capacity >= size) return 1;
148 if (changeBuffer(size)) {
149 if (len == 0) buffer[0] = 0;
150 return 1;
151 }
152 return 0;
153}
154
155unsigned char String::changeBuffer(unsigned int maxStrLen)
156{
157 char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
158 if (newbuffer) {
159 buffer = newbuffer;
160 capacity = maxStrLen;
161 return 1;
162 }
163 return 0;
164}
165
166/*********************************************/
167/* Copy and Move */
168/*********************************************/
169
170String & String::copy(const char *cstr, unsigned int length)
171{
172 if (!reserve(length)) {
173 invalidate();
174 return *this;
175 }
176 len = length;
177 strcpy(buffer, cstr);
178 return *this;
179}
180
181String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
182{
183 if (!reserve(length)) {
184 invalidate();
185 return *this;
186 }
187 len = length;
188 strcpy_P(buffer, (PGM_P)pstr);
189 return *this;
190}
191
192#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
193void String::move(String &rhs)
194{
195 if (buffer) {
196 if (rhs && capacity >= rhs.len) {
197 strcpy(buffer, rhs.buffer);
198 len = rhs.len;
199 rhs.len = 0;
200 return;
201 } else {
202 free(buffer);
203 }
204 }
205 buffer = rhs.buffer;
206 capacity = rhs.capacity;
207 len = rhs.len;
208 rhs.buffer = NULL;
209 rhs.capacity = 0;
210 rhs.len = 0;
211}
212#endif
213
214String & String::operator = (const String &rhs)
215{
216 if (this == &rhs) return *this;
217
218 if (rhs.buffer) copy(rhs.buffer, rhs.len);
219 else invalidate();
220
221 return *this;
222}
223
224#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
225String & String::operator = (String &&rval)
226{
227 if (this != &rval) move(rval);
228 return *this;
229}
230
231String & String::operator = (StringSumHelper &&rval)
232{
233 if (this != &rval) move(rval);
234 return *this;
235}
236#endif
237
238String & String::operator = (const char *cstr)
239{
240 if (cstr) copy(cstr, strlen(cstr));
241 else invalidate();
242
243 return *this;
244}
245
246String & String::operator = (const __FlashStringHelper *pstr)
247{
248 if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
249 else invalidate();
250
251 return *this;
252}
253
254/*********************************************/
255/* concat */
256/*********************************************/
257
258unsigned char String::concat(const String &s)
259{
260 return concat(s.buffer, s.len);
261}
262
263unsigned char String::concat(const char *cstr, unsigned int length)
264{
265 unsigned int newlen = len + length;
266 if (!cstr) return 0;
267 if (length == 0) return 1;
268 if (!reserve(newlen)) return 0;
269 strcpy(buffer + len, cstr);
270 len = newlen;
271 return 1;
272}
273
274unsigned char String::concat(const char *cstr)
275{
276 if (!cstr) return 0;
277 return concat(cstr, strlen(cstr));
278}
279
280unsigned char String::concat(char c)
281{
282 char buf[2];
283 buf[0] = c;
284 buf[1] = 0;
285 return concat(buf, 1);
286}
287
288unsigned char String::concat(unsigned char num)
289{
290 char buf[1 + 3 * sizeof(unsigned char)];
291 itoa(num, buf, 10);
292 return concat(buf, strlen(buf));
293}
294
295unsigned char String::concat(int num)
296{
297 char buf[2 + 3 * sizeof(int)];
298 itoa(num, buf, 10);
299 return concat(buf, strlen(buf));
300}
301
302unsigned char 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
309unsigned char String::concat(long num)
310{
311 char buf[2 + 3 * sizeof(long)];
312 ltoa(num, buf, 10);
313 return concat(buf, strlen(buf));
314}
315
316unsigned char String::concat(unsigned long num)
317{
318 char buf[1 + 3 * sizeof(unsigned long)];
319 ultoa(num, buf, 10);
320 return concat(buf, strlen(buf));
321}
322
323unsigned char String::concat(float num)
324{
325 char buf[20];
326 char* string = dtostrf(num, 4, 2, buf);
327 return concat(string, strlen(string));
328}
329
330unsigned char String::concat(double num)
331{
332 char buf[20];
333 char* string = dtostrf(num, 4, 2, buf);
334 return concat(string, strlen(string));
335}
336
337unsigned char String::concat(const __FlashStringHelper * str)
338{
339 if (!str) return 0;
340 int length = strlen_P((const char *) str);
341 if (length == 0) return 1;
342 unsigned int newlen = len + length;
343 if (!reserve(newlen)) return 0;
344 strcpy_P(buffer + len, (const char *) str);
345 len = newlen;
346 return 1;
347}
348
349/*********************************************/
350/* Concatenate */
351/*********************************************/
352
353StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
354{
355 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
356 if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
357 return a;
358}
359
360StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
361{
362 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
363 if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
364 return a;
365}
366
367StringSumHelper & operator + (const StringSumHelper &lhs, char c)
368{
369 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
370 if (!a.concat(c)) a.invalidate();
371 return a;
372}
373
374StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
375{
376 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
377 if (!a.concat(num)) a.invalidate();
378 return a;
379}
380
381StringSumHelper & operator + (const StringSumHelper &lhs, int num)
382{
383 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
384 if (!a.concat(num)) a.invalidate();
385 return a;
386}
387
388StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
389{
390 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
391 if (!a.concat(num)) a.invalidate();
392 return a;
393}
394
395StringSumHelper & operator + (const StringSumHelper &lhs, long num)
396{
397 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
398 if (!a.concat(num)) a.invalidate();
399 return a;
400}
401
402StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
403{
404 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
405 if (!a.concat(num)) a.invalidate();
406 return a;
407}
408
409StringSumHelper & operator + (const StringSumHelper &lhs, float num)
410{
411 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
412 if (!a.concat(num)) a.invalidate();
413 return a;
414}
415
416StringSumHelper & operator + (const StringSumHelper &lhs, double num)
417{
418 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
419 if (!a.concat(num)) a.invalidate();
420 return a;
421}
422
423StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
424{
425 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
426 if (!a.concat(rhs)) a.invalidate();
427 return a;
428}
429
430/*********************************************/
431/* Comparison */
432/*********************************************/
433
434int String::compareTo(const String &s) const
435{
436 if (!buffer || !s.buffer) {
437 if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
438 if (buffer && len > 0) return *(unsigned char *)buffer;
439 return 0;
440 }
441 return strcmp(buffer, s.buffer);
442}
443
444unsigned char String::equals(const String &s2) const
445{
446 return (len == s2.len && compareTo(s2) == 0);
447}
448
449unsigned char String::equals(const char *cstr) const
450{
451 if (len == 0) return (cstr == NULL || *cstr == 0);
452 if (cstr == NULL) return buffer[0] == 0;
453 return strcmp(buffer, cstr) == 0;
454}
455
456unsigned char String::operator<(const String &rhs) const
457{
458 return compareTo(rhs) < 0;
459}
460
461unsigned char String::operator>(const String &rhs) const
462{
463 return compareTo(rhs) > 0;
464}
465
466unsigned char String::operator<=(const String &rhs) const
467{
468 return compareTo(rhs) <= 0;
469}
470
471unsigned char String::operator>=(const String &rhs) const
472{
473 return compareTo(rhs) >= 0;
474}
475
476unsigned char String::equalsIgnoreCase( const String &s2 ) const
477{
478 if (this == &s2) return 1;
479 if (len != s2.len) return 0;
480 if (len == 0) return 1;
481 const char *p1 = buffer;
482 const char *p2 = s2.buffer;
483 while (*p1) {
484 if (tolower(*p1++) != tolower(*p2++)) return 0;
485 }
486 return 1;
487}
488
489unsigned char String::startsWith( const String &s2 ) const
490{
491 if (len < s2.len) return 0;
492 return startsWith(s2, 0);
493}
494
495unsigned char String::startsWith( const String &s2, unsigned int offset ) const
496{
497 if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
498 return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
499}
500
501unsigned char String::endsWith( const String &s2 ) const
502{
503 if ( len < s2.len || !buffer || !s2.buffer) return 0;
504 return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
505}
506
507/*********************************************/
508/* Character Access */
509/*********************************************/
510
511char String::charAt(unsigned int loc) const
512{
513 return operator[](loc);
514}
515
516void String::setCharAt(unsigned int loc, char c)
517{
518 if (loc < len) buffer[loc] = c;
519}
520
521char & String::operator[](unsigned int index)
522{
523 static char dummy_writable_char;
524 if (index >= len || !buffer) {
525 dummy_writable_char = 0;
526 return dummy_writable_char;
527 }
528 return buffer[index];
529}
530
531char String::operator[]( unsigned int index ) const
532{
533 if (index >= len || !buffer) return 0;
534 return buffer[index];
535}
536
537void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
538{
539 if (!bufsize || !buf) return;
540 if (index >= len) {
541 buf[0] = 0;
542 return;
543 }
544 unsigned int n = bufsize - 1;
545 if (n > len - index) n = len - index;
546 strncpy((char *)buf, buffer + index, n);
547 buf[n] = 0;
548}
549
550/*********************************************/
551/* Search */
552/*********************************************/
553
554int String::indexOf(char c) const
555{
556 return indexOf(c, 0);
557}
558
559int String::indexOf( char ch, unsigned int fromIndex ) const
560{
561 if (fromIndex >= len) return -1;
562 const char* temp = strchr(buffer + fromIndex, ch);
563 if (temp == NULL) return -1;
564 return temp - buffer;
565}
566
567int String::indexOf(const String &s2) const
568{
569 return indexOf(s2, 0);
570}
571
572int String::indexOf(const String &s2, unsigned int fromIndex) const
573{
574 if (fromIndex >= len) return -1;
575 const char *found = strstr(buffer + fromIndex, s2.buffer);
576 if (found == NULL) return -1;
577 return found - buffer;
578}
579
580int String::lastIndexOf( char theChar ) const
581{
582 return lastIndexOf(theChar, len - 1);
583}
584
585int String::lastIndexOf(char ch, unsigned int fromIndex) const
586{
587 if (fromIndex >= len) return -1;
588 char tempchar = buffer[fromIndex + 1];
589 buffer[fromIndex + 1] = '\0';
590 char* temp = strrchr( buffer, ch );
591 buffer[fromIndex + 1] = tempchar;
592 if (temp == NULL) return -1;
593 return temp - buffer;
594}
595
596int String::lastIndexOf(const String &s2) const
597{
598 return lastIndexOf(s2, len - s2.len);
599}
600
601int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
602{
603 if (s2.len == 0 || len == 0 || s2.len > len) return -1;
604 if (fromIndex >= len) fromIndex = len - 1;
605 int found = -1;
606 for (char *p = buffer; p <= buffer + fromIndex; p++) {
607 p = strstr(p, s2.buffer);
608 if (!p) break;
609 if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
610 }
611 return found;
612}
613
614String String::substring(unsigned int left, unsigned int right) const
615{
616 if (left > right) {
617 unsigned int temp = right;
618 right = left;
619 left = temp;
620 }
621 String out;
622 if (left >= len) return out;
623 if (right > len) right = len;
624 char temp = buffer[right]; // save the replaced character
625 buffer[right] = '\0';
626 out = buffer + left; // pointer arithmetic
627 buffer[right] = temp; //restore character
628 return out;
629}
630
631/*********************************************/
632/* Modification */
633/*********************************************/
634
635void String::replace(char find, char replace)
636{
637 if (!buffer) return;
638 for (char *p = buffer; *p; p++) {
639 if (*p == find) *p = replace;
640 }
641}
642
643void String::replace(const String& find, const String& replace)
644{
645 if (len == 0 || find.len == 0) return;
646 int diff = replace.len - find.len;
647 char *readFrom = buffer;
648 char *foundAt;
649 if (diff == 0) {
650 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
651 memcpy(foundAt, replace.buffer, replace.len);
652 readFrom = foundAt + replace.len;
653 }
654 } else if (diff < 0) {
655 char *writeTo = buffer;
656 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
657 unsigned int n = foundAt - readFrom;
658 memcpy(writeTo, readFrom, n);
659 writeTo += n;
660 memcpy(writeTo, replace.buffer, replace.len);
661 writeTo += replace.len;
662 readFrom = foundAt + find.len;
663 len += diff;
664 }
665 strcpy(writeTo, readFrom);
666 } else {
667 unsigned int size = len; // compute size needed for result
668 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
669 readFrom = foundAt + find.len;
670 size += diff;
671 }
672 if (size == len) return;
673 if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
674 int index = len - 1;
675 while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
676 readFrom = buffer + index + find.len;
677 memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
678 len += diff;
679 buffer[len] = 0;
680 memcpy(buffer + index, replace.buffer, replace.len);
681 index--;
682 }
683 }
684}
685
686void String::remove(unsigned int index){
687 // Pass the biggest integer as the count. The remove method
688 // below will take care of truncating it at the end of the
689 // string.
690 remove(index, (unsigned int)-1);
691}
692
693void String::remove(unsigned int index, unsigned int count){
694 if (index >= len) { return; }
695 if (count <= 0) { return; }
696 if (count > len - index) { count = len - index; }
697 char *writeTo = buffer + index;
698 len = len - count;
699 strncpy(writeTo, buffer + index + count,len - index);
700 buffer[len] = 0;
701}
702
703void String::toLowerCase(void)
704{
705 if (!buffer) return;
706 for (char *p = buffer; *p; p++) {
707 *p = tolower(*p);
708 }
709}
710
711void String::toUpperCase(void)
712{
713 if (!buffer) return;
714 for (char *p = buffer; *p; p++) {
715 *p = toupper(*p);
716 }
717}
718
719void String::trim(void)
720{
721 if (!buffer || len == 0) return;
722 char *begin = buffer;
723 while (isspace(*begin)) begin++;
724 char *end = buffer + len - 1;
725 while (isspace(*end) && end >= begin) end--;
726 len = end + 1 - begin;
727 if (begin > buffer) memcpy(buffer, begin, len);
728 buffer[len] = 0;
729}
730
731/*********************************************/
732/* Parsing / Conversion */
733/*********************************************/
734
735long String::toInt(void) const
736{
737 if (buffer) return atol(buffer);
738 return 0;
739}
740
741float String::toFloat(void) const
742{
743 return float(toDouble());
744}
745
746double String::toDouble(void) const
747{
748 if (buffer) return atof(buffer);
749 return 0;
750}
751