WString.cpp 23.7 KB
Newer Older
M
me-no-dev 已提交
1 2 3 4 5
/*
 WString.cpp - String library for Wiring & Arduino
 ...mostly rewritten by Paul Stoffregen...
 Copyright (c) 2009-10 Hernando Barragan.  All rights reserved.
 Copyright 2011, Paul Stoffregen, paul@pjrc.com
6 7
 Modified by Ivan Grokhotkov, 2014 - esp8266 support
 Modified by Michael C. Miller, 2015 - esp8266 progmem support
M
me-no-dev 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

D
David McCurley 已提交
24
#include "Arduino.h"
M
me-no-dev 已提交
25 26
#include "WString.h"
#include "stdlib_noniso.h"
M
mrengineer7777 已提交
27
#include "esp32-hal-log.h"
M
me-no-dev 已提交
28 29 30 31 32

/*********************************************/
/*  Constructors                             */
/*********************************************/

33
String::String(const char *cstr) {
M
me-no-dev 已提交
34
    init();
35
    if (cstr)
M
me-no-dev 已提交
36 37 38
        copy(cstr, strlen(cstr));
}

39 40 41 42 43 44
String::String(const char *cstr, unsigned int length) {
    init();
    if (cstr)
        copy(cstr, length);
}

45
String::String(const String &value) {
M
me-no-dev 已提交
46 47 48
    init();
    *this = value;
}
49

50 51 52 53 54
String::String(const __FlashStringHelper *pstr) {
    init();
    *this = pstr; // see operator =
}

M
me-no-dev 已提交
55
#ifdef __GXX_EXPERIMENTAL_CXX0X__
56
String::String(String &&rval) {
M
me-no-dev 已提交
57 58 59 60
    init();
    move(rval);
}

61
String::String(StringSumHelper &&rval) {
M
me-no-dev 已提交
62 63 64 65 66
    init();
    move(rval);
}
#endif

67
String::String(char c) {
M
me-no-dev 已提交
68
    init();
69
    char buf[] = { c, '\0' };
M
me-no-dev 已提交
70 71 72
    *this = buf;
}

73
String::String(unsigned char value, unsigned char base) {
M
me-no-dev 已提交
74 75 76 77 78 79
    init();
    char buf[1 + 8 * sizeof(unsigned char)];
    utoa(value, buf, base);
    *this = buf;
}

80
String::String(int value, unsigned char base) {
M
me-no-dev 已提交
81 82
    init();
    char buf[2 + 8 * sizeof(int)];
D
David McCurley 已提交
83
    itoa(value, buf, base);
M
me-no-dev 已提交
84 85 86
    *this = buf;
}

87
String::String(unsigned int value, unsigned char base) {
M
me-no-dev 已提交
88 89 90 91 92 93
    init();
    char buf[1 + 8 * sizeof(unsigned int)];
    utoa(value, buf, base);
    *this = buf;
}

94
String::String(long value, unsigned char base) {
M
me-no-dev 已提交
95 96
    init();
    char buf[2 + 8 * sizeof(long)];
D
David McCurley 已提交
97
    ltoa(value, buf, base);
M
me-no-dev 已提交
98 99 100
    *this = buf;
}

101
String::String(unsigned long value, unsigned char base) {
M
me-no-dev 已提交
102 103 104 105 106 107
    init();
    char buf[1 + 8 * sizeof(unsigned long)];
    ultoa(value, buf, base);
    *this = buf;
}

108
String::String(float value, unsigned int decimalPlaces) {
M
me-no-dev 已提交
109
    init();
110 111 112 113 114 115 116 117
    char *buf = (char*)malloc(decimalPlaces + 42);
    if (buf) {
        *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
        free(buf);
    } else {
        *this = "nan";
        log_e("No enought memory for the operation.");
    }
M
me-no-dev 已提交
118 119
}

120
String::String(double value, unsigned int decimalPlaces) {
M
me-no-dev 已提交
121
    init();
122 123 124 125 126 127 128 129
    char *buf = (char*)malloc(decimalPlaces + 312);
    if (buf) {
        *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
        free(buf);
    } else {
        *this = "nan";
        log_e("No enought memory for the operation.");
    }
M
me-no-dev 已提交
130 131
}

132 133 134
String::String(long long value, unsigned char base) {
    init();
    char buf[2 + 8 * sizeof(long long)];
D
David McCurley 已提交
135
    lltoa(value, buf, base);
136 137 138 139 140 141 142 143 144 145
    *this = buf;
}

String::String(unsigned long long value, unsigned char base) {
    init();
    char buf[1 + 8 * sizeof(unsigned long long)];
    ulltoa(value, buf, base);
    *this = buf;
}

146 147
String::~String() {
    invalidate();
M
me-no-dev 已提交
148 149
}

D
David McCurley 已提交
150 151 152
/*********************************************/
/*  Memory Management                        */
/*********************************************/
M
me-no-dev 已提交
153

154 155
inline void String::init(void) {
    setSSO(false);
156
    setBuffer(nullptr);
157 158
    setCapacity(0);
    setLen(0);
M
me-no-dev 已提交
159 160
}

161
void String::invalidate(void) {
162
    if(!isSSO() && wbuffer())
163
        free(wbuffer());
M
me-no-dev 已提交
164 165 166
    init();
}

D
David McCurley 已提交
167
bool String::reserve(unsigned int size) {
168
    if(buffer() && capacity() >= size)
D
David McCurley 已提交
169
        return true;
M
me-no-dev 已提交
170
    if(changeBuffer(size)) {
171 172
        if(len() == 0)
            wbuffer()[0] = 0;
D
David McCurley 已提交
173
        return true;
M
me-no-dev 已提交
174
    }
D
David McCurley 已提交
175
    return false;
M
me-no-dev 已提交
176 177
}

D
David McCurley 已提交
178
bool String::changeBuffer(unsigned int maxStrLen) {
179
    // Can we use SSO here to avoid allocation?
180 181
    if (maxStrLen < sizeof(sso.buff) - 1) {
        if (isSSO() || !buffer()) {
182
            // Already using SSO, nothing to do
D
David McCurley 已提交
183
            uint16_t oldLen = len();
184
            setSSO(true);
185
            setLen(oldLen);
186 187 188
        } else { // if bufptr && !isSSO()
            // Using bufptr, need to shrink into sso.buff
            char temp[sizeof(sso.buff)];
189 190
            memcpy(temp, buffer(), maxStrLen);
            free(wbuffer());
191
            uint16_t oldLen = len();
192 193
            setSSO(true);
            memcpy(wbuffer(), temp, maxStrLen);
194
            setLen(oldLen);
195
        }
D
David McCurley 已提交
196
        return true;
197 198 199 200 201 202 203 204
    }
    // Fallthrough to normal allocator
    size_t newSize = (maxStrLen + 16) & (~0xf);
    // Make sure we can fit newsize in the buffer
    if (newSize > CAPACITY_MAX) {
        return false;
    }
    uint16_t oldLen = len();
205 206
    char *newbuffer = (char *) realloc(isSSO() ? nullptr : wbuffer(), newSize);
    if (newbuffer) {
207
        size_t oldSize = capacity() + 1; // include NULL.
208
        if (isSSO()) {
209
            // Copy the SSO buffer into allocated space
210
            memmove(newbuffer, sso.buff, sizeof(sso.buff));
M
me-no-dev 已提交
211
        }
D
David McCurley 已提交
212
        if (newSize > oldSize) {
213 214 215 216 217
            memset(newbuffer + oldSize, 0, newSize - oldSize);
        }
        setSSO(false);
        setCapacity(newSize - 1);
        setBuffer(newbuffer);
218
        setLen(oldLen); // Needed in case of SSO where len() never existed
D
David McCurley 已提交
219
        return true;
M
me-no-dev 已提交
220
    }
D
David McCurley 已提交
221
    return false;
M
me-no-dev 已提交
222 223
}

D
David McCurley 已提交
224 225 226
/*********************************************/
/*  Copy and Move                            */
/*********************************************/
M
me-no-dev 已提交
227

228
String & String::copy(const char *cstr, unsigned int length) {
M
me-no-dev 已提交
229 230 231 232
    if(!reserve(length)) {
        invalidate();
        return *this;
    }
233
    memmove(wbuffer(), cstr, length + 1);
234
    setLen(length);
M
me-no-dev 已提交
235 236
    return *this;
}
237

238 239 240 241 242
String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
    if (!reserve(length)) {
        invalidate();
        return *this;
    }
243
    memcpy_P(wbuffer(), (PGM_P)pstr, length + 1); // We know wbuffer() cannot ever be in PROGMEM, so memcpy safe here
244
    setLen(length);
245
    return *this;
M
me-no-dev 已提交
246
}
247

M
me-no-dev 已提交
248
#ifdef __GXX_EXPERIMENTAL_CXX0X__
249 250 251
void String::move(String &rhs) {
    if(buffer()) {
        if(capacity() >= rhs.len()) {
252
            memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
253 254
            setLen(rhs.len());
	    rhs.invalidate();
M
me-no-dev 已提交
255 256
            return;
        } else {
257
            if (!isSSO()) {
258 259 260
                free(wbuffer());
                setBuffer(nullptr);
            }
M
me-no-dev 已提交
261 262
        }
    }
263
    if (rhs.isSSO()) {
264
        setSSO(true);
265
        memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
266 267 268 269 270 271 272 273 274
    } else {
        setSSO(false);
        setBuffer(rhs.wbuffer());
    }
    setCapacity(rhs.capacity());
    setLen(rhs.len());
    rhs.setSSO(false);
    rhs.setCapacity(0);
    rhs.setBuffer(nullptr);
275
    rhs.setLen(0);
M
me-no-dev 已提交
276 277 278
}
#endif

279 280
String & String::operator =(const String &rhs) {
    if(this == &rhs)
M
me-no-dev 已提交
281
        return *this;
282 283 284
    if(rhs.buffer())
        copy(rhs.buffer(), rhs.len());
    else
M
me-no-dev 已提交
285 286 287 288 289
        invalidate();
    return *this;
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
290 291
String & String::operator =(String &&rval) {
    if(this != &rval)
M
me-no-dev 已提交
292 293 294 295
        move(rval);
    return *this;
}

296 297
String & String::operator =(StringSumHelper &&rval) {
    if(this != &rval)
M
me-no-dev 已提交
298 299 300 301 302
        move(rval);
    return *this;
}
#endif

303 304
String & String::operator =(const char *cstr) {
    if(cstr)
M
me-no-dev 已提交
305
        copy(cstr, strlen(cstr));
306
    else
M
me-no-dev 已提交
307 308 309
        invalidate();
    return *this;
}
310

311 312 313 314 315
String & String::operator =(const __FlashStringHelper *pstr) {
    if(pstr)
        copy(pstr, strlen_P((PGM_P)pstr));
    else
        invalidate();
M
me-no-dev 已提交
316 317 318

    return *this;
}
319

D
David McCurley 已提交
320 321 322
/*********************************************/
/*  concat                                   */
/*********************************************/
M
me-no-dev 已提交
323

D
David McCurley 已提交
324
bool String::concat(const String &s) {
325 326 327 328 329
    // Special case if we're concatting ourself (s += s;) since we may end up
    // realloc'ing the buffer and moving s.buffer in the method called
    if (&s == this) {
        unsigned int newlen = 2 * len();
        if (!s.buffer())
D
David McCurley 已提交
330
            return false;
331
        if (s.len() == 0)
D
David McCurley 已提交
332
            return true;
333
        if (!reserve(newlen))
D
David McCurley 已提交
334
            return false;
335
        memmove(wbuffer() + len(), buffer(), len());
336 337
        setLen(newlen);
        wbuffer()[len()] = 0;
D
David McCurley 已提交
338
        return true;
339 340 341
    } else {
        return concat(s.buffer(), s.len());
    }
M
me-no-dev 已提交
342 343
}

D
David McCurley 已提交
344
bool String::concat(const char *cstr, unsigned int length) {
345 346
    unsigned int newlen = len() + length;
    if(!cstr)
D
David McCurley 已提交
347
        return false;
348
    if(length == 0)
D
David McCurley 已提交
349
        return true;
350
    if(!reserve(newlen))
D
David McCurley 已提交
351
        return false;
352 353 354 355 356 357
    if (cstr >= wbuffer() && cstr < wbuffer() + len())
        // compatible with SSO in ram #6155 (case "x += x.c_str()")
        memmove(wbuffer() + len(), cstr, length + 1);
    else
        // compatible with source in flash #6367
        memcpy_P(wbuffer() + len(), cstr, length + 1);
358
    setLen(newlen);
D
David McCurley 已提交
359
    return true;
M
me-no-dev 已提交
360 361
}

D
David McCurley 已提交
362
bool String::concat(const char *cstr) {
363
    if(!cstr)
D
David McCurley 已提交
364
        return false;
M
me-no-dev 已提交
365 366 367
    return concat(cstr, strlen(cstr));
}

D
David McCurley 已提交
368
bool String::concat(char c) {
369
    char buf[] = { c, '\0' };
M
me-no-dev 已提交
370 371 372
    return concat(buf, 1);
}

D
David McCurley 已提交
373
bool String::concat(unsigned char num) {
M
me-no-dev 已提交
374
    char buf[1 + 3 * sizeof(unsigned char)];
D
David McCurley 已提交
375 376
    utoa(num, buf, 10);
    return concat(buf, strlen(buf));
M
me-no-dev 已提交
377 378
}

D
David McCurley 已提交
379
bool String::concat(int num) {
M
me-no-dev 已提交
380
    char buf[2 + 3 * sizeof(int)];
D
David McCurley 已提交
381 382
    itoa(num, buf, 10);
    return concat(buf, strlen(buf));
M
me-no-dev 已提交
383 384
}

D
David McCurley 已提交
385
bool String::concat(unsigned int num) {
M
me-no-dev 已提交
386 387 388 389 390
    char buf[1 + 3 * sizeof(unsigned int)];
    utoa(num, buf, 10);
    return concat(buf, strlen(buf));
}

D
David McCurley 已提交
391
bool String::concat(long num) {
M
me-no-dev 已提交
392
    char buf[2 + 3 * sizeof(long)];
D
David McCurley 已提交
393 394
    ltoa(num, buf, 10);
    return concat(buf, strlen(buf));
M
me-no-dev 已提交
395 396
}

D
David McCurley 已提交
397
bool String::concat(unsigned long num) {
M
me-no-dev 已提交
398 399 400 401 402
    char buf[1 + 3 * sizeof(unsigned long)];
    ultoa(num, buf, 10);
    return concat(buf, strlen(buf));
}

D
David McCurley 已提交
403 404 405 406 407 408 409 410 411 412 413 414
bool String::concat(long long num) {
    char buf[2 + 3 * sizeof(long long)];
    lltoa(num, buf, 10);
    return concat(buf, strlen(buf));
}

bool String::concat(unsigned long long num) {
    char buf[1 + 3 * sizeof(unsigned long long)];
    ulltoa(num, buf, 10);
    return concat(buf, strlen(buf));
}

D
David McCurley 已提交
415
bool String::concat(float num) {
M
me-no-dev 已提交
416 417 418 419 420
    char buf[20];
    char* string = dtostrf(num, 4, 2, buf);
    return concat(string, strlen(string));
}

D
David McCurley 已提交
421
bool String::concat(double num) {
M
me-no-dev 已提交
422 423 424 425
    char buf[20];
    char* string = dtostrf(num, 4, 2, buf);
    return concat(string, strlen(string));
}
426

D
David McCurley 已提交
427 428 429
bool String::concat(const __FlashStringHelper * str) {
    if (!str)
        return false;
430
    int length = strlen_P((PGM_P)str);
D
David McCurley 已提交
431 432
    if (length == 0)
        return true;
433
    unsigned int newlen = len() + length;
D
David McCurley 已提交
434 435
    if (!reserve(newlen))
        return false;
436
    memcpy_P(wbuffer() + len(), (PGM_P)str, length + 1);
437
    setLen(newlen);
D
David McCurley 已提交
438
    return true;
M
me-no-dev 已提交
439
}
440

M
me-no-dev 已提交
441 442 443 444
/*********************************************/
/*  Concatenate                              */
/*********************************************/

445
StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) {
M
me-no-dev 已提交
446
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
447
    if(!a.concat(rhs.buffer(), rhs.len()))
M
me-no-dev 已提交
448 449 450 451
        a.invalidate();
    return a;
}

452
StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) {
M
me-no-dev 已提交
453
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
454
    if(!cstr || !a.concat(cstr, strlen(cstr)))
M
me-no-dev 已提交
455 456 457 458
        a.invalidate();
    return a;
}

459
StringSumHelper & operator +(const StringSumHelper &lhs, char c) {
M
me-no-dev 已提交
460
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
461
    if(!a.concat(c))
M
me-no-dev 已提交
462 463 464 465
        a.invalidate();
    return a;
}

466
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) {
M
me-no-dev 已提交
467
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
468
    if(!a.concat(num))
M
me-no-dev 已提交
469 470 471 472
        a.invalidate();
    return a;
}

473
StringSumHelper & operator +(const StringSumHelper &lhs, int num) {
M
me-no-dev 已提交
474
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
475
    if(!a.concat(num))
M
me-no-dev 已提交
476 477 478 479
        a.invalidate();
    return a;
}

480
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) {
M
me-no-dev 已提交
481
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
482
    if(!a.concat(num))
M
me-no-dev 已提交
483 484 485 486
        a.invalidate();
    return a;
}

487
StringSumHelper & operator +(const StringSumHelper &lhs, long num) {
M
me-no-dev 已提交
488
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
489
    if(!a.concat(num))
M
me-no-dev 已提交
490 491 492 493
        a.invalidate();
    return a;
}

494
StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) {
M
me-no-dev 已提交
495
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
496
    if(!a.concat(num))
M
me-no-dev 已提交
497 498 499 500
        a.invalidate();
    return a;
}

501
StringSumHelper & operator +(const StringSumHelper &lhs, float num) {
M
me-no-dev 已提交
502
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
503
    if(!a.concat(num))
M
me-no-dev 已提交
504 505 506 507
        a.invalidate();
    return a;
}

508
StringSumHelper & operator +(const StringSumHelper &lhs, double num) {
M
me-no-dev 已提交
509
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
510
    if(!a.concat(num))
M
me-no-dev 已提交
511 512 513
        a.invalidate();
    return a;
}
514

515 516 517 518 519 520 521 522 523 524 525 526 527 528
StringSumHelper & operator +(const StringSumHelper &lhs, long long num) {
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
    if(!a.concat(num))
        a.invalidate();
    return a;
}

StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long long num) {
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
    if(!a.concat(num))
        a.invalidate();
    return a;
}

M
me-no-dev 已提交
529 530 531
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
    StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
532 533
    if (!a.concat(rhs))
        a.invalidate();
M
me-no-dev 已提交
534 535
    return a;
}
536

D
David McCurley 已提交
537 538 539
/*********************************************/
/*  Comparison                               */
/*********************************************/
M
me-no-dev 已提交
540

541 542 543 544 545 546
int String::compareTo(const String &s) const {
    if(!buffer() || !s.buffer()) {
        if(s.buffer() && s.len() > 0)
            return 0 - *(unsigned char *) s.buffer();
        if(buffer() && len() > 0)
            return *(unsigned char *) buffer();
M
me-no-dev 已提交
547 548
        return 0;
    }
549
    return strcmp(buffer(), s.buffer());
M
me-no-dev 已提交
550 551
}

D
David McCurley 已提交
552
bool String::equals(const String &s2) const {
553
    return (len() == s2.len() && compareTo(s2) == 0);
M
me-no-dev 已提交
554 555
}

D
David McCurley 已提交
556
bool String::equals(const char *cstr) const {
557
    if(len() == 0)
M
me-no-dev 已提交
558
        return (cstr == NULL || *cstr == 0);
559 560 561
    if(cstr == NULL)
        return buffer()[0] == 0;
    return strcmp(buffer(), cstr) == 0;
M
me-no-dev 已提交
562 563
}

D
David McCurley 已提交
564
bool String::operator<(const String &rhs) const {
M
me-no-dev 已提交
565 566 567
    return compareTo(rhs) < 0;
}

D
David McCurley 已提交
568
bool String::operator>(const String &rhs) const {
M
me-no-dev 已提交
569 570 571
    return compareTo(rhs) > 0;
}

D
David McCurley 已提交
572
bool String::operator<=(const String &rhs) const {
M
me-no-dev 已提交
573 574 575
    return compareTo(rhs) <= 0;
}

D
David McCurley 已提交
576
bool String::operator>=(const String &rhs) const {
M
me-no-dev 已提交
577 578 579
    return compareTo(rhs) >= 0;
}

D
David McCurley 已提交
580
bool String::equalsIgnoreCase(const String &s2) const {
581
    if(this == &s2)
D
David McCurley 已提交
582
        return true;
583
    if(len() != s2.len())
D
David McCurley 已提交
584
        return false;
585
    if(len() == 0)
D
David McCurley 已提交
586
        return true;
587 588
    const char *p1 = buffer();
    const char *p2 = s2.buffer();
M
me-no-dev 已提交
589
    while(*p1) {
590
        if(tolower(*p1++) != tolower(*p2++))
D
David McCurley 已提交
591
            return false;
M
me-no-dev 已提交
592
    }
D
David McCurley 已提交
593
    return true;
M
me-no-dev 已提交
594 595
}

596 597 598 599
unsigned char String::equalsConstantTime(const String &s2) const {
    // To avoid possible time-based attacks present function
    // compares given strings in a constant time.
    if(len() != s2.len())
M
me-no-dev 已提交
600
        return 0;
601 602 603
    //at this point lengths are the same
    if(len() == 0)
        return 1;
A
Ato Araki 已提交
604
    //at this point lengths are the same and non-zero
605 606 607 608 609 610 611 612 613 614 615
    const char *p1 = buffer();
    const char *p2 = s2.buffer();
    unsigned int equalchars = 0;
    unsigned int diffchars = 0;
    while(*p1) {
        if(*p1 == *p2)
            ++equalchars;
        else
            ++diffchars;
        ++p1;
        ++p2;
M
me-no-dev 已提交
616
    }
617 618 619 620 621 622
    //the following should force a constant time eval of the condition without a compiler "logical shortcut"
    unsigned char equalcond = (equalchars == len());
    unsigned char diffcond = (diffchars == 0);
    return (equalcond & diffcond); //bitwise AND
}

D
David McCurley 已提交
623
bool String::startsWith(const String &s2) const {
624
    if(len() < s2.len())
D
David McCurley 已提交
625
        return false;
M
me-no-dev 已提交
626 627 628
    return startsWith(s2, 0);
}

D
David McCurley 已提交
629
bool String::startsWith(const String &s2, unsigned int offset) const {
630
    if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer())
D
David McCurley 已提交
631
        return false;
632
    return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0;
M
me-no-dev 已提交
633 634
}

D
David McCurley 已提交
635
bool String::endsWith(const String &s2) const {
636
    if(len() < s2.len() || !buffer() || !s2.buffer())
D
David McCurley 已提交
637
        return false;
638
    return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0;
M
me-no-dev 已提交
639 640
}

D
David McCurley 已提交
641 642 643
/*********************************************/
/*  Character Access                         */
/*********************************************/
M
me-no-dev 已提交
644

645
char String::charAt(unsigned int loc) const {
M
me-no-dev 已提交
646 647 648
    return operator[](loc);
}

649 650 651
void String::setCharAt(unsigned int loc, char c) {
    if(loc < len())
        wbuffer()[loc] = c;
M
me-no-dev 已提交
652 653
}

654
char & String::operator[](unsigned int index) {
M
me-no-dev 已提交
655
    static char dummy_writable_char;
656
    if(index >= len() || !buffer()) {
M
me-no-dev 已提交
657 658 659
        dummy_writable_char = 0;
        return dummy_writable_char;
    }
660
    return wbuffer()[index];
M
me-no-dev 已提交
661 662
}

663 664
char String::operator[](unsigned int index) const {
    if(index >= len() || !buffer())
M
me-no-dev 已提交
665
        return 0;
666
    return buffer()[index];
M
me-no-dev 已提交
667 668
}

669 670
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const {
    if(!bufsize || !buf)
M
me-no-dev 已提交
671
        return;
672
    if(index >= len()) {
M
me-no-dev 已提交
673 674 675 676
        buf[0] = 0;
        return;
    }
    unsigned int n = bufsize - 1;
677 678 679
    if(n > len() - index)
        n = len() - index;
    strncpy((char *) buf, buffer() + index, n);
M
me-no-dev 已提交
680 681 682
    buf[n] = 0;
}

D
David McCurley 已提交
683 684 685
/*********************************************/
/*  Search                                   */
/*********************************************/
M
me-no-dev 已提交
686

687
int String::indexOf(char c) const {
M
me-no-dev 已提交
688 689 690
    return indexOf(c, 0);
}

691 692
int String::indexOf(char ch, unsigned int fromIndex) const {
    if(fromIndex >= len())
M
me-no-dev 已提交
693
        return -1;
D
David McCurley 已提交
694
    const char *temp = strchr(buffer() + fromIndex, ch);
695
    if(temp == NULL)
M
me-no-dev 已提交
696
        return -1;
697
    return temp - buffer();
M
me-no-dev 已提交
698 699
}

700
int String::indexOf(const String &s2) const {
M
me-no-dev 已提交
701 702 703
    return indexOf(s2, 0);
}

704 705
int String::indexOf(const String &s2, unsigned int fromIndex) const {
    if(fromIndex >= len())
M
me-no-dev 已提交
706
        return -1;
707 708
    const char *found = strstr(buffer() + fromIndex, s2.buffer());
    if(found == NULL)
M
me-no-dev 已提交
709
        return -1;
710
    return found - buffer();
M
me-no-dev 已提交
711 712
}

713 714
int String::lastIndexOf(char theChar) const {
    return lastIndexOf(theChar, len() - 1);
M
me-no-dev 已提交
715 716
}

717 718
int String::lastIndexOf(char ch, unsigned int fromIndex) const {
    if(fromIndex >= len())
M
me-no-dev 已提交
719
        return -1;
720 721 722 723 724
    char tempchar = buffer()[fromIndex + 1];
    wbuffer()[fromIndex + 1] = '\0';
    char* temp = strrchr(wbuffer(), ch);
    wbuffer()[fromIndex + 1] = tempchar;
    if(temp == NULL)
M
me-no-dev 已提交
725
        return -1;
726
    return temp - buffer();
M
me-no-dev 已提交
727 728
}

729 730
int String::lastIndexOf(const String &s2) const {
    return lastIndexOf(s2, len() - s2.len());
M
me-no-dev 已提交
731 732
}

733 734
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const {
    if(s2.len() == 0 || len() == 0 || s2.len() > len())
M
me-no-dev 已提交
735
        return -1;
736 737
    if(fromIndex >= len())
        fromIndex = len() - 1;
M
me-no-dev 已提交
738
    int found = -1;
739 740 741
    for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) {
        p = strstr(p, s2.buffer());
        if(!p)
M
me-no-dev 已提交
742
            break;
743 744
        if((unsigned int) (p - wbuffer()) <= fromIndex)
            found = p - buffer();
M
me-no-dev 已提交
745 746 747 748
    }
    return found;
}

749
String String::substring(unsigned int left, unsigned int right) const {
M
me-no-dev 已提交
750 751 752 753 754 755
    if(left > right) {
        unsigned int temp = right;
        right = left;
        left = temp;
    }
    String out;
756
    if(left >= len())
M
me-no-dev 已提交
757
        return out;
758 759
    if(right > len())
        right = len();
760
    out.copy(buffer() + left, right - left);
M
me-no-dev 已提交
761 762 763
    return out;
}

D
David McCurley 已提交
764 765 766
/*********************************************/
/*  Modification                             */
/*********************************************/
M
me-no-dev 已提交
767

768 769
void String::replace(char find, char replace) {
    if(!buffer())
M
me-no-dev 已提交
770
        return;
771 772
    for(char *p = wbuffer(); *p; p++) {
        if(*p == find)
M
me-no-dev 已提交
773 774 775 776
            *p = replace;
    }
}

D
David McCurley 已提交
777
void String::replace(const String &find, const String &replace) {
778
    if(len() == 0 || find.len() == 0)
M
me-no-dev 已提交
779
        return;
780 781
    int diff = replace.len() - find.len();
    char *readFrom = wbuffer();
M
me-no-dev 已提交
782 783
    char *foundAt;
    if(diff == 0) {
784 785 786
        while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
            memmove(foundAt, replace.buffer(), replace.len());
            readFrom = foundAt + replace.len();
M
me-no-dev 已提交
787 788
        }
    } else if(diff < 0) {
789
        char *writeTo = wbuffer();
M
me-no-dev 已提交
790
        unsigned int l = len();
791
        while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
M
me-no-dev 已提交
792
            unsigned int n = foundAt - readFrom;
793
            memmove(writeTo, readFrom, n);
M
me-no-dev 已提交
794
            writeTo += n;
795 796 797
            memmove(writeTo, replace.buffer(), replace.len());
            writeTo += replace.len();
            readFrom = foundAt + find.len();
M
me-no-dev 已提交
798
            l += diff;
M
me-no-dev 已提交
799
        }
800
        memmove(writeTo, readFrom, strlen(readFrom)+1);
M
me-no-dev 已提交
801
        setLen(l);
M
me-no-dev 已提交
802
    } else {
803 804 805
        unsigned int size = len(); // compute size needed for result
        while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
            readFrom = foundAt + find.len();
M
me-no-dev 已提交
806 807
            size += diff;
        }
808
        if(size == len())
M
me-no-dev 已提交
809
            return;
S
s-hadinger 已提交
810
        if(size > capacity() && !changeBuffer(size)) {
M
mrengineer7777 已提交
811 812
            log_w("String.Replace() Insufficient space to replace string");
            return;
S
s-hadinger 已提交
813
        }
814
        int index = len() - 1;
M
me-no-dev 已提交
815
        while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
816 817
            readFrom = wbuffer() + index + find.len();
            memmove(readFrom + diff, readFrom, len() - (readFrom - buffer()));
M
me-no-dev 已提交
818
            int newLen = len() + diff;
819 820 821
            memmove(wbuffer() + index, replace.buffer(), replace.len());
            setLen(newLen);
            wbuffer()[newLen] = 0;
M
me-no-dev 已提交
822 823 824 825 826
            index--;
        }
    }
}

827
void String::remove(unsigned int index) {
M
me-no-dev 已提交
828 829 830 831 832 833
    // Pass the biggest integer as the count. The remove method
    // below will take care of truncating it at the end of the
    // string.
    remove(index, (unsigned int) -1);
}

834 835
void String::remove(unsigned int index, unsigned int count) {
    if(index >= len()) {
M
me-no-dev 已提交
836 837 838 839 840
        return;
    }
    if(count <= 0) {
        return;
    }
841 842
    if(count > len() - index) {
        count = len() - index;
M
me-no-dev 已提交
843
    }
844 845 846
    char *writeTo = wbuffer() + index;
    unsigned int newlen = len() - count;
    memmove(writeTo, wbuffer() + index + count, newlen - index);
M
me-no-dev 已提交
847
    setLen(newlen);
848
    wbuffer()[newlen] = 0;
M
me-no-dev 已提交
849 850
}

851 852
void String::toLowerCase(void) {
    if(!buffer())
M
me-no-dev 已提交
853
        return;
854
    for(char *p = wbuffer(); *p; p++) {
M
me-no-dev 已提交
855 856 857 858
        *p = tolower(*p);
    }
}

859 860
void String::toUpperCase(void) {
    if(!buffer())
M
me-no-dev 已提交
861
        return;
862
    for(char *p = wbuffer(); *p; p++) {
M
me-no-dev 已提交
863 864 865 866
        *p = toupper(*p);
    }
}

867 868
void String::trim(void) {
    if(!buffer() || len() == 0)
M
me-no-dev 已提交
869
        return;
870 871
    char *begin = wbuffer();
    while(isspace(*begin))
M
me-no-dev 已提交
872
        begin++;
873 874
    char *end = wbuffer() + len() - 1;
    while(isspace(*end) && end >= begin)
M
me-no-dev 已提交
875
        end--;
876 877 878
    unsigned int newlen = end + 1 - begin;
    if(begin > buffer())
        memmove(wbuffer(), begin, newlen);
879
    setLen(newlen);
880
    wbuffer()[newlen] = 0;
M
me-no-dev 已提交
881 882
}

D
David McCurley 已提交
883 884 885
/*********************************************/
/*  Parsing / Conversion                     */
/*********************************************/
M
me-no-dev 已提交
886

887 888 889
long String::toInt(void) const {
    if (buffer())
        return atol(buffer());
M
me-no-dev 已提交
890 891 892
    return 0;
}

893 894 895
float String::toFloat(void) const {
    if (buffer())
        return atof(buffer());
M
me-no-dev 已提交
896 897
    return 0;
}
M
Me No Dev 已提交
898

D
David McCurley 已提交
899
double String::toDouble(void) const {
900 901 902
    if (buffer())
        return atof(buffer());
    return 0.0;
T
Terry J Myers 已提交
903
}
M
Me No Dev 已提交
904

905 906 907
// global empty string to allow returning const String& with nothing

const String emptyString;