PropWare  3.0.0.229
C++ objects and CMake build system for Parallax Propeller
WString.cpp
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 "nonstdlib.h" // MCH for Propeller port.
23 #include "WString.h"
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 }
isspace
#define isspace(c)
Definition: ctype.h:119
String
Definition: String.h:10
tolower
int tolower(int c)
toupper
int toupper(int c)
nonstdlib.h
Provides common C functions that are not part of stdlib.h but the Arduino depends upon.