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
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.
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.
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
25 /*********************************************/
27 /*********************************************/
29 String::String(const char *cstr)
32 if (cstr) copy(cstr, strlen(cstr));
35 String::String(const String &value)
41 #ifdef __GXX_EXPERIMENTAL_CXX0X__
42 String::String(String &&rval)
47 String::String(StringSumHelper &&rval)
54 String::String(char c)
63 String::String(unsigned char value, unsigned char base)
67 utoa(value, buf, base);
71 String::String(int value, unsigned char base)
75 itoa(value, buf, base);
79 String::String(unsigned int value, unsigned char base)
83 utoa(value, buf, base);
87 String::String(long value, unsigned char base)
91 ltoa(value, buf, base);
95 String::String(unsigned long value, unsigned char base)
99 ultoa(value, buf, base);
108 /*********************************************/
109 /* Memory Management */
110 /*********************************************/
112 inline void String::init(void)
120 void String::invalidate(void)
122 if (buffer) free(buffer);
127 unsigned char String::reserve(unsigned int size)
129 if (buffer && capacity >= size) return 1;
130 if (changeBuffer(size)) {
131 if (len == 0) buffer[0] = 0;
137 unsigned char String::changeBuffer(unsigned int maxStrLen)
139 char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
142 capacity = maxStrLen;
148 /*********************************************/
150 /*********************************************/
152 String & String::copy(const char *cstr, unsigned int length)
154 if (!reserve(length)) {
159 strcpy(buffer, cstr);
163 #ifdef __GXX_EXPERIMENTAL_CXX0X__
164 void String::move(String &rhs)
167 if (capacity >= rhs.len) {
168 strcpy(buffer, rhs.buffer);
177 capacity = rhs.capacity;
185 String & String::operator = (const String &rhs)
187 if (this == &rhs) return *this;
189 if (rhs.buffer) copy(rhs.buffer, rhs.len);
195 #ifdef __GXX_EXPERIMENTAL_CXX0X__
196 String & String::operator = (String &&rval)
198 if (this != &rval) move(rval);
202 String & String::operator = (StringSumHelper &&rval)
204 if (this != &rval) move(rval);
209 String & String::operator = (const char *cstr)
211 if (cstr) copy(cstr, strlen(cstr));
217 /*********************************************/
219 /*********************************************/
221 unsigned char String::concat(const String &s)
223 return concat(s.buffer, s.len);
226 unsigned char String::concat(const char *cstr, unsigned int length)
228 unsigned int newlen = len + length;
230 if (length == 0) return 1;
231 if (!reserve(newlen)) return 0;
232 strcpy(buffer + len, cstr);
237 unsigned char String::concat(const char *cstr)
240 return concat(cstr, strlen(cstr));
243 unsigned char String::concat(char c)
248 return concat(buf, 1);
251 unsigned char String::concat(unsigned char num)
255 return concat(buf, strlen(buf));
258 unsigned char String::concat(int num)
262 return concat(buf, strlen(buf));
265 unsigned char String::concat(unsigned int num)
269 return concat(buf, strlen(buf));
272 unsigned char String::concat(long num)
276 return concat(buf, strlen(buf));
279 unsigned char String::concat(unsigned long num)
283 return concat(buf, strlen(buf));
286 /*********************************************/
288 /*********************************************/
290 StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
292 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
293 if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
297 StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
299 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
300 if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
304 StringSumHelper & operator + (const StringSumHelper &lhs, char c)
306 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
307 if (!a.concat(c)) a.invalidate();
311 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
313 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
314 if (!a.concat(num)) a.invalidate();
318 StringSumHelper & operator + (const StringSumHelper &lhs, int num)
320 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
321 if (!a.concat(num)) a.invalidate();
325 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
327 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
328 if (!a.concat(num)) a.invalidate();
332 StringSumHelper & operator + (const StringSumHelper &lhs, long num)
334 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
335 if (!a.concat(num)) a.invalidate();
339 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
341 StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
342 if (!a.concat(num)) a.invalidate();
346 /*********************************************/
348 /*********************************************/
350 int String::compareTo(const String &s) const
352 if (!buffer || !s.buffer) {
353 if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
354 if (buffer && len > 0) return *(unsigned char *)buffer;
357 return strcmp(buffer, s.buffer);
360 unsigned char String::equals(const String &s2) const
362 return (len == s2.len && compareTo(s2) == 0);
365 unsigned char String::equals(const char *cstr) const
367 if (len == 0) return (cstr == NULL || *cstr == 0);
368 if (cstr == NULL) return buffer[0] == 0;
369 return strcmp(buffer, cstr) == 0;
372 unsigned char String::operator<(const String &rhs) const
374 return compareTo(rhs) < 0;
377 unsigned char String::operator>(const String &rhs) const
379 return compareTo(rhs) > 0;
382 unsigned char String::operator<=(const String &rhs) const
384 return compareTo(rhs) <= 0;
387 unsigned char String::operator>=(const String &rhs) const
389 return compareTo(rhs) >= 0;
392 unsigned char String::equalsIgnoreCase( const String &s2 ) const
394 if (this == &s2) return 1;
395 if (len != s2.len) return 0;
396 if (len == 0) return 1;
397 const char *p1 = buffer;
398 const char *p2 = s2.buffer;
400 if (tolower(*p1++) != tolower(*p2++)) return 0;
405 unsigned char String::startsWith( const String &s2 ) const
407 if (len < s2.len) return 0;
408 return startsWith(s2, 0);
411 unsigned char String::startsWith( const String &s2, unsigned int offset ) const
413 if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
414 return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
417 unsigned char String::endsWith( const String &s2 ) const
419 if ( len < s2.len || !buffer || !s2.buffer) return 0;
420 return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
423 /*********************************************/
424 /* Character Access */
425 /*********************************************/
427 char String::charAt(unsigned int loc) const
429 return operator[](loc);
432 void String::setCharAt(unsigned int loc, char c)
434 if (loc < len) buffer[loc] = c;
437 char & String::operator[](unsigned int index)
439 static char dummy_writable_char;
440 if (index >= len || !buffer) {
441 dummy_writable_char = 0;
442 return dummy_writable_char;
444 return buffer[index];
447 char String::operator[]( unsigned int index ) const
449 if (index >= len || !buffer) return 0;
450 return buffer[index];
453 void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
455 if (!bufsize || !buf) return;
460 unsigned int n = bufsize - 1;
461 if (n > len - index) n = len - index;
462 strncpy((char *)buf, buffer + index, n);
466 /*********************************************/
468 /*********************************************/
470 int String::indexOf(char c) const
472 return indexOf(c, 0);
475 int String::indexOf( char ch, unsigned int fromIndex ) const
477 if (fromIndex >= len) return -1;
478 const char* temp = strchr(buffer + fromIndex, ch);
479 if (temp == NULL) return -1;
480 return temp - buffer;
483 int String::indexOf(const String &s2) const
485 return indexOf(s2, 0);
488 int String::indexOf(const String &s2, unsigned int fromIndex) const
490 if (fromIndex >= len) return -1;
491 const char *found = strstr(buffer + fromIndex, s2.buffer);
492 if (found == NULL) return -1;
493 return found - buffer;
496 int String::lastIndexOf( char theChar ) const
498 return lastIndexOf(theChar, len - 1);
501 int String::lastIndexOf(char ch, unsigned int fromIndex) const
503 if (fromIndex >= len) return -1;
504 char tempchar = buffer[fromIndex + 1];
505 buffer[fromIndex + 1] = '\0';
506 char* temp = strrchr( buffer, ch );
507 buffer[fromIndex + 1] = tempchar;
508 if (temp == NULL) return -1;
509 return temp - buffer;
512 int String::lastIndexOf(const String &s2) const
514 return lastIndexOf(s2, len - s2.len);
517 int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
519 if (s2.len == 0 || len == 0 || s2.len > len) return -1;
520 if (fromIndex >= len) fromIndex = len - 1;
522 for (char *p = buffer; p <= buffer + fromIndex; p++) {
523 p = strstr(p, s2.buffer);
525 if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
530 String String::substring( unsigned int left ) const
532 return substring(left, len);
535 String String::substring(unsigned int left, unsigned int right) const
538 unsigned int temp = right;
543 if (left > len) return out;
544 if (right > len) right = len;
545 char temp = buffer[right]; // save the replaced character
546 buffer[right] = '\0';
547 out = buffer + left; // pointer arithmetic
548 buffer[right] = temp; //restore character
552 /*********************************************/
554 /*********************************************/
556 void String::replace(char find, char replace)
559 for (char *p = buffer; *p; p++) {
560 if (*p == find) *p = replace;
564 void String::replace(const String& find, const String& replace)
566 if (len == 0 || find.len == 0) return;
567 int diff = replace.len - find.len;
568 char *readFrom = buffer;
571 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
572 memcpy(foundAt, replace.buffer, replace.len);
573 readFrom = foundAt + replace.len;
575 } else if (diff < 0) {
576 char *writeTo = buffer;
577 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
578 unsigned int n = foundAt - readFrom;
579 memcpy(writeTo, readFrom, n);
581 memcpy(writeTo, replace.buffer, replace.len);
582 writeTo += replace.len;
583 readFrom = foundAt + find.len;
586 strcpy(writeTo, readFrom);
588 unsigned int size = len; // compute size needed for result
589 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
590 readFrom = foundAt + find.len;
593 if (size == len) return;
594 if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
596 while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
597 readFrom = buffer + index + find.len;
598 memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
601 memcpy(buffer + index, replace.buffer, replace.len);
607 void String::toLowerCase(void)
610 for (char *p = buffer; *p; p++) {
615 void String::toUpperCase(void)
618 for (char *p = buffer; *p; p++) {
623 void String::trim(void)
625 if (!buffer || len == 0) return;
626 char *begin = buffer;
627 while (isspace(*begin)) begin++;
628 char *end = buffer + len - 1;
629 while (isspace(*end) && end >= begin) end--;
630 len = end + 1 - begin;
631 if (begin > buffer) memcpy(buffer, begin, len);
635 /*********************************************/
636 /* Parsing / Conversion */
637 /*********************************************/
639 long String::toInt(void) const
641 if (buffer) return atol(buffer);