1/* 2 WString.cpp - String library for Wiring & Arduino 3 Copyright (c) 2009-10 Hernando Barragan. All rights reserved. 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18*/ 19 20#include <stdlib.h> 21#include "WProgram.h" 22#include "WString.h" 23 24 25String::String( const char *value ) 26{ 27 if ( value == NULL ) 28 value = ""; 29 getBuffer( _length = strlen( value ) ); 30 if ( _buffer != NULL ) 31 strcpy( _buffer, value ); 32} 33 34String::String( const String &value ) 35{ 36 getBuffer( _length = value._length ); 37 if ( _buffer != NULL ) 38 strcpy( _buffer, value._buffer ); 39} 40 41String::String( const char value ) 42{ 43 _length = 1; 44 getBuffer(1); 45 if ( _buffer != NULL ) { 46 _buffer[0] = value; 47 _buffer[1] = 0; 48 } 49} 50 51String::String( const unsigned char value ) 52{ 53 _length = 1; 54 getBuffer(1); 55 if ( _buffer != NULL) { 56 _buffer[0] = value; 57 _buffer[1] = 0; 58 } 59} 60 61String::String( const int value, const int base ) 62{ 63 char buf[33]; 64 itoa((signed long)value, buf, base); 65 getBuffer( _length = strlen(buf) ); 66 if ( _buffer != NULL ) 67 strcpy( _buffer, buf ); 68} 69 70String::String( const unsigned int value, const int base ) 71{ 72 char buf[33]; 73 ultoa((unsigned long)value, buf, base); 74 getBuffer( _length = strlen(buf) ); 75 if ( _buffer != NULL ) 76 strcpy( _buffer, buf ); 77} 78 79String::String( const long value, const int base ) 80{ 81 char buf[33]; 82 ltoa(value, buf, base); 83 getBuffer( _length = strlen(buf) ); 84 if ( _buffer != NULL ) 85 strcpy( _buffer, buf ); 86} 87 88String::String( const unsigned long value, const int base ) 89{ 90 char buf[33]; 91 ultoa(value, buf, 10); 92 getBuffer( _length = strlen(buf) ); 93 if ( _buffer != NULL ) 94 strcpy( _buffer, buf ); 95} 96 97char String::charAt( unsigned int loc ) const 98{ 99 return operator[]( loc ); 100} 101 102void String::setCharAt( unsigned int loc, const char aChar ) 103{ 104 if(_buffer == NULL) return; 105 if(_length > loc) { 106 _buffer[loc] = aChar; 107 } 108} 109 110int String::compareTo( const String &s2 ) const 111{ 112 return strcmp( _buffer, s2._buffer ); 113} 114 115const String & String::concat( const String &s2 ) 116{ 117 return (*this) += s2; 118} 119 120const String & String::operator=( const String &rhs ) 121{ 122 if ( this == &rhs ) 123 return *this; 124 125 if ( rhs._length > _length ) 126 { 127 free(_buffer); 128 getBuffer( rhs._length ); 129 } 130 131 if ( _buffer != NULL ) { 132 _length = rhs._length; 133 strcpy( _buffer, rhs._buffer ); 134 } 135 return *this; 136} 137 138//const String & String::operator+=( const char aChar ) 139//{ 140// if ( _length == _capacity ) 141// doubleBuffer(); 142// 143// _buffer[ _length++ ] = aChar; 144// _buffer[ _length ] = '\0'; 145// return *this; 146//} 147 148const String & String::operator+=( const String &other ) 149{ 150 _length += other._length; 151 if ( _length > _capacity ) 152 { 153 char *temp = (char *)realloc(_buffer, _length + 1); 154 if ( temp != NULL ) { 155 _buffer = temp; 156 _capacity = _length; 157 } else { 158 _length -= other._length; 159 return *this; 160 } 161 } 162 strcat( _buffer, other._buffer ); 163 return *this; 164} 165 166 167int String::operator==( const String &rhs ) const 168{ 169 return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); 170} 171 172int String::operator!=( const String &rhs ) const 173{ 174 return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); 175} 176 177int String::operator<( const String &rhs ) const 178{ 179 return strcmp( _buffer, rhs._buffer ) < 0; 180} 181 182int String::operator>( const String &rhs ) const 183{ 184 return strcmp( _buffer, rhs._buffer ) > 0; 185} 186 187int String::operator<=( const String &rhs ) const 188{ 189 return strcmp( _buffer, rhs._buffer ) <= 0; 190} 191 192int String::operator>=( const String & rhs ) const 193{ 194 return strcmp( _buffer, rhs._buffer ) >= 0; 195} 196 197char & String::operator[]( unsigned int index ) 198{ 199 static char dummy_writable_char; 200 if (index >= _length || !_buffer) { 201 dummy_writable_char = 0; 202 return dummy_writable_char; 203 } 204 return _buffer[ index ]; 205} 206 207char String::operator[]( unsigned int index ) const 208{ 209 // need to check for valid index, to do later 210 return _buffer[ index ]; 211} 212 213boolean String::endsWith( const String &s2 ) const 214{ 215 if ( _length < s2._length ) 216 return 0; 217 218 return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; 219} 220 221boolean String::equals( const String &s2 ) const 222{ 223 return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); 224} 225 226boolean String::equalsIgnoreCase( const String &s2 ) const 227{ 228 if ( this == &s2 ) 229 return true; //1; 230 else if ( _length != s2._length ) 231 return false; //0; 232 233 return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; 234} 235 236String String::replace( char findChar, char replaceChar ) 237{ 238 if ( _buffer == NULL ) return *this; 239 String theReturn = _buffer; 240 char* temp = theReturn._buffer; 241 while( (temp = strchr( temp, findChar )) != 0 ) 242 *temp = replaceChar; 243 244 return theReturn; 245} 246 247String String::replace( const String& match, const String& replace ) 248{ 249 if ( _buffer == NULL ) return *this; 250 String temp = _buffer, newString; 251 252 int loc; 253 while ( (loc = temp.indexOf( match )) != -1 ) 254 { 255 newString += temp.substring( 0, loc ); 256 newString += replace; 257 temp = temp.substring( loc + match._length ); 258 } 259 newString += temp; 260 return newString; 261} 262 263int String::indexOf( char temp ) const 264{ 265 return indexOf( temp, 0 ); 266} 267 268int String::indexOf( char ch, unsigned int fromIndex ) const 269{ 270 if ( fromIndex >= _length ) 271 return -1; 272 273 const char* temp = strchr( &_buffer[fromIndex], ch ); 274 if ( temp == NULL ) 275 return -1; 276 277 return temp - _buffer; 278} 279 280int String::indexOf( const String &s2 ) const 281{ 282 return indexOf( s2, 0 ); 283} 284 285int String::indexOf( const String &s2, unsigned int fromIndex ) const 286{ 287 if ( fromIndex >= _length ) 288 return -1; 289 290 const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); 291 292 if ( theFind == NULL ) 293 return -1; 294 295 return theFind - _buffer; // pointer subtraction 296} 297 298int String::lastIndexOf( char theChar ) const 299{ 300 return lastIndexOf( theChar, _length - 1 ); 301} 302 303int String::lastIndexOf( char ch, unsigned int fromIndex ) const 304{ 305 if ( fromIndex >= _length ) 306 return -1; 307 308 char tempchar = _buffer[fromIndex + 1]; 309 _buffer[fromIndex + 1] = '\0'; 310 char* temp = strrchr( _buffer, ch ); 311 _buffer[fromIndex + 1] = tempchar; 312 313 if ( temp == NULL ) 314 return -1; 315 316 return temp - _buffer; 317} 318 319int String::lastIndexOf( const String &s2 ) const 320{ 321 return lastIndexOf( s2, _length - s2._length ); 322} 323 324int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const 325{ 326 // check for empty strings 327 if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) 328 return -1; 329 330 // matching first character 331 char temp = s2[ 0 ]; 332 333 for ( int i = fromIndex; i >= 0; i-- ) 334 { 335 if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) 336 return i; 337 } 338 return -1; 339} 340 341boolean String::startsWith( const String &s2 ) const 342{ 343 if ( _length < s2._length ) 344 return 0; 345 346 return startsWith( s2, 0 ); 347} 348 349boolean String::startsWith( const String &s2, unsigned int offset ) const 350{ 351 if ( offset > _length - s2._length ) 352 return 0; 353 354 return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; 355} 356 357String String::substring( unsigned int left ) const 358{ 359 return substring( left, _length ); 360} 361 362String String::substring( unsigned int left, unsigned int right ) const 363{ 364 if ( left > right ) 365 { 366 int temp = right; 367 right = left; 368 left = temp; 369 } 370 371 if ( right > _length ) 372 { 373 right = _length; 374 } 375 376 char temp = _buffer[ right ]; // save the replaced character 377 _buffer[ right ] = '\0'; 378 String outPut = ( _buffer + left ); // pointer arithmetic 379 _buffer[ right ] = temp; //restore character 380 return outPut; 381} 382 383String String::toLowerCase() const 384{ 385 String temp = _buffer; 386 387 for ( unsigned int i = 0; i < _length; i++ ) 388 temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); 389 return temp; 390} 391 392String String::toUpperCase() const 393{ 394 String temp = _buffer; 395 396 for ( unsigned int i = 0; i < _length; i++ ) 397 temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); 398 return temp; 399} 400 401String String::trim() const 402{ 403 if ( _buffer == NULL ) return *this; 404 String temp = _buffer; 405 unsigned int i,j; 406 407 for ( i = 0; i < _length; i++ ) 408 { 409 if ( !isspace(_buffer[i]) ) 410 break; 411 } 412 413 for ( j = temp._length - 1; j > i; j-- ) 414 { 415 if ( !isspace(_buffer[j]) ) 416 break; 417 } 418 419 return temp.substring( i, j + 1); 420} 421 422void String::getBytes(unsigned char *buf, unsigned int bufsize) 423{ 424 if (!bufsize || !buf) return; 425 unsigned int len = bufsize - 1; 426 if (len > _length) len = _length; 427 strncpy((char *)buf, _buffer, len); 428 buf[len] = 0; 429} 430 431void String::toCharArray(char *buf, unsigned int bufsize) 432{ 433 if (!bufsize || !buf) return; 434 unsigned int len = bufsize - 1; 435 if (len > _length) len = _length; 436 strncpy(buf, _buffer, len); 437 buf[len] = 0; 438} 439 440 441long String::toInt() { 442 return atol(_buffer); 443} 444