Armageddon - a missile commad clone by Wuuff, originally for Gamebuino. Conversion by Jonne
Dependencies: PokittoLib
Fork of Asterocks by
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
Generated on Sun Jul 17 2022 01:52:57 by 1.7.2