Arduino Core API Library besed on mbed platform.

Dependents:   WeeESP8266 ESP8266_moj

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WString.cpp Source File

WString.cpp

00001 /*
00002   WString.cpp - String library for Wiring & Arduino
00003   ...mostly rewritten by Paul Stoffregen...
00004   Copyright (c) 2009-10 Hernando Barragan.  All rights reserved.
00005   Copyright 2011, Paul Stoffregen, paul@pjrc.com
00006 
00007   This library is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU Lesser General Public
00009   License as published by the Free Software Foundation; either
00010   version 2.1 of the License, or (at your option) any later version.
00011 
00012   This library is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   Lesser General Public License for more details.
00016 
00017   You should have received a copy of the GNU Lesser General Public
00018   License along with this library; if not, write to the Free Software
00019   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 
00022 #include "WString.h"
00023 
00024 
00025 /*********************************************/
00026 /*  Constructors                             */
00027 /*********************************************/
00028 
00029 String::String(const char *cstr)
00030 {
00031     init();
00032     if (cstr) copy(cstr, strlen(cstr));
00033 }
00034 
00035 String::String(const String &value)
00036 {
00037     init();
00038     *this = value;
00039 }
00040 
00041 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00042 String::String(String &&rval)
00043 {
00044     init();
00045     move(rval);
00046 }
00047 String::String(StringSumHelper &&rval)
00048 {
00049     init();
00050     move(rval);
00051 }
00052 #endif
00053 
00054 String::String(char c)
00055 {
00056     init();
00057     char buf[2];
00058     buf[0] = c;
00059     buf[1] = 0;
00060     *this = buf;
00061 }
00062 
00063 String::String(unsigned char value, unsigned char base)
00064 {
00065     init();
00066     char buf[9];
00067     utoa(value, buf, base);
00068     *this = buf;
00069 }
00070 
00071 String::String(int value, unsigned char base)
00072 {
00073     init();
00074     char buf[18];
00075     itoa(value, buf, base);
00076     *this = buf;
00077 }
00078 
00079 String::String(unsigned int value, unsigned char base)
00080 {
00081     init();
00082     char buf[17];
00083     utoa(value, buf, base);
00084     *this = buf;
00085 }
00086 
00087 String::String(long value, unsigned char base)
00088 {
00089     init();
00090     char buf[34];
00091     ltoa(value, buf, base);
00092     *this = buf;
00093 }
00094 
00095 String::String(unsigned long value, unsigned char base)
00096 {
00097     init();
00098     char buf[33];
00099     ultoa(value, buf, base);
00100     *this = buf;
00101 }
00102 
00103 String::~String()
00104 {
00105     free(buffer);
00106 }
00107 
00108 /*********************************************/
00109 /*  Memory Management                        */
00110 /*********************************************/
00111 
00112 inline void String::init(void)
00113 {
00114     buffer = NULL;
00115     capacity = 0;
00116     len = 0;
00117     flags = 0;
00118 }
00119 
00120 void String::invalidate(void)
00121 {
00122     if (buffer) free(buffer);
00123     buffer = NULL;
00124     capacity = len = 0;
00125 }
00126 
00127 unsigned char String::reserve(unsigned int size)
00128 {
00129     if (buffer && capacity >= size) return 1;
00130     if (changeBuffer(size)) {
00131         if (len == 0) buffer[0] = 0;
00132         return 1;
00133     }
00134     return 0;
00135 }
00136 
00137 unsigned char String::changeBuffer(unsigned int maxStrLen)
00138 {
00139     char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
00140     if (newbuffer) {
00141         buffer = newbuffer;
00142         capacity = maxStrLen;
00143         return 1;
00144     }
00145     return 0;
00146 }
00147 
00148 /*********************************************/
00149 /*  Copy and Move                            */
00150 /*********************************************/
00151 
00152 String & String::copy(const char *cstr, unsigned int length)
00153 {
00154     if (!reserve(length)) {
00155         invalidate();
00156         return *this;
00157     }
00158     len = length;
00159     strcpy(buffer, cstr);
00160     return *this;
00161 }
00162 
00163 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00164 void String::move(String &rhs)
00165 {
00166     if (buffer) {
00167         if (capacity >= rhs.len) {
00168             strcpy(buffer, rhs.buffer);
00169             len = rhs.len;
00170             rhs.len = 0;
00171             return;
00172         } else {
00173             free(buffer);
00174         }
00175     }
00176     buffer = rhs.buffer;
00177     capacity = rhs.capacity;
00178     len = rhs.len;
00179     rhs.buffer = NULL;
00180     rhs.capacity = 0;
00181     rhs.len = 0;
00182 }
00183 #endif
00184 
00185 String & String::operator = (const String &rhs)
00186 {
00187     if (this == &rhs) return *this;
00188     
00189     if (rhs.buffer) copy(rhs.buffer, rhs.len);
00190     else invalidate();
00191     
00192     return *this;
00193 }
00194 
00195 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00196 String & String::operator = (String &&rval)
00197 {
00198     if (this != &rval) move(rval);
00199     return *this;
00200 }
00201 
00202 String & String::operator = (StringSumHelper &&rval)
00203 {
00204     if (this != &rval) move(rval);
00205     return *this;
00206 }
00207 #endif
00208 
00209 String & String::operator = (const char *cstr)
00210 {
00211     if (cstr) copy(cstr, strlen(cstr));
00212     else invalidate();
00213     
00214     return *this;
00215 }
00216 
00217 /*********************************************/
00218 /*  concat                                   */
00219 /*********************************************/
00220 
00221 unsigned char String::concat(const String &s)
00222 {
00223     return concat(s.buffer, s.len);
00224 }
00225 
00226 unsigned char String::concat(const char *cstr, unsigned int length)
00227 {
00228     unsigned int newlen = len + length;
00229     if (!cstr) return 0;
00230     if (length == 0) return 1;
00231     if (!reserve(newlen)) return 0;
00232     strcpy(buffer + len, cstr);
00233     len = newlen;
00234     return 1;
00235 }
00236 
00237 unsigned char String::concat(const char *cstr)
00238 {
00239     if (!cstr) return 0;
00240     return concat(cstr, strlen(cstr));
00241 }
00242 
00243 unsigned char String::concat(char c)
00244 {
00245     char buf[2];
00246     buf[0] = c;
00247     buf[1] = 0;
00248     return concat(buf, 1);
00249 }
00250 
00251 unsigned char String::concat(unsigned char num)
00252 {
00253     char buf[4];
00254     itoa(num, buf, 10);
00255     return concat(buf, strlen(buf));
00256 }
00257 
00258 unsigned char String::concat(int num)
00259 {
00260     char buf[7];
00261     itoa(num, buf, 10);
00262     return concat(buf, strlen(buf));
00263 }
00264 
00265 unsigned char String::concat(unsigned int num)
00266 {
00267     char buf[6];
00268     utoa(num, buf, 10);
00269     return concat(buf, strlen(buf));
00270 }
00271 
00272 unsigned char String::concat(long num)
00273 {
00274     char buf[12];
00275     ltoa(num, buf, 10);
00276     return concat(buf, strlen(buf));
00277 }
00278 
00279 unsigned char String::concat(unsigned long num)
00280 {
00281     char buf[11];
00282     ultoa(num, buf, 10);
00283     return concat(buf, strlen(buf));
00284 }
00285 
00286 /*********************************************/
00287 /*  Concatenate                              */
00288 /*********************************************/
00289 
00290 StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
00291 {
00292     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00293     if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
00294     return a;
00295 }
00296 
00297 StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
00298 {
00299     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00300     if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
00301     return a;
00302 }
00303 
00304 StringSumHelper & operator + (const StringSumHelper &lhs, char c)
00305 {
00306     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00307     if (!a.concat(c)) a.invalidate();
00308     return a;
00309 }
00310 
00311 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
00312 {
00313     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00314     if (!a.concat(num)) a.invalidate();
00315     return a;
00316 }
00317 
00318 StringSumHelper & operator + (const StringSumHelper &lhs, int num)
00319 {
00320     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00321     if (!a.concat(num)) a.invalidate();
00322     return a;
00323 }
00324 
00325 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
00326 {
00327     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00328     if (!a.concat(num)) a.invalidate();
00329     return a;
00330 }
00331 
00332 StringSumHelper & operator + (const StringSumHelper &lhs, long num)
00333 {
00334     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00335     if (!a.concat(num)) a.invalidate();
00336     return a;
00337 }
00338 
00339 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
00340 {
00341     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00342     if (!a.concat(num)) a.invalidate();
00343     return a;
00344 }
00345 
00346 /*********************************************/
00347 /*  Comparison                               */
00348 /*********************************************/
00349 
00350 int String::compareTo(const String &s) const
00351 {
00352     if (!buffer || !s.buffer) {
00353         if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
00354         if (buffer && len > 0) return *(unsigned char *)buffer;
00355         return 0;
00356     }
00357     return strcmp(buffer, s.buffer);
00358 }
00359 
00360 unsigned char String::equals(const String &s2) const
00361 {
00362     return (len == s2.len && compareTo(s2) == 0);
00363 }
00364 
00365 unsigned char String::equals(const char *cstr) const
00366 {
00367     if (len == 0) return (cstr == NULL || *cstr == 0);
00368     if (cstr == NULL) return buffer[0] == 0;
00369     return strcmp(buffer, cstr) == 0;
00370 }
00371 
00372 unsigned char String::operator<(const String &rhs) const
00373 {
00374     return compareTo(rhs) < 0;
00375 }
00376 
00377 unsigned char String::operator>(const String &rhs) const
00378 {
00379     return compareTo(rhs) > 0;
00380 }
00381 
00382 unsigned char String::operator<=(const String &rhs) const
00383 {
00384     return compareTo(rhs) <= 0;
00385 }
00386 
00387 unsigned char String::operator>=(const String &rhs) const
00388 {
00389     return compareTo(rhs) >= 0;
00390 }
00391 
00392 unsigned char String::equalsIgnoreCase( const String &s2 ) const
00393 {
00394     if (this == &s2) return 1;
00395     if (len != s2.len) return 0;
00396     if (len == 0) return 1;
00397     const char *p1 = buffer;
00398     const char *p2 = s2.buffer;
00399     while (*p1) {
00400         if (tolower(*p1++) != tolower(*p2++)) return 0;
00401     } 
00402     return 1;
00403 }
00404 
00405 unsigned char String::startsWith( const String &s2 ) const
00406 {
00407     if (len < s2.len) return 0;
00408     return startsWith(s2, 0);
00409 }
00410 
00411 unsigned char String::startsWith( const String &s2, unsigned int offset ) const
00412 {
00413     if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
00414     return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
00415 }
00416 
00417 unsigned char String::endsWith( const String &s2 ) const
00418 {
00419     if ( len < s2.len || !buffer || !s2.buffer) return 0;
00420     return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
00421 }
00422 
00423 /*********************************************/
00424 /*  Character Access                         */
00425 /*********************************************/
00426 
00427 char String::charAt(unsigned int loc) const
00428 {
00429     return operator[](loc);
00430 }
00431 
00432 void String::setCharAt(unsigned int loc, char c) 
00433 {
00434     if (loc < len) buffer[loc] = c;
00435 }
00436 
00437 char & String::operator[](unsigned int index)
00438 {
00439     static char dummy_writable_char;
00440     if (index >= len || !buffer) {
00441         dummy_writable_char = 0;
00442         return dummy_writable_char;
00443     }
00444     return buffer[index];
00445 }
00446 
00447 char String::operator[]( unsigned int index ) const
00448 {
00449     if (index >= len || !buffer) return 0;
00450     return buffer[index];
00451 }
00452 
00453 void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
00454 {
00455     if (!bufsize || !buf) return;
00456     if (index >= len) {
00457         buf[0] = 0;
00458         return;
00459     }
00460     unsigned int n = bufsize - 1;
00461     if (n > len - index) n = len - index;
00462     strncpy((char *)buf, buffer + index, n);
00463     buf[n] = 0;
00464 }
00465 
00466 /*********************************************/
00467 /*  Search                                   */
00468 /*********************************************/
00469 
00470 int String::indexOf(char c) const
00471 {
00472     return indexOf(c, 0);
00473 }
00474 
00475 int String::indexOf( char ch, unsigned int fromIndex ) const
00476 {
00477     if (fromIndex >= len) return -1;
00478     const char* temp = strchr(buffer + fromIndex, ch);
00479     if (temp == NULL) return -1;
00480     return temp - buffer;
00481 }
00482 
00483 int String::indexOf(const String &s2) const
00484 {
00485     return indexOf(s2, 0);
00486 }
00487 
00488 int String::indexOf(const String &s2, unsigned int fromIndex) const
00489 {
00490     if (fromIndex >= len) return -1;
00491     const char *found = strstr(buffer + fromIndex, s2.buffer);
00492     if (found == NULL) return -1;
00493     return found - buffer;
00494 }
00495 
00496 int String::lastIndexOf( char theChar ) const
00497 {
00498     return lastIndexOf(theChar, len - 1);
00499 }
00500 
00501 int String::lastIndexOf(char ch, unsigned int fromIndex) const
00502 {
00503     if (fromIndex >= len) return -1;
00504     char tempchar = buffer[fromIndex + 1];
00505     buffer[fromIndex + 1] = '\0';
00506     char* temp = strrchr( buffer, ch );
00507     buffer[fromIndex + 1] = tempchar;
00508     if (temp == NULL) return -1;
00509     return temp - buffer;
00510 }
00511 
00512 int String::lastIndexOf(const String &s2) const
00513 {
00514     return lastIndexOf(s2, len - s2.len);
00515 }
00516 
00517 int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
00518 {
00519     if (s2.len == 0 || len == 0 || s2.len > len) return -1;
00520     if (fromIndex >= len) fromIndex = len - 1;
00521     int found = -1;
00522     for (char *p = buffer; p <= buffer + fromIndex; p++) {
00523         p = strstr(p, s2.buffer);
00524         if (!p) break;
00525         if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
00526     }
00527     return found;
00528 }
00529 
00530 String String::substring( unsigned int left ) const
00531 {
00532     return substring(left, len);
00533 }
00534 
00535 String String::substring(unsigned int left, unsigned int right) const
00536 {
00537     if (left > right) {
00538         unsigned int temp = right;
00539         right = left;
00540         left = temp;
00541     }
00542     String out;
00543     if (left > len) return out;
00544     if (right > len) right = len;
00545     char temp = buffer[right];  // save the replaced character
00546     buffer[right] = '\0';   
00547     out = buffer + left;  // pointer arithmetic
00548     buffer[right] = temp;  //restore character
00549     return out;
00550 }
00551 
00552 /*********************************************/
00553 /*  Modification                             */
00554 /*********************************************/
00555 
00556 void String::replace(char find, char replace)
00557 {
00558     if (!buffer) return;
00559     for (char *p = buffer; *p; p++) {
00560         if (*p == find) *p = replace;
00561     }
00562 }
00563 
00564 void String::replace(const String& find, const String& replace)
00565 {
00566     if (len == 0 || find.len == 0) return;
00567     int diff = replace.len - find.len;
00568     char *readFrom = buffer;
00569     char *foundAt;
00570     if (diff == 0) {
00571         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00572             memcpy(foundAt, replace.buffer, replace.len);
00573             readFrom = foundAt + replace.len;
00574         }
00575     } else if (diff < 0) {
00576         char *writeTo = buffer;
00577         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00578             unsigned int n = foundAt - readFrom;
00579             memcpy(writeTo, readFrom, n);
00580             writeTo += n;
00581             memcpy(writeTo, replace.buffer, replace.len);
00582             writeTo += replace.len;
00583             readFrom = foundAt + find.len;
00584             len += diff;
00585         }
00586         strcpy(writeTo, readFrom);
00587     } else {
00588         unsigned int size = len; // compute size needed for result
00589         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00590             readFrom = foundAt + find.len;
00591             size += diff;
00592         }
00593         if (size == len) return;
00594         if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
00595         int index = len - 1;
00596         while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
00597             readFrom = buffer + index + find.len;
00598             memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
00599             len += diff;
00600             buffer[len] = 0;
00601             memcpy(buffer + index, replace.buffer, replace.len);
00602             index--;
00603         }
00604     }
00605 }
00606 
00607 void String::toLowerCase(void)
00608 {
00609     if (!buffer) return;
00610     for (char *p = buffer; *p; p++) {
00611         *p = tolower(*p);
00612     }
00613 }
00614 
00615 void String::toUpperCase(void)
00616 {
00617     if (!buffer) return;
00618     for (char *p = buffer; *p; p++) {
00619         *p = toupper(*p);
00620     }
00621 }
00622 
00623 void String::trim(void)
00624 {
00625     if (!buffer || len == 0) return;
00626     char *begin = buffer;
00627     while (isspace(*begin)) begin++;
00628     char *end = buffer + len - 1;
00629     while (isspace(*end) && end >= begin) end--;
00630     len = end + 1 - begin;
00631     if (begin > buffer) memcpy(buffer, begin, len);
00632     buffer[len] = 0;
00633 }
00634 
00635 /*********************************************/
00636 /*  Parsing / Conversion                     */
00637 /*********************************************/
00638 
00639 long String::toInt(void) const
00640 {
00641     if (buffer) return atol(buffer);
00642     return 0;
00643 }
00644