@@ -150,11 +150,8 @@ void String::invalidate(void) {
150150bool String::reserve (unsigned int size) {
151151 if (buffer () && capacity () >= size)
152152 return true ;
153- if (changeBuffer (size)) {
154- if (len () == 0 )
155- wbuffer ()[0 ] = 0 ;
153+ if (changeBuffer (size))
156154 return true ;
157- }
158155 return false ;
159156}
160157
@@ -163,17 +160,17 @@ bool String::changeBuffer(unsigned int maxStrLen) {
163160 if (maxStrLen < sizeof (sso.buff ) - 1 ) {
164161 if (isSSO () || !buffer ()) {
165162 // Already using SSO, nothing to do
166- uint16_t oldLen = len ();
163+ unsigned int oldLen = len ();
167164 setSSO (true );
168165 setLen (oldLen);
169166 } else { // if bufptr && !isSSO()
170167 // Using bufptr, need to shrink into sso.buff
171168 const char *temp = buffer ();
172- uint16_t oldLen = len ();
169+ unsigned int oldLen = len ();
173170 setSSO (true );
174- setLen (oldLen);
175171 memcpy (wbuffer (), temp, maxStrLen);
176172 free ((void *)temp);
173+ setLen (oldLen);
177174 }
178175 return true ;
179176 }
@@ -191,7 +188,7 @@ bool String::changeBuffer(unsigned int maxStrLen) {
191188 if (newSize > CAPACITY_MAX) {
192189 return false ;
193190 }
194- uint16_t oldLen = len ();
191+ unsigned int oldLen = len ();
195192 char *newbuffer = (char *)realloc (isSSO () ? nullptr : wbuffer (), newSize);
196193 if (newbuffer) {
197194 size_t oldSize = capacity () + 1 ; // include NULL.
@@ -220,8 +217,8 @@ String &String::copy(const char *cstr, unsigned int length) {
220217 invalidate ();
221218 return *this ;
222219 }
220+ memmove_P (wbuffer (), cstr, length);
223221 setLen (length);
224- memmove_P (wbuffer (), cstr, length + 1 );
225222 return *this ;
226223}
227224
@@ -230,8 +227,8 @@ String &String::copy(const __FlashStringHelper *pstr, unsigned int length) {
230227 invalidate ();
231228 return *this ;
232229 }
230+ memcpy_P (wbuffer (), (PGM_P)pstr, length); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
233231 setLen (length);
234- memcpy_P (wbuffer (), (PGM_P)pstr, length + 1 ); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
235232 return *this ;
236233}
237234
@@ -282,15 +279,15 @@ bool String::concat(const String &s) {
282279 // realloc'ing the buffer and moving s.buffer in the method called
283280 if (&s == this ) {
284281 unsigned int newlen = 2 * len ();
285- if (!s. buffer ())
282+ if (!buffer ())
286283 return false ;
287- if (s. len () == 0 )
284+ if (len () == 0 )
288285 return true ;
289286 if (!reserve (newlen))
290287 return false ;
291- memmove_P (wbuffer () + len (), buffer (), len ());
288+ char *writeTo = wbuffer ();
289+ memmove_P (writeTo + len (), writeTo, len ());
292290 setLen (newlen);
293- wbuffer ()[newlen] = 0 ;
294291 return true ;
295292 } else {
296293 return concat (s.buffer (), s.len ());
@@ -305,9 +302,8 @@ bool String::concat(const char *cstr, unsigned int length) {
305302 return true ;
306303 if (!reserve (newlen))
307304 return false ;
308- memmove_P (wbuffer () + len (), cstr, length + 1 );
305+ memmove_P (wbuffer () + len (), cstr, length);
309306 setLen (newlen);
310- wbuffer ()[newlen] = 0 ;
311307 return true ;
312308}
313309
@@ -371,15 +367,14 @@ bool String::concat(double num) {
371367}
372368
373369bool String::concat (const __FlashStringHelper *str) {
370+ unsigned int length = strlen_P ((PGM_P)str), newlen = len () + length;
374371 if (!str)
375372 return false ;
376- int length = strlen_P ((PGM_P)str);
377373 if (length == 0 )
378374 return true ;
379- unsigned int newlen = len () + length;
380375 if (!reserve (newlen))
381376 return false ;
382- memcpy_P (wbuffer () + len (), (PGM_P)str, length + 1 );
377+ memcpy_P (wbuffer () + len (), (PGM_P)str, length);
383378 setLen (newlen);
384379 return true ;
385380}
@@ -398,12 +393,10 @@ String &String::insert(size_t position, const char *other, size_t other_length)
398393 return *this ;
399394
400395 auto left = len - position;
401- setLen (total);
402-
403396 auto *start = wbuffer () + position;
404397 memmove (start + other_length, start, left);
405398 memmove_P (start, other, other_length);
406- wbuffer ()[ total] = ' \0 ' ;
399+ setLen ( total) ;
407400
408401 return *this ;
409402}
@@ -414,8 +407,7 @@ String &String::insert(size_t position, const __FlashStringHelper *other) {
414407}
415408
416409String &String::insert (size_t position, char other) {
417- char tmp[2 ] { other, ' \0 ' };
418- return insert (position, tmp, 1 );
410+ return insert (position, &other, 1 );
419411}
420412
421413String &String::insert (size_t position, const char *other) {
@@ -565,6 +557,14 @@ bool String::startsWith(const String &s2) const {
565557 return startsWith (s2, 0 );
566558}
567559
560+ bool String::startsWith (const char *prefix) const {
561+ return this ->startsWith (String (prefix));
562+ }
563+
564+ bool String::startsWith (const __FlashStringHelper *prefix) const {
565+ return this ->startsWith (String (prefix));
566+ }
567+
568568bool String::startsWith (const String &s2, unsigned int offset) const {
569569 if (offset > (unsigned )(len () - s2.len ()) || !buffer () || !s2.buffer ())
570570 return false ;
@@ -577,6 +577,14 @@ bool String::endsWith(const String &s2) const {
577577 return strcmp (&buffer ()[len () - s2.len ()], s2.buffer ()) == 0 ;
578578}
579579
580+ bool String::endsWith (const char *suffix) const {
581+ return this ->endsWith (String (suffix));
582+ }
583+
584+ bool String::endsWith (const __FlashStringHelper *suffix) const {
585+ return this ->endsWith (String (suffix));
586+ }
587+
580588/* ********************************************/
581589/* Character Access */
582590/* ********************************************/
@@ -684,16 +692,12 @@ String String::substring(unsigned int left, unsigned int right) const {
684692 right = left;
685693 left = temp;
686694 }
687- String out;
688- if (left >= len ())
689- return out;
695+ if (left > len ())
696+ left = len ();
690697 if (right > len ())
691698 right = len ();
692- char *writeTo = wbuffer ();
693- char tempchar = writeTo[right]; // save the replaced character
694- writeTo[right] = ' \0 ' ;
695- out = writeTo + left; // pointer arithmetic
696- writeTo[right] = tempchar; // restore character
699+ String out;
700+ out.concat (buffer () + left, right - left);
697701 return out;
698702}
699703
@@ -702,41 +706,41 @@ String String::substring(unsigned int left, unsigned int right) const {
702706/* ********************************************/
703707
704708void String::replace (char find, char replace) {
705- if (!buffer ())
706- return ;
707- for (char *p = wbuffer (); *p; p++) {
708- if (*p == find)
709- *p = replace;
709+ for (auto &c : *this ) {
710+ if (c == find)
711+ c = replace;
710712 }
711713}
712714
713715void String::replace (const String &find, const String &replace) {
714- if (len () == 0 || find.len () == 0 )
716+ unsigned int find_len = find.len (), replace_len = replace.len ();
717+ const char *find_buffer = find.buffer (), *replace_buffer = replace.buffer ();
718+ if (len () == 0 || find_len == 0 )
715719 return ;
716- int diff = replace. len () - find. len () ;
720+ int diff = replace_len - find_len ;
717721 char *readFrom = wbuffer ();
718722 char *foundAt;
719723 if (diff == 0 ) {
720- while ((foundAt = strstr (readFrom, find. buffer () )) != NULL ) {
721- memmove_P (foundAt, replace. buffer (), replace. len () );
722- readFrom = foundAt + replace. len () ;
724+ while ((foundAt = strstr (readFrom, find_buffer )) != NULL ) {
725+ memmove_P (foundAt, replace_buffer, replace_len );
726+ readFrom = foundAt + replace_len ;
723727 }
724728 } else if (diff < 0 ) {
725729 char *writeTo = wbuffer ();
726- while ((foundAt = strstr (readFrom, find. buffer () )) != NULL ) {
730+ while ((foundAt = strstr (readFrom, find_buffer )) != NULL ) {
727731 unsigned int n = foundAt - readFrom;
728732 memmove_P (writeTo, readFrom, n);
729733 writeTo += n;
730- memmove_P (writeTo, replace. buffer (), replace. len () );
731- writeTo += replace. len () ;
732- readFrom = foundAt + find. len () ;
734+ memmove_P (writeTo, replace_buffer, replace_len );
735+ writeTo += replace_len ;
736+ readFrom = foundAt + find_len ;
733737 setLen (len () + diff);
734738 }
735739 memmove_P (writeTo, readFrom, strlen (readFrom) + 1 );
736740 } else {
737741 unsigned int size = len (); // compute size needed for result
738- while ((foundAt = strstr (readFrom, find. buffer () )) != NULL ) {
739- readFrom = foundAt + find. len () ;
742+ while ((foundAt = strstr (readFrom, find_buffer )) != NULL ) {
743+ readFrom = foundAt + find_len ;
740744 size += diff;
741745 }
742746 if (size == len ())
@@ -745,64 +749,75 @@ void String::replace(const String &find, const String &replace) {
745749 return ; // XXX: tell user!
746750 int index = len () - 1 ;
747751 while (index >= 0 && (index = lastIndexOf (find, index)) >= 0 ) {
748- readFrom = wbuffer () + index + find. len () ;
752+ readFrom = wbuffer () + index + find_len ;
749753 memmove_P (readFrom + diff, readFrom, len () - (readFrom - buffer ()));
750754 int newLen = len () + diff;
751- memmove_P (wbuffer () + index, replace. buffer (), replace. len () );
755+ memmove_P (wbuffer () + index, replace_buffer, replace_len );
752756 setLen (newLen);
753- wbuffer ()[newLen] = 0 ;
754757 index--;
755758 }
756759 }
757760}
758761
762+ void String::replace (const char *find, const String &replace) {
763+ this ->replace (String (find), replace);
764+ }
765+
766+ void String::replace (const __FlashStringHelper *find, const String &replace) {
767+ this ->replace (String (find), replace);
768+ }
769+
770+ void String::replace (const char *find, const char *replace) {
771+ this ->replace (String (find), String (replace));
772+ }
773+
774+ void String::replace (const __FlashStringHelper *find, const char *replace) {
775+ this ->replace (String (find), String (replace));
776+ }
777+
778+ void String::replace (const __FlashStringHelper *find, const __FlashStringHelper *replace) {
779+ this ->replace (String (find), String (replace));
780+ }
781+
759782void String::remove (unsigned int index, unsigned int count) {
760- if (index >= len ()) {
761- return ;
762- }
763- if (count <= 0 ) {
783+ if (count == 0 || index >= len ()) {
764784 return ;
765785 }
766786 if (count > len () - index) {
767787 count = len () - index;
768788 }
769- char *writeTo = wbuffer () + index;
770789 unsigned int newlen = len () - count;
790+ char *writeTo = wbuffer ();
791+ memmove_P (writeTo + index, writeTo + index + count, newlen - index);
771792 setLen (newlen);
772- memmove_P (writeTo, wbuffer () + index + count, newlen - index);
773- wbuffer ()[newlen] = 0 ;
774793}
775794
776795void String::toLowerCase (void ) {
777- if (!buffer ())
778- return ;
779- for (char *p = wbuffer (); *p; p++) {
780- *p = tolower (*p);
796+ for (auto &c : *this ) {
797+ c = tolower (c);
781798 }
782799}
783800
784801void String::toUpperCase (void ) {
785- if (!buffer ())
786- return ;
787- for (char *p = wbuffer (); *p; p++) {
788- *p = toupper (*p);
802+ for (auto &c : *this ) {
803+ c = toupper (c);
789804 }
790805}
791806
792807void String::trim (void ) {
793- if (!buffer () || len () == 0 )
808+ char *writeTo = wbuffer ();
809+ if (!writeTo || len () == 0 )
794810 return ;
795- char *begin = wbuffer () ;
811+ char *begin = writeTo ;
796812 while (isspace (*begin))
797813 begin++;
798- char *end = wbuffer () + len () - 1 ;
814+ char *end = writeTo + len () - 1 ;
799815 while (isspace (*end) && end >= begin)
800816 end--;
801817 unsigned int newlen = end + 1 - begin;
818+ if (begin > writeTo)
819+ memmove_P (writeTo, begin, newlen);
802820 setLen (newlen);
803- if (begin > buffer ())
804- memmove_P (wbuffer (), begin, newlen);
805- wbuffer ()[newlen] = 0 ;
806821}
807822
808823/* ********************************************/
0 commit comments