]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp
Squashed 'tmk_core/' content from commit 05caacc
[qmk_firmware.git] / protocol / usb_hid / arduino-1.0.1 / cores / arduino / 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 "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