WString.cpp
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 /*********************************************/ 26 /* Constructors */ 27 /*********************************************/ 28 29 String::String(const char *cstr) 30 { 31 init(); 32 if (cstr) copy(cstr, strlen(cstr)); 33 } 34 35 String::String(const __FlashStringHelper *pgmstr) 36 { 37 init(); 38 *this = pgmstr; 39 } 40 41 String::String(const String &value) 42 { 43 init(); 44 *this = value; 45 } 46 47 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 48 String::String(String &&rval) 49 { 50 init(); 51 move(rval); 52 } 53 String::String(StringSumHelper &&rval) 54 { 55 init(); 56 move(rval); 57 } 58 #endif 59 60 String::String(char c) 61 { 62 init(); 63 *this = c; 64 } 65 66 String::String(unsigned char c) 67 { 68 init(); 69 *this = (char)c; 70 } 71 72 String::String(const int value, unsigned char base) 73 { 74 init(); 75 char buf[18]; 76 itoa(value, buf, base); 77 *this = buf; 78 } 79 80 String::String(unsigned int value, unsigned char base) 81 { 82 init(); 83 char buf[17]; 84 utoa(value, buf, base); 85 *this = buf; 86 } 87 88 String::String(long value, unsigned char base) 89 { 90 init(); 91 char buf[34]; 92 ltoa(value, buf, base); 93 *this = buf; 94 } 95 96 String::String(unsigned long value, unsigned char base) 97 { 98 init(); 99 char buf[33]; 100 ultoa(value, buf, base); 101 *this = buf; 102 } 103 104 String::String(float num, unsigned char digits) 105 { 106 init(); 107 char buf[40]; 108 *this = dtostrf(num, digits + 2, digits, buf); 109 } 110 111 String::String(double num, unsigned char digits) 112 { 113 init(); 114 char buf[40]; 115 *this = dtostrf(num, digits + 2, digits, buf); 116 } 117 118 String::~String() 119 { 120 free(buffer); 121 } 122 123 /*********************************************/ 124 /* Memory Management */ 125 /*********************************************/ 126 127 inline void String::init(void) 128 { 129 buffer = NULL; 130 capacity = 0; 131 len = 0; 132 flags = 0; 133 } 134 135 unsigned char String::reserve(unsigned int size) 136 { 137 if (capacity >= size) return 1; 138 if (changeBuffer(size)) { 139 if (len == 0) buffer[0] = 0; 140 return 1; 141 } 142 return 0; 143 } 144 145 unsigned char String::changeBuffer(unsigned int maxStrLen) 146 { 147 char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); 148 if (newbuffer) { 149 buffer = newbuffer; 150 capacity = maxStrLen; 151 return 1; 152 } 153 return 0; 154 } 155 156 /*********************************************/ 157 /* Copy and Move */ 158 /*********************************************/ 159 160 String & String::copy(const char *cstr, unsigned int length) 161 { 162 if (length == 0) { 163 if (buffer) buffer[0] = 0; 164 len = 0; 165 return *this; 166 } 167 if (!reserve(length)) { 168 if (buffer) { 169 free(buffer); 170 buffer = NULL; 171 } 172 len = capacity = 0; 173 return *this; 174 } 175 len = length; 176 strcpy(buffer, cstr); 177 return *this; 178 } 179 180 String & String::copy(const __FlashStringHelper *pgmstr) 181 { 182 unsigned int length = strlen_P((const char PROGMEM *)pgmstr); 183 if (!reserve(length)) { 184 if (buffer) { 185 free(buffer); 186 buffer = NULL; 187 } 188 len = capacity = 0; 189 return *this; 190 } 191 len = length; 192 strcpy_P(buffer, (const char PROGMEM *)pgmstr); 193 return *this; 194 } 195 196 void String::move(String &rhs) 197 { 198 if (buffer) { 199 if (capacity >= rhs.len) { 200 strcpy(buffer, rhs.buffer); 201 len = rhs.len; 202 rhs.len = 0; 203 return; 204 } else { 205 free(buffer); 206 } 207 } 208 buffer = rhs.buffer; 209 capacity = rhs.capacity; 210 len = rhs.len; 211 rhs.buffer = NULL; 212 rhs.capacity = 0; 213 rhs.len = 0; 214 } 215 216 String & String::operator = (const String &rhs) 217 { 218 if (this == &rhs) return *this; 219 return copy(rhs.buffer, rhs.len); 220 } 221 222 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 223 String & String::operator = (String &&rval) 224 { 225 if (this != &rval) move(rval); 226 return *this; 227 } 228 229 String & String::operator = (StringSumHelper &&rval) 230 { 231 if (this != &rval) move(rval); 232 return *this; 233 } 234 #endif 235 236 String & String::operator = (const char *cstr) 237 { 238 if (cstr) { 239 copy(cstr, strlen(cstr)); 240 } else { 241 len = 0; 242 } 243 return *this; 244 } 245 246 String & String::operator = (const __FlashStringHelper *pgmstr) 247 { 248 copy(pgmstr); 249 return *this; 250 } 251 252 String & String::operator = (char c) 253 { 254 char buf[2]; 255 buf[0] = c; 256 buf[1] = 0; 257 return copy(buf, 1); 258 } 259 260 /*********************************************/ 261 /* Append */ 262 /*********************************************/ 263 264 String & String::append(const String &s) 265 { 266 return append(s.buffer, s.len); 267 } 268 269 String & String::append(const char *cstr, unsigned int length) 270 { 271 unsigned int newlen = len + length; 272 if (length == 0 || !reserve(newlen)) return *this; 273 strcpy(buffer + len, cstr); 274 len = newlen; 275 return *this; 276 } 277 278 String & String::append(const char *cstr) 279 { 280 if (cstr) append(cstr, strlen(cstr)); 281 return *this; 282 } 283 284 String & String::append(const __FlashStringHelper *pgmstr) 285 { 286 unsigned int length = strlen_P((const char PROGMEM *)pgmstr); 287 unsigned int newlen = len + length; 288 if (length == 0 || !reserve(newlen)) return *this; 289 strcpy_P(buffer + len, (const char PROGMEM *)pgmstr); 290 len = newlen; 291 return *this; 292 } 293 294 String & String::append(char c) 295 { 296 char buf[2]; 297 buf[0] = c; 298 buf[1] = 0; 299 append(buf, 1); 300 return *this; 301 } 302 303 String & String::append(int num) 304 { 305 char buf[7]; 306 itoa(num, buf, 10); 307 append(buf, strlen(buf)); 308 return *this; 309 } 310 311 String & String::append(unsigned int num) 312 { 313 char buf[6]; 314 utoa(num, buf, 10); 315 append(buf, strlen(buf)); 316 return *this; 317 } 318 319 String & String::append(long num) 320 { 321 char buf[12]; 322 ltoa(num, buf, 10); 323 append(buf, strlen(buf)); 324 return *this; 325 } 326 327 String & String::append(unsigned long num) 328 { 329 char buf[11]; 330 ultoa(num, buf, 10); 331 append(buf, strlen(buf)); 332 return *this; 333 } 334 335 String & String::append(float num) 336 { 337 char buf[30]; 338 dtostrf(num, 4, 2, buf); 339 append(buf, strlen(buf)); 340 return *this; 341 } 342 343 /*********************************************/ 344 /* Concatenate */ 345 /*********************************************/ 346 347 StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) 348 { 349 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 350 a.append(rhs.buffer, rhs.len); 351 return a; 352 } 353 354 StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) 355 { 356 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 357 if (cstr) a.append(cstr, strlen(cstr)); 358 return a; 359 } 360 361 StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) 362 { 363 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 364 a.append(pgmstr); 365 return a; 366 } 367 368 StringSumHelper & operator + (const StringSumHelper &lhs, char c) 369 { 370 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 371 a.append(c); 372 return a; 373 } 374 375 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) 376 { 377 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 378 a.append(c); 379 return a; 380 } 381 382 StringSumHelper & operator + (const StringSumHelper &lhs, int num) 383 { 384 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 385 a.append(num); 386 return a; 387 } 388 389 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) 390 { 391 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 392 a.append(num); 393 return a; 394 } 395 396 StringSumHelper & operator + (const StringSumHelper &lhs, long num) 397 { 398 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 399 a.append(num); 400 return a; 401 } 402 403 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) 404 { 405 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 406 a.append(num); 407 return a; 408 } 409 410 StringSumHelper & operator + (const StringSumHelper &lhs, float num) 411 { 412 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 413 a.append(num); 414 return a; 415 } 416 417 StringSumHelper & operator + (const StringSumHelper &lhs, double num) 418 { 419 StringSumHelper &a = const_cast<StringSumHelper&>(lhs); 420 a.append(num); 421 return a; 422 } 423 424 /*********************************************/ 425 /* Comparison */ 426 /*********************************************/ 427 428 int String::compareTo(const String &s) const 429 { 430 if (!buffer || !s.buffer) { 431 if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; 432 if (buffer && len > 0) return *(unsigned char *)buffer; 433 return 0; 434 } 435 return strcmp(buffer, s.buffer); 436 } 437 438 unsigned char String::equals(const String &s2) const 439 { 440 return (len == s2.len && compareTo(s2) == 0); 441 } 442 443 unsigned char String::equals(const char *cstr) const 444 { 445 if (len == 0) return (cstr == NULL || *cstr == 0); 446 if (cstr == NULL) return buffer[0] == 0; 447 return strcmp(buffer, cstr) == 0; 448 } 449 450 unsigned char String::equals(const __FlashStringHelper *pgmstr) const 451 { 452 if (len == 0) return pgm_read_byte(pgmstr) == 0; 453 return strcmp_P(buffer, (const char PROGMEM *)pgmstr) == 0; 454 } 455 456 unsigned char String::operator<(const String &rhs) const 457 { 458 return compareTo(rhs) < 0; 459 } 460 461 unsigned char String::operator>(const String &rhs) const 462 { 463 return compareTo(rhs) > 0; 464 } 465 466 unsigned char String::operator<=(const String &rhs) const 467 { 468 return compareTo(rhs) <= 0; 469 } 470 471 unsigned char String::operator>=(const String &rhs) const 472 { 473 return compareTo(rhs) >= 0; 474 } 475 476 unsigned 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 489 unsigned char String::startsWith( const String &s2 ) const 490 { 491 if (len < s2.len) return 0; 492 return startsWith(s2, 0); 493 } 494 495 unsigned 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 501 unsigned 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 511 char String::charAt(unsigned int loc) const 512 { 513 return operator[](loc); 514 } 515 516 void String::setCharAt(unsigned int loc, char c) 517 { 518 if (loc < len) buffer[loc] = c; 519 } 520 521 char & 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 531 char String::operator[]( unsigned int index ) const 532 { 533 if (index >= len || !buffer) return 0; 534 return buffer[index]; 535 } 536 537 void 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 554 int String::indexOf(char c) const 555 { 556 return indexOf(c, 0); 557 } 558 559 int 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 567 int String::indexOf(const String &s2) const 568 { 569 return indexOf(s2, 0); 570 } 571 572 int 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 580 int String::lastIndexOf( char theChar ) const 581 { 582 return lastIndexOf(theChar, len - 1); 583 } 584 585 int String::lastIndexOf(char ch, unsigned int fromIndex) const 586 { 587 if (fromIndex >= len || fromIndex < 0) 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 596 int String::lastIndexOf(const String &s2) const 597 { 598 return lastIndexOf(s2, len - s2.len); 599 } 600 601 int String::lastIndexOf(const String &s2, unsigned int fromIndex) const 602 { 603 if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) 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 614 String String::substring( unsigned int left ) const 615 { 616 return substring(left, len); 617 } 618 619 String String::substring(unsigned int left, unsigned int right) const 620 { 621 if (left > right) { 622 unsigned int temp = right; 623 right = left; 624 left = temp; 625 } 626 String out; 627 if (left > len) return out; 628 if (right > len) right = len; 629 char temp = buffer[right]; // save the replaced character 630 buffer[right] = '\0'; 631 out = buffer + left; // pointer arithmetic 632 buffer[right] = temp; //restore character 633 return out; 634 } 635 636 /*********************************************/ 637 /* Modification */ 638 /*********************************************/ 639 640 String & String::replace(char find, char replace) 641 { 642 if (!buffer) return *this; 643 for (char *p = buffer; *p; p++) { 644 if (*p == find) *p = replace; 645 } 646 return *this; 647 } 648 649 String & String::replace(const String& find, const String& replace) 650 { 651 if (len == 0 || find.len == 0) return *this; 652 int diff = replace.len - find.len; 653 char *readFrom = buffer; 654 char *foundAt; 655 if (diff == 0) { 656 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { 657 memcpy(foundAt, replace.buffer, replace.len); 658 readFrom = foundAt + replace.len; 659 } 660 } else if (diff < 0) { 661 char *writeTo = buffer; 662 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { 663 unsigned int n = foundAt - readFrom; 664 memcpy(writeTo, readFrom, n); 665 writeTo += n; 666 memcpy(writeTo, replace.buffer, replace.len); 667 writeTo += replace.len; 668 readFrom = foundAt + find.len; 669 len += diff; 670 } 671 strcpy(writeTo, readFrom); 672 } else { 673 unsigned int size = len; // compute size needed for result 674 while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { 675 readFrom = foundAt + find.len; 676 size += diff; 677 } 678 if (size == len) return *this; 679 if (size > capacity && !changeBuffer(size)) return *this; 680 int index = len - 1; 681 while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { 682 readFrom = buffer + index + find.len; 683 memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); 684 len += diff; 685 buffer[len] = 0; 686 memcpy(buffer + index, replace.buffer, replace.len); 687 index--; 688 } 689 } 690 return *this; 691 } 692 693 String & String::remove(unsigned int index) 694 { 695 if (index < len) { 696 len = index; 697 buffer[len] = 0; 698 } 699 return *this; 700 } 701 702 String & String::remove(unsigned int index, unsigned int count) 703 { 704 if (index < len && count > 0) { 705 if (index + count > len) count = len - index; 706 len = len - count; 707 memmove(buffer + index, buffer + index + count, len - index); 708 buffer[len] = 0; 709 } 710 return *this; 711 } 712 713 String & String::toLowerCase(void) 714 { 715 if (!buffer) return *this; 716 for (char *p = buffer; *p; p++) { 717 *p = tolower(*p); 718 } 719 return *this; 720 } 721 722 String & String::toUpperCase(void) 723 { 724 if (!buffer) return *this; 725 for (char *p = buffer; *p; p++) { 726 *p = toupper(*p); 727 } 728 return *this; 729 } 730 731 String & String::trim(void) 732 { 733 if (!buffer || len == 0) return *this; 734 char *begin = buffer; 735 while (isspace(*begin)) begin++; 736 char *end = buffer + len - 1; 737 while (isspace(*end) && end >= begin) end--; 738 len = end + 1 - begin; 739 if (begin > buffer) memcpy(buffer, begin, len); 740 buffer[len] = 0; 741 return *this; 742 } 743 744 /*********************************************/ 745 /* Parsing / Conversion */ 746 /*********************************************/ 747 748 long String::toInt(void) const 749 { 750 if (buffer) return atol(buffer); 751 return 0; 752 } 753 754 float String::toFloat(void) const 755 { 756 if (buffer) return atof(buffer); 757 return 0.0; 758 } 759