Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / cores / arduino / WString.cpp @ 58d82c77

History | View | Annotate | Download (13.9 KB)

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