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