diff options
author | David A. Mellis <d.mellis@arduino.cc> | 2011-03-11 17:56:10 -0500 |
---|---|---|
committer | David A. Mellis <d.mellis@arduino.cc> | 2011-03-11 17:56:10 -0500 |
commit | 438bca3cb270b0d882b6b3b0bc42d57d72307c76 (patch) | |
tree | 6ae4bde98e9b0b46e9917b8d27a5b87fe12bb8b4 /cores/arduino | |
parent | ba3d26dcaee4245912e49125b847d29a771bd08b (diff) |
Rewrite of the String class by Paul Stoffregen.
http://www.pjrc.com/teensy/string_class_experimental.html
Diffstat (limited to 'cores/arduino')
-rw-r--r-- | cores/arduino/WString.cpp | 783 | ||||
-rw-r--r-- | cores/arduino/WString.h | 243 |
2 files changed, 681 insertions, 345 deletions
diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index 5899798..c980e24 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -1,6 +1,8 @@ /* WString.cpp - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... Copyright (c) 2009-10 Hernando Barragan. All rights reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,427 +19,680 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <stdlib.h> -#include "Arduino.h" #include "WString.h" -String::String( const char *value ) +/*********************************************/ +/* Constructors */ +/*********************************************/ + +String::String(const char *cstr) { - if ( value == NULL ) - value = ""; - getBuffer( _length = strlen( value ) ); - if ( _buffer != NULL ) - strcpy( _buffer, value ); + init(); + if (cstr) copy(cstr, strlen(cstr)); } -String::String( const String &value ) +String::String(const __FlashStringHelper *pgmstr) { - getBuffer( _length = value._length ); - if ( _buffer != NULL ) - strcpy( _buffer, value._buffer ); + init(); + *this = pgmstr; } -String::String( const char value ) +String::String(const String &value) { - _length = 1; - getBuffer(1); - if ( _buffer != NULL ) { - _buffer[0] = value; - _buffer[1] = 0; - } + init(); + *this = value; } -String::String( const unsigned char value ) +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String::String(String &&rval) { - _length = 1; - getBuffer(1); - if ( _buffer != NULL) { - _buffer[0] = value; - _buffer[1] = 0; - } + init(); + move(rval); } - -String::String( const int value, const int base ) +String::String(StringSumHelper &&rval) { - char buf[33]; - itoa((signed long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + move(rval); } +#endif -String::String( const unsigned int value, const int base ) +String::String(char c) { - char buf[33]; - ultoa((unsigned long)value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + *this = c; } -String::String( const long value, const int base ) +String::String(unsigned char c) { - char buf[33]; - ltoa(value, buf, base); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + *this = (char)c; } -String::String( const unsigned long value, const int base ) +String::String(const int value, unsigned char base) { - char buf[33]; - ultoa(value, buf, 10); - getBuffer( _length = strlen(buf) ); - if ( _buffer != NULL ) - strcpy( _buffer, buf ); + init(); + char buf[18]; + itoa(value, buf, base); + *this = buf; } -char String::charAt( unsigned int loc ) const +String::String(unsigned int value, unsigned char base) { - return operator[]( loc ); + init(); + char buf[17]; + utoa(value, buf, base); + *this = buf; } -void String::setCharAt( unsigned int loc, const char aChar ) +String::String(long value, unsigned char base) { - if(_buffer == NULL) return; - if(_length > loc) { - _buffer[loc] = aChar; - } + init(); + char buf[34]; + ltoa(value, buf, base); + *this = buf; } -int String::compareTo( const String &s2 ) const +String::String(unsigned long value, unsigned char base) { - return strcmp( _buffer, s2._buffer ); + init(); + char buf[33]; + ultoa(value, buf, base); + *this = buf; } -const String & String::concat( const String &s2 ) +String::~String() { - return (*this) += s2; + free(buffer); } -const String & String::operator=( const String &rhs ) -{ - if ( this == &rhs ) - return *this; +/*********************************************/ +/* Memory Management */ +/*********************************************/ - if ( rhs._length > _length ) - { - free(_buffer); - getBuffer( rhs._length ); - } - - if ( _buffer != NULL ) { - _length = rhs._length; - strcpy( _buffer, rhs._buffer ); - } - return *this; +inline void String::init(void) +{ + buffer = NULL; + capacity = 0; + len = 0; + flags = 0; } -//const String & String::operator+=( const char aChar ) -//{ -// if ( _length == _capacity ) -// doubleBuffer(); -// -// _buffer[ _length++ ] = aChar; -// _buffer[ _length ] = '\0'; -// return *this; -//} +unsigned char String::reserve(unsigned int size) +{ + if (capacity >= size) return 1; + if (changeBuffer(size)) { + if (len == 0) buffer[0] = 0; + return 1; + } + return 0; +} -const String & String::operator+=( const String &other ) +unsigned char String::changeBuffer(unsigned int maxStrLen) { - _length += other._length; - if ( _length > _capacity ) - { - char *temp = (char *)realloc(_buffer, _length + 1); - if ( temp != NULL ) { - _buffer = temp; - _capacity = _length; - } else { - _length -= other._length; - return *this; - } - } - strcat( _buffer, other._buffer ); - return *this; + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; } +/*********************************************/ +/* Copy and Move */ +/*********************************************/ -int String::operator==( const String &rhs ) const +String & String::copy(const char *cstr, unsigned int length) { - return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); + if (length == 0) { + if (buffer) buffer[0] = 0; + len = 0; + return *this; + } + if (!reserve(length)) { + if (buffer) { + free(buffer); + buffer = NULL; + } + len = capacity = 0; + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; } -int String::operator!=( const String &rhs ) const +String & String::copy(const __FlashStringHelper *pgmstr) { - return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); + unsigned int length = strlen_P((const prog_char *)pgmstr); + if (!reserve(length)) { + if (buffer) { + free(buffer); + buffer = NULL; + } + len = capacity = 0; + return *this; + } + len = length; + strcpy_P(buffer, (const prog_char *)pgmstr); + return *this; } -int String::operator<( const String &rhs ) const +void String::move(String &rhs) { - return strcmp( _buffer, rhs._buffer ) < 0; + if (buffer) { + if (capacity >= rhs.len) { + strcpy(buffer, rhs.buffer); + len = rhs.len; + rhs.len = 0; + return; + } else { + free(buffer); + } + } + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.buffer = NULL; + rhs.capacity = 0; + rhs.len = 0; } -int String::operator>( const String &rhs ) const +String & String::operator = (const String &rhs) { - return strcmp( _buffer, rhs._buffer ) > 0; + if (this == &rhs) return *this; + return copy(rhs.buffer, rhs.len); } -int String::operator<=( const String &rhs ) const +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String & String::operator = (String &&rval) { - return strcmp( _buffer, rhs._buffer ) <= 0; + if (this != &rval) move(rval); + return *this; } -int String::operator>=( const String & rhs ) const +String & String::operator = (StringSumHelper &&rval) { - return strcmp( _buffer, rhs._buffer ) >= 0; + if (this != &rval) move(rval); + return *this; } +#endif -char & String::operator[]( unsigned int index ) +String & String::operator = (const char *cstr) { - static char dummy_writable_char; - if (index >= _length || !_buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return _buffer[ index ]; + if (cstr) { + copy(cstr, strlen(cstr)); + } else { + len = 0; + } + return *this; } -char String::operator[]( unsigned int index ) const +String & String::operator = (const __FlashStringHelper *pgmstr) { - // need to check for valid index, to do later - return _buffer[ index ]; + copy(pgmstr); + return *this; } -boolean String::endsWith( const String &s2 ) const +String & String::operator = (char c) { - if ( _length < s2._length ) - return 0; - - return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; + char buf[2]; + buf[0] = c; + buf[1] = 0; + return copy(buf, 1); } -boolean String::equals( const String &s2 ) const +/*********************************************/ +/* Append */ +/*********************************************/ + +String & String::append(const String &s) { - return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); + return append(s.buffer, s.len); } -boolean String::equalsIgnoreCase( const String &s2 ) const +String & String::append(const char *cstr, unsigned int length) { - if ( this == &s2 ) - return true; //1; - else if ( _length != s2._length ) - return false; //0; + unsigned int newlen = len + length; + if (length == 0 || !reserve(newlen)) return *this; + strcpy(buffer + len, cstr); + len = newlen; + return *this; +} - return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; +String & String::append(const char *cstr) +{ + if (cstr) append(cstr, strlen(cstr)); + return *this; } -String String::replace( char findChar, char replaceChar ) +String & String::append(const __FlashStringHelper *pgmstr) { - if ( _buffer == NULL ) return *this; - String theReturn = _buffer; - char* temp = theReturn._buffer; - while( (temp = strchr( temp, findChar )) != 0 ) - *temp = replaceChar; + unsigned int length = strlen_P((const prog_char *)pgmstr); + unsigned int newlen = len + length; + if (length == 0 || !reserve(newlen)) return *this; + strcpy_P(buffer + len, (const prog_char *)pgmstr); + len = newlen; + return *this; +} - return theReturn; +String & String::append(char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + append(buf, 1); + return *this; } -String String::replace( const String& match, const String& replace ) +String & String::append(int num) { - if ( _buffer == NULL ) return *this; - String temp = _buffer, newString; + char buf[7]; + itoa(num, buf, 10); + append(buf, strlen(buf)); + return *this; +} - int loc; - while ( (loc = temp.indexOf( match )) != -1 ) - { - newString += temp.substring( 0, loc ); - newString += replace; - temp = temp.substring( loc + match._length ); - } - newString += temp; - return newString; +String & String::append(unsigned int num) +{ + char buf[6]; + utoa(num, buf, 10); + append(buf, strlen(buf)); + return *this; } -int String::indexOf( char temp ) const +String & String::append(long num) { - return indexOf( temp, 0 ); + char buf[12]; + ltoa(num, buf, 10); + append(buf, strlen(buf)); + return *this; } -int String::indexOf( char ch, unsigned int fromIndex ) const +String & String::append(unsigned long num) { - if ( fromIndex >= _length ) - return -1; + char buf[11]; + ultoa(num, buf, 10); + append(buf, strlen(buf)); + return *this; +} - const char* temp = strchr( &_buffer[fromIndex], ch ); - if ( temp == NULL ) - return -1; +/*********************************************/ +/* Concatenate */ +/*********************************************/ - return temp - _buffer; +StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(rhs.buffer, rhs.len); + return a; } -int String::indexOf( const String &s2 ) const +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) { - return indexOf( s2, 0 ); + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + if (cstr) a.append(cstr, strlen(cstr)); + return a; } -int String::indexOf( const String &s2, unsigned int fromIndex ) const +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) { - if ( fromIndex >= _length ) - return -1; + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(pgmstr); + return a; +} - const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); +StringSumHelper & operator + (const StringSumHelper &lhs, char c) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(c); + return a; +} - if ( theFind == NULL ) - return -1; +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(c); + return a; +} - return theFind - _buffer; // pointer subtraction +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(num); + return a; } -int String::lastIndexOf( char theChar ) const +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) { - return lastIndexOf( theChar, _length - 1 ); + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(num); + return a; } -int String::lastIndexOf( char ch, unsigned int fromIndex ) const +StringSumHelper & operator + (const StringSumHelper &lhs, long num) { - if ( fromIndex >= _length ) - return -1; + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(num); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast<StringSumHelper&>(lhs); + a.append(num); + return a; +} - char tempchar = _buffer[fromIndex + 1]; - _buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( _buffer, ch ); - _buffer[fromIndex + 1] = tempchar; +/*********************************************/ +/* Comparison */ +/*********************************************/ - if ( temp == NULL ) - return -1; +int String::compareTo(const String &s) const +{ + if (!buffer || !s.buffer) { + if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, s.buffer); +} - return temp - _buffer; +unsigned char String::equals(const String &s2) const +{ + return (len == s2.len && compareTo(s2) == 0); } -int String::lastIndexOf( const String &s2 ) const +unsigned char String::equals(const char *cstr) const { - return lastIndexOf( s2, _length - s2._length ); + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; } -int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const +unsigned char String::equals(const __FlashStringHelper *pgmstr) const { - // check for empty strings - if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) - return -1; + if (len == 0) return pgm_read_byte(pgmstr) == 0; + return strcmp_P(buffer, (const prog_char *)pgmstr) == 0; +} - // matching first character - char temp = s2[ 0 ]; +unsigned char String::operator<(const String &rhs) const +{ + return compareTo(rhs) < 0; +} - for ( int i = fromIndex; i >= 0; i-- ) - { - if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) - return i; - } - return -1; +unsigned char String::operator>(const String &rhs) const +{ + return compareTo(rhs) > 0; } -boolean String::startsWith( const String &s2 ) const +unsigned char String::operator<=(const String &rhs) const { - if ( _length < s2._length ) - return 0; + return compareTo(rhs) <= 0; +} - return startsWith( s2, 0 ); +unsigned char String::operator>=(const String &rhs) const +{ + return compareTo(rhs) >= 0; } -boolean String::startsWith( const String &s2, unsigned int offset ) const +unsigned char String::equalsIgnoreCase( const String &s2 ) const { - if ( offset > _length - s2._length ) - return 0; + if (this == &s2) return 1; + if (len != s2.len) return 0; + if (len == 0) return 1; + const char *p1 = buffer; + const char *p2 = s2.buffer; + while (*p1) { + if (tolower(*p1++) != tolower(*p2++)) return 0; + } + return 1; +} - return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; +unsigned char String::startsWith( const String &s2 ) const +{ + if (len < s2.len) return 0; + return startsWith(s2, 0); } -String String::substring( unsigned int left ) const +unsigned char String::startsWith( const String &s2, unsigned int offset ) const { - return substring( left, _length ); + if (offset > len - s2.len || !buffer || !s2.buffer) return 0; + return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; } -String String::substring( unsigned int left, unsigned int right ) const +unsigned char String::endsWith( const String &s2 ) const { - if ( left > right ) - { - int temp = right; - right = left; - left = temp; - } + if ( len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; +} - if ( right > _length ) - { - right = _length; - } +/*********************************************/ +/* Character Access */ +/*********************************************/ - char temp = _buffer[ right ]; // save the replaced character - _buffer[ right ] = '\0'; - String outPut = ( _buffer + left ); // pointer arithmetic - _buffer[ right ] = temp; //restore character - return outPut; +char String::charAt(unsigned int loc) const +{ + return operator[](loc); } -String String::toLowerCase() const +void String::setCharAt(unsigned int loc, char c) { - String temp = _buffer; + if (loc < len) buffer[loc] = c; +} - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); - return temp; +char & String::operator[](unsigned int index) +{ + static char dummy_writable_char; + if (index >= len || !buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; } -String String::toUpperCase() const +char String::operator[]( unsigned int index ) const { - String temp = _buffer; + if (index >= len || !buffer) return 0; + return buffer[index]; +} - for ( unsigned int i = 0; i < _length; i++ ) - temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); - return temp; +void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const +{ + if (!bufsize || !buf) return; + if (index >= len) { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if (n > len - index) n = len - index; + strncpy((char *)buf, buffer + index, n); + buf[n] = 0; } -String String::trim() const +/*********************************************/ +/* Search */ +/*********************************************/ + +int String::indexOf(char c) const { - if ( _buffer == NULL ) return *this; - String temp = _buffer; - unsigned int i,j; + return indexOf(c, 0); +} - for ( i = 0; i < _length; i++ ) - { - if ( !isspace(_buffer[i]) ) - break; - } +int String::indexOf( char ch, unsigned int fromIndex ) const +{ + if (fromIndex >= len) return -1; + const char* temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; +} + +int String::indexOf(const String &s2) const +{ + return indexOf(s2, 0); +} - for ( j = temp._length - 1; j > i; j-- ) - { - if ( !isspace(_buffer[j]) ) - break; - } +int String::indexOf(const String &s2, unsigned int fromIndex) const +{ + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; +} - return temp.substring( i, j + 1); +int String::lastIndexOf( char theChar ) const +{ + return lastIndexOf(theChar, len - 1); } -void String::getBytes(unsigned char *buf, unsigned int bufsize) +int String::lastIndexOf(char ch, int fromIndex) const { - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy((char *)buf, _buffer, len); - buf[len] = 0; + if (fromIndex >= len || fromIndex < 0) return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char* temp = strrchr( buffer, ch ); + buffer[fromIndex + 1] = tempchar; + if (temp == NULL) return -1; + return temp - buffer; } -void String::toCharArray(char *buf, unsigned int bufsize) +int String::lastIndexOf(const String &s2) const { - if (!bufsize || !buf) return; - unsigned int len = bufsize - 1; - if (len > _length) len = _length; - strncpy(buf, _buffer, len); - buf[len] = 0; + return lastIndexOf(s2, len - s2.len); } +int String::lastIndexOf(const String &s2, int fromIndex) const +{ + if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1; + if (fromIndex >= len) fromIndex = len - 1; + int found = -1; + for (char *p = buffer; p <= buffer + fromIndex; p++) { + p = strstr(p, s2.buffer); + if (!p) break; + if (p - buffer <= fromIndex) found = p - buffer; + } + return found; +} -long String::toInt() { - return atol(_buffer); +String String::substring( unsigned int left ) const +{ + return substring(left, len); +} + +String String::substring(unsigned int left, unsigned int right) const +{ + if (left > right) { + unsigned int temp = right; + right = left; + left = temp; + } + String out; + if (left > len) return out; + if (right > len) right = len; + char temp = buffer[right]; // save the replaced character + buffer[right] = '\0'; + out = buffer + left; // pointer arithmetic + buffer[right] = temp; //restore character + return out; +} + +/*********************************************/ +/* Modification */ +/*********************************************/ + +String & String::replace(char find, char replace) +{ + if (!buffer) return *this; + for (char *p = buffer; *p; p++) { + if (*p == find) *p = replace; + } + return *this; +} + +String & String::replace(const String& find, const String& replace) +{ + if (len == 0 || find.len == 0) return *this; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if (diff == 0) { + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } else if (diff < 0) { + char *writeTo = buffer; + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } else { + unsigned int size = len; // compute size needed for result + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { + readFrom = foundAt + find.len; + size += diff; + } + if (size == len) return *this; + if (size > capacity && !changeBuffer(size)) return *this; + int index = len - 1; + while ((index = lastIndexOf(find, index)) >= 0) { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } + return *this; +} + +String & String::toLowerCase(void) +{ + if (!buffer) return *this; + for (char *p = buffer; *p; p++) { + *p = tolower(*p); + } + return *this; +} + +String & String::toUpperCase(void) +{ + if (!buffer) return *this; + for (char *p = buffer; *p; p++) { + *p = toupper(*p); + } + return *this; +} + +String & String::trim(void) +{ + if (!buffer || len == 0) return *this; + char *begin = buffer; + while (isspace(*begin)) begin++; + char *end = buffer + len - 1; + while (isspace(*end) && end >= begin) end--; + len = end + 1 - begin; + if (begin > buffer) memcpy(buffer, begin, len); + buffer[len] = 0; + return *this; +} + +/*********************************************/ +/* Parsing / Conversion */ +/*********************************************/ + +long String::toInt(void) const +{ + if (buffer) return atol(buffer); + return 0; } + + diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h index ff671d8..541a118 100644 --- a/cores/arduino/WString.h +++ b/cores/arduino/WString.h @@ -1,6 +1,8 @@ /* WString.h - String library for Wiring & Arduino + ...mostly rewritten by Paul Stoffregen... Copyright (c) 2009-10 Hernando Barragan. All right reserved. + Copyright 2011, Paul Stoffregen, paul@pjrc.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,96 +19,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef String_h -#define String_h +#ifndef String_class_h +#define String_class_h +#ifdef __cplusplus -//#include "Arduino.h" #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <avr/pgmspace.h> +// When compiling programs with this class, the following gcc parameters +// dramatically increase performance and memory (RAM) efficiency, typically +// with little or no increase in code size. +// -felide-constructors +// -std=c++0x + +// Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010) +// modified by Mikal Hart for his FlashString library +class __FlashStringHelper; +#ifndef F +#define F(string_literal) (reinterpret_cast<__FlashStringHelper *>(PSTR(string_literal))) +#endif + +// An inherited class for holding the result of a concatenation. These +// result objects are assumed to be writable by subsequent concatenations. +class StringSumHelper; + +// The string class class String { - public: - // constructors - String( const char *value = "" ); - String( const String &value ); - String( const char ); - String( const unsigned char ); - String( const int, const int base=10); - String( const unsigned int, const int base=10 ); - String( const long, const int base=10 ); - String( const unsigned long, const int base=10 ); - ~String() { free(_buffer); _length = _capacity = 0;} //added _length = _capacity = 0; - - // operators - const String & operator = ( const String &rhs ); - const String & operator +=( const String &rhs ); - //const String & operator +=( const char ); - int operator ==( const String &rhs ) const; - int operator !=( const String &rhs ) const; - int operator < ( const String &rhs ) const; - int operator > ( const String &rhs ) const; - int operator <=( const String &rhs ) const; - int operator >=( const String &rhs ) const; - char operator []( unsigned int index ) const; - char& operator []( unsigned int index ); - //operator const char *() const { return _buffer; } - - // general methods - char charAt( unsigned int index ) const; - int compareTo( const String &anotherString ) const; - unsigned char endsWith( const String &suffix ) const; - unsigned char equals( const String &anObject ) const; - unsigned char equalsIgnoreCase( const String &anotherString ) const; - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - const unsigned int length( ) const { return _length; } - void setCharAt(unsigned int index, const char ch); - unsigned char startsWith( const String &prefix ) const; - unsigned char startsWith( const String &prefix, unsigned int toffset ) const; - String substring( unsigned int beginIndex ) const; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - String toLowerCase( ) const; - String toUpperCase( ) const; - String trim( ) const; - void getBytes(unsigned char *buf, unsigned int bufsize); - void toCharArray(char *buf, unsigned int bufsize); - long toInt( ); - const String& concat( const String &str ); - String replace( char oldChar, char newChar ); - String replace( const String& match, const String& replace ); - friend String operator + ( String lhs, const String &rhs ); - - protected: - char *_buffer; // the actual char array - unsigned int _capacity; // the array length minus one (for the '\0') - unsigned int _length; // the String length (not counting the '\0') - - void getBuffer(unsigned int maxStrLen); - - private: +public: + // constructors + String(const char *cstr = NULL); + String(const __FlashStringHelper *pgmstr); + String(const String &str); + #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String(String &&rval); + String(StringSumHelper &&rval); + #endif + String(char c); + String(unsigned char c); + String(int, unsigned char base=10); + String(unsigned int, unsigned char base=10); + String(long, unsigned char base=10); + String(unsigned long, unsigned char base=10); + ~String(void); -}; + // memory management + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const {return len;} -// allocate buffer space -inline void String::getBuffer(unsigned int maxStrLen) -{ - _capacity = maxStrLen; - _buffer = (char *) malloc(_capacity + 1); - if (_buffer == NULL) _length = _capacity = 0; -} + // copy and move + String & copy(const char *cstr, unsigned int length); + String & copy(const __FlashStringHelper *pgmstr); + void move(String &rhs); + String & operator = (const String &rhs); + String & operator = (const char *cstr); + String & operator = (const __FlashStringHelper *pgmstr); + #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String & operator = (String &&rval); + String & operator = (StringSumHelper &&rval); + #endif + String & operator = (char c); -inline String operator+( String lhs, const String &rhs ) -{ - return lhs += rhs; -} + // append + String & append(const String &str); + String & append(const char *cstr); + String & append(const __FlashStringHelper *pgmstr); + String & append(char c); + String & append(unsigned char c) {return append((char)c);} + String & append(int num); + String & append(unsigned int num); + String & append(long num); + String & append(unsigned long num); + String & operator += (const String &rhs) {return append(rhs);} + String & operator += (const char *cstr) {return append(cstr);} + String & operator += (const __FlashStringHelper *pgmstr) {return append(pgmstr);} + String & operator += (char c) {return append(c);} + String & operator += (unsigned char c) {return append((char)c);} + String & operator += (int num) {return append(num);} + String & operator += (unsigned int num) {return append(num);} + String & operator += (long num) {return append(num);} + String & operator += (unsigned long num) {return append(num);} + // concatenate + friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr); + friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c); + friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); -#endif + // comparison + int compareTo(const String &s) const; + unsigned char equals(const String &s) const; + unsigned char equals(const char *cstr) const; + unsigned char equals(const __FlashStringHelper *pgmstr) const; + unsigned char operator == (const String &rhs) const {return equals(rhs);} + unsigned char operator == (const char *cstr) const {return equals(cstr);} + unsigned char operator == (const __FlashStringHelper *pgmstr) const {return equals(pgmstr);} + unsigned char operator != (const String &rhs) const {return !equals(rhs);} + unsigned char operator != (const char *cstr) const {return !equals(cstr);} + unsigned char operator != (const __FlashStringHelper *pgmstr) const {return !equals(pgmstr);} + unsigned char operator < (const String &rhs) const; + unsigned char operator > (const String &rhs) const; + unsigned char operator <= (const String &rhs) const; + unsigned char operator >= (const String &rhs) const; + unsigned char equalsIgnoreCase(const String &s) const; + unsigned char startsWith( const String &prefix) const; + unsigned char startsWith(const String &prefix, unsigned int offset) const; + unsigned char endsWith(const String &suffix) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator [] (unsigned int index) const; + char& operator [] (unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const + {getBytes((unsigned char *)buf, bufsize, index);} + + // search + int indexOf( char ch ) const; + int indexOf( char ch, unsigned int fromIndex ) const; + int indexOf( const String &str ) const; + int indexOf( const String &str, unsigned int fromIndex ) const; + int lastIndexOf( char ch ) const; + int lastIndexOf( char ch, int fromIndex ) const; + int lastIndexOf( const String &str ) const; + int lastIndexOf( const String &str, int fromIndex ) const; + String substring( unsigned int beginIndex ) const; + String substring( unsigned int beginIndex, unsigned int endIndex ) const; + + // modification + String & replace(char find, char replace); + String & replace(const String& find, const String& replace); + String & toLowerCase(void); + String & toUpperCase(void); + String & trim(void); + + // parsing/conversion + long toInt(void) const; + +protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') + unsigned char flags; // unused, for future features +protected: + void init(void); + unsigned char changeBuffer(unsigned int maxStrLen); + String & append(const char *cstr, unsigned int length); +}; + +class StringSumHelper : public String +{ +public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(const __FlashStringHelper *pgmstr) : String(pgmstr) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char c) : String(c) {} + StringSumHelper(int num) : String(num, 10) {} + StringSumHelper(unsigned int num) : String(num, 10) {} + StringSumHelper(long num) : String(num, 10) {} + StringSumHelper(unsigned long num) : String(num, 10) {} +}; + +#endif // __cplusplus +#endif // String_class_h |