sanguino/cores/arduino/WString.cpp

changeset 2
b373b0288715
equal deleted inserted replaced
1:b584642d4f58 2:b373b0288715
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
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) 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) 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
645

mercurial