aboutsummaryrefslogtreecommitdiff
path: root/cores/arduino/WString.cpp
diff options
context:
space:
mode:
authorDavid A. Mellis <d.mellis@arduino.cc>2011-03-11 17:56:10 -0500
committerDavid A. Mellis <d.mellis@arduino.cc>2011-03-11 17:56:10 -0500
commit438bca3cb270b0d882b6b3b0bc42d57d72307c76 (patch)
tree6ae4bde98e9b0b46e9917b8d27a5b87fe12bb8b4 /cores/arduino/WString.cpp
parentba3d26dcaee4245912e49125b847d29a771bd08b (diff)
Rewrite of the String class by Paul Stoffregen.
http://www.pjrc.com/teensy/string_class_experimental.html
Diffstat (limited to 'cores/arduino/WString.cpp')
-rw-r--r--cores/arduino/WString.cpp783
1 files changed, 519 insertions, 264 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;
}
+
+