Armageddon - a missile commad clone by Wuuff, originally for Gamebuino. Conversion by Jonne

Dependencies:   PokittoLib

Fork of Asterocks by Pokitto Community Team

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     pokItoa(value, buf, base);
00076     //itoa(value, buf, base);
00077     *this = buf;
00078 }
00079 
00080 String::String(unsigned int value, unsigned char base)
00081 {
00082     init();
00083     char buf[17];
00084     pokItoa(value, buf, base);
00085     //utoa(value, buf, base);
00086     *this = buf;
00087 }
00088 
00089 String::String(long value, unsigned char base)
00090 {
00091     init();
00092     char buf[34];
00093     //ltoa(value, buf, base);
00094     pokLtoa(value, buf, base);
00095     *this = buf;
00096 }
00097 
00098 String::String(unsigned long value, unsigned char base)
00099 {
00100     init();
00101     char buf[33];
00102     //ultoa(value, buf, base);
00103     pokLtoa(value, buf, base);
00104     *this = buf;
00105 }
00106 
00107 String::~String()
00108 {
00109     free(buffer);
00110 }
00111 
00112 /*********************************************/
00113 /*  Memory Management                        */
00114 /*********************************************/
00115 
00116 inline void String::init(void)
00117 {
00118     buffer = NULL;
00119     capacity = 0;
00120     len = 0;
00121     flags = 0;
00122 }
00123 
00124 void String::invalidate(void)
00125 {
00126     if (buffer) free(buffer);
00127     buffer = NULL;
00128     capacity = len = 0;
00129 }
00130 
00131 unsigned char String::reserve(unsigned int size)
00132 {
00133     if (buffer && capacity >= size) return 1;
00134     if (changeBuffer(size)) {
00135         if (len == 0) buffer[0] = 0;
00136         return 1;
00137     }
00138     return 0;
00139 }
00140 
00141 unsigned char String::changeBuffer(unsigned int maxStrLen)
00142 {
00143     char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
00144     if (newbuffer) {
00145         buffer = newbuffer;
00146         capacity = maxStrLen;
00147         return 1;
00148     }
00149     return 0;
00150 }
00151 
00152 /*********************************************/
00153 /*  Copy and Move                            */
00154 /*********************************************/
00155 
00156 String & String::copy(const char *cstr, unsigned int length)
00157 {
00158     if (!reserve(length)) {
00159         invalidate();
00160         return *this;
00161     }
00162     len = length;
00163     strcpy(buffer, cstr);
00164     return *this;
00165 }
00166 
00167 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00168 void String::move(String &rhs)
00169 {
00170     if (buffer) {
00171         if (capacity >= rhs.len) {
00172             strcpy(buffer, rhs.buffer);
00173             len = rhs.len;
00174             rhs.len = 0;
00175             return;
00176         } else {
00177             free(buffer);
00178         }
00179     }
00180     buffer = rhs.buffer;
00181     capacity = rhs.capacity;
00182     len = rhs.len;
00183     rhs.buffer = NULL;
00184     rhs.capacity = 0;
00185     rhs.len = 0;
00186 }
00187 #endif
00188 
00189 String & String::operator = (const String &rhs)
00190 {
00191     if (this == &rhs) return *this;
00192 
00193     if (rhs.buffer) copy(rhs.buffer, rhs.len);
00194     else invalidate();
00195 
00196     return *this;
00197 }
00198 
00199 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00200 String & String::operator = (String &&rval)
00201 {
00202     if (this != &rval) move(rval);
00203     return *this;
00204 }
00205 
00206 String & String::operator = (StringSumHelper &&rval)
00207 {
00208     if (this != &rval) move(rval);
00209     return *this;
00210 }
00211 #endif
00212 
00213 String & String::operator = (const char *cstr)
00214 {
00215     if (cstr) copy(cstr, strlen(cstr));
00216     else invalidate();
00217 
00218     return *this;
00219 }
00220 
00221 /*********************************************/
00222 /*  concat                                   */
00223 /*********************************************/
00224 
00225 unsigned char String::concat(const String &s)
00226 {
00227     return concat(s.buffer, s.len);
00228 }
00229 
00230 unsigned char String::concat(const char *cstr, unsigned int length)
00231 {
00232     unsigned int newlen = len + length;
00233     if (!cstr) return 0;
00234     if (length == 0) return 1;
00235     if (!reserve(newlen)) return 0;
00236     strcpy(buffer + len, cstr);
00237     len = newlen;
00238     return 1;
00239 }
00240 
00241 unsigned char String::concat(const char *cstr)
00242 {
00243     if (!cstr) return 0;
00244     return concat(cstr, strlen(cstr));
00245 }
00246 
00247 unsigned char String::concat(char c)
00248 {
00249     char buf[2];
00250     buf[0] = c;
00251     buf[1] = 0;
00252     return concat(buf, 1);
00253 }
00254 
00255 unsigned char String::concat(unsigned char num)
00256 {
00257     char buf[4];
00258     //itoa(num, buf, 10);
00259     pokItoa(num, buf, 10);
00260     return concat(buf, strlen(buf));
00261 }
00262 
00263 unsigned char String::concat(int num)
00264 {
00265     char buf[7];
00266     //itoa(num, buf, 10);
00267     pokItoa(num, buf, 10);
00268     return concat(buf, strlen(buf));
00269 }
00270 
00271 unsigned char String::concat(unsigned int num)
00272 {
00273     char buf[6];
00274     utoa(num, buf, 10);
00275     return concat(buf, strlen(buf));
00276 }
00277 
00278 unsigned char String::concat(long num)
00279 {
00280     char buf[12];
00281     //ltoa(num, buf, 10);
00282     pokItoa(num, buf, 10);
00283     return concat(buf, strlen(buf));
00284 }
00285 
00286 unsigned char String::concat(unsigned long num)
00287 {
00288     char buf[11];
00289     ultoa(num, buf, 10);
00290     return concat(buf, strlen(buf));
00291 }
00292 
00293 /*********************************************/
00294 /*  Concatenate                              */
00295 /*********************************************/
00296 
00297 StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
00298 {
00299     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00300     if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
00301     return a;
00302 }
00303 
00304 StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
00305 {
00306     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00307     if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
00308     return a;
00309 }
00310 
00311 StringSumHelper & operator + (const StringSumHelper &lhs, char c)
00312 {
00313     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00314     if (!a.concat(c)) a.invalidate();
00315     return a;
00316 }
00317 
00318 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char 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, 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, unsigned int 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, long num)
00340 {
00341     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00342     if (!a.concat(num)) a.invalidate();
00343     return a;
00344 }
00345 
00346 StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
00347 {
00348     StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
00349     if (!a.concat(num)) a.invalidate();
00350     return a;
00351 }
00352 
00353 /*********************************************/
00354 /*  Comparison                               */
00355 /*********************************************/
00356 
00357 int String::compareTo(const String &s) const
00358 {
00359     if (!buffer || !s.buffer) {
00360         if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
00361         if (buffer && len > 0) return *(unsigned char *)buffer;
00362         return 0;
00363     }
00364     return strcmp(buffer, s.buffer);
00365 }
00366 
00367 unsigned char String::equals(const String &s2) const
00368 {
00369     return (len == s2.len && compareTo(s2) == 0);
00370 }
00371 
00372 unsigned char String::equals(const char *cstr) const
00373 {
00374     if (len == 0) return (cstr == NULL || *cstr == 0);
00375     if (cstr == NULL) return buffer[0] == 0;
00376     return strcmp(buffer, cstr) == 0;
00377 }
00378 
00379 unsigned char String::operator<(const String &rhs) const
00380 {
00381     return compareTo(rhs) < 0;
00382 }
00383 
00384 unsigned char String::operator>(const String &rhs) const
00385 {
00386     return compareTo(rhs) > 0;
00387 }
00388 
00389 unsigned char String::operator<=(const String &rhs) const
00390 {
00391     return compareTo(rhs) <= 0;
00392 }
00393 
00394 unsigned char String::operator>=(const String &rhs) const
00395 {
00396     return compareTo(rhs) >= 0;
00397 }
00398 
00399 unsigned char String::equalsIgnoreCase( const String &s2 ) const
00400 {
00401     if (this == &s2) return 1;
00402     if (len != s2.len) return 0;
00403     if (len == 0) return 1;
00404     const char *p1 = buffer;
00405     const char *p2 = s2.buffer;
00406     while (*p1) {
00407         if (tolower(*p1++) != tolower(*p2++)) return 0;
00408     }
00409     return 1;
00410 }
00411 
00412 unsigned char String::startsWith( const String &s2 ) const
00413 {
00414     if (len < s2.len) return 0;
00415     return startsWith(s2, 0);
00416 }
00417 
00418 unsigned char String::startsWith( const String &s2, unsigned int offset ) const
00419 {
00420     if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
00421     return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
00422 }
00423 
00424 unsigned char String::endsWith( const String &s2 ) const
00425 {
00426     if ( len < s2.len || !buffer || !s2.buffer) return 0;
00427     return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
00428 }
00429 
00430 /*********************************************/
00431 /*  Character Access                         */
00432 /*********************************************/
00433 
00434 char String::charAt(unsigned int loc) const
00435 {
00436     return operator[](loc);
00437 }
00438 
00439 void String::setCharAt(unsigned int loc, char c)
00440 {
00441     if (loc < len) buffer[loc] = c;
00442 }
00443 
00444 char & String::operator[](unsigned int index)
00445 {
00446     static char dummy_writable_char;
00447     if (index >= len || !buffer) {
00448         dummy_writable_char = 0;
00449         return dummy_writable_char;
00450     }
00451     return buffer[index];
00452 }
00453 
00454 char String::operator[]( unsigned int index ) const
00455 {
00456     if (index >= len || !buffer) return 0;
00457     return buffer[index];
00458 }
00459 
00460 void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
00461 {
00462     if (!bufsize || !buf) return;
00463     if (index >= len) {
00464         buf[0] = 0;
00465         return;
00466     }
00467     unsigned int n = bufsize - 1;
00468     if (n > len - index) n = len - index;
00469     strncpy((char *)buf, buffer + index, n);
00470     buf[n] = 0;
00471 }
00472 
00473 /*********************************************/
00474 /*  Search                                   */
00475 /*********************************************/
00476 
00477 int String::indexOf(char c) const
00478 {
00479     return indexOf(c, 0);
00480 }
00481 
00482 int String::indexOf( char ch, unsigned int fromIndex ) const
00483 {
00484     if (fromIndex >= len) return -1;
00485     const char* temp = strchr(buffer + fromIndex, ch);
00486     if (temp == NULL) return -1;
00487     return temp - buffer;
00488 }
00489 
00490 int String::indexOf(const String &s2) const
00491 {
00492     return indexOf(s2, 0);
00493 }
00494 
00495 int String::indexOf(const String &s2, unsigned int fromIndex) const
00496 {
00497     if (fromIndex >= len) return -1;
00498     const char *found = strstr(buffer + fromIndex, s2.buffer);
00499     if (found == NULL) return -1;
00500     return found - buffer;
00501 }
00502 
00503 int String::lastIndexOf( char theChar ) const
00504 {
00505     return lastIndexOf(theChar, len - 1);
00506 }
00507 
00508 int String::lastIndexOf(char ch, unsigned int fromIndex) const
00509 {
00510     if (fromIndex >= len) return -1;
00511     char tempchar = buffer[fromIndex + 1];
00512     buffer[fromIndex + 1] = '\0';
00513     char* temp = strrchr( buffer, ch );
00514     buffer[fromIndex + 1] = tempchar;
00515     if (temp == NULL) return -1;
00516     return temp - buffer;
00517 }
00518 
00519 int String::lastIndexOf(const String &s2) const
00520 {
00521     return lastIndexOf(s2, len - s2.len);
00522 }
00523 
00524 int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
00525 {
00526     if (s2.len == 0 || len == 0 || s2.len > len) return -1;
00527     if (fromIndex >= len) fromIndex = len - 1;
00528     int found = -1;
00529     for (char *p = buffer; p <= buffer + fromIndex; p++) {
00530         p = strstr(p, s2.buffer);
00531         if (!p) break;
00532         if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
00533     }
00534     return found;
00535 }
00536 
00537 String String::substring( unsigned int left ) const
00538 {
00539     return substring(left, len);
00540 }
00541 
00542 String String::substring(unsigned int left, unsigned int right) const
00543 {
00544     if (left > right) {
00545         unsigned int temp = right;
00546         right = left;
00547         left = temp;
00548     }
00549     String out;
00550     if (left > len) return out;
00551     if (right > len) right = len;
00552     char temp = buffer[right];  // save the replaced character
00553     buffer[right] = '\0';
00554     out = buffer + left;  // pointer arithmetic
00555     buffer[right] = temp;  //restore character
00556     return out;
00557 }
00558 
00559 /*********************************************/
00560 /*  Modification                             */
00561 /*********************************************/
00562 
00563 void String::replace(char find, char replace)
00564 {
00565     if (!buffer) return;
00566     for (char *p = buffer; *p; p++) {
00567         if (*p == find) *p = replace;
00568     }
00569 }
00570 
00571 void String::replace(const String& find, const String& replace)
00572 {
00573     if (len == 0 || find.len == 0) return;
00574     int diff = replace.len - find.len;
00575     char *readFrom = buffer;
00576     char *foundAt;
00577     if (diff == 0) {
00578         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00579             memcpy(foundAt, replace.buffer, replace.len);
00580             readFrom = foundAt + replace.len;
00581         }
00582     } else if (diff < 0) {
00583         char *writeTo = buffer;
00584         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00585             unsigned int n = foundAt - readFrom;
00586             memcpy(writeTo, readFrom, n);
00587             writeTo += n;
00588             memcpy(writeTo, replace.buffer, replace.len);
00589             writeTo += replace.len;
00590             readFrom = foundAt + find.len;
00591             len += diff;
00592         }
00593         strcpy(writeTo, readFrom);
00594     } else {
00595         unsigned int size = len; // compute size needed for result
00596         while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
00597             readFrom = foundAt + find.len;
00598             size += diff;
00599         }
00600         if (size == len) return;
00601         if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
00602         int index = len - 1;
00603         while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
00604             readFrom = buffer + index + find.len;
00605             memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
00606             len += diff;
00607             buffer[len] = 0;
00608             memcpy(buffer + index, replace.buffer, replace.len);
00609             index--;
00610         }
00611     }
00612 }
00613 
00614 void String::toLowerCase(void)
00615 {
00616     if (!buffer) return;
00617     for (char *p = buffer; *p; p++) {
00618         *p = tolower(*p);
00619     }
00620 }
00621 
00622 void String::toUpperCase(void)
00623 {
00624     if (!buffer) return;
00625     for (char *p = buffer; *p; p++) {
00626         *p = toupper(*p);
00627     }
00628 }
00629 
00630 void String::trim(void)
00631 {
00632     if (!buffer || len == 0) return;
00633     char *begin = buffer;
00634     while (isspace(*begin)) begin++;
00635     char *end = buffer + len - 1;
00636     while (isspace(*end) && end >= begin) end--;
00637     len = end + 1 - begin;
00638     if (begin > buffer) memcpy(buffer, begin, len);
00639     buffer[len] = 0;
00640 }
00641 
00642 /*********************************************/
00643 /*  Parsing / Conversion                     */
00644 /*********************************************/
00645 
00646 long String::toInt(void) const
00647 {
00648     if (buffer) return atol(buffer);
00649     return 0;
00650 }
00651 
00652 
00653