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