You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					444 lines
				
				9.3 KiB
			
		
		
			
		
	
	
					444 lines
				
				9.3 KiB
			|   
											14 years ago
										 | /*
 | ||
|  |   WString.cpp - String library for Wiring & Arduino | ||
|  |   Copyright (c) 2009-10 Hernando Barragan.  All rights reserved. | ||
|  | 
 | ||
|  |   This library is free software; you can redistribute it and/or | ||
|  |   modify it under the terms of the GNU Lesser General Public | ||
|  |   License as published by the Free Software Foundation; either | ||
|  |   version 2.1 of the License, or (at your option) any later version. | ||
|  | 
 | ||
|  |   This library is distributed in the hope that it will be useful, | ||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||
|  |   Lesser General Public License for more details. | ||
|  | 
 | ||
|  |   You should have received a copy of the GNU Lesser General Public | ||
|  |   License along with this library; if not, write to the Free Software | ||
|  |   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||
|  | */ | ||
|  | 
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include "WProgram.h"
 | ||
|  | #include "WString.h"
 | ||
|  | 
 | ||
|  | 
 | ||
|  | String::String( const char *value ) | ||
|  | { | ||
|  |   if ( value == NULL ) | ||
|  |     value = ""; | ||
|  |   getBuffer( _length = strlen( value ) ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, value ); | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const String &value ) | ||
|  | { | ||
|  |   getBuffer( _length = value._length ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, value._buffer ); | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const char value ) | ||
|  | { | ||
|  |   _length = 1; | ||
|  |   getBuffer(1); | ||
|  |   if ( _buffer != NULL ) { | ||
|  |     _buffer[0] = value; | ||
|  |     _buffer[1] = 0; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const unsigned char value ) | ||
|  | { | ||
|  |   _length = 1; | ||
|  |   getBuffer(1); | ||
|  |   if ( _buffer != NULL) { | ||
|  |     _buffer[0] = value; | ||
|  |     _buffer[1] = 0; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const int value, const int base ) | ||
|  | { | ||
|  |   char buf[33];    | ||
|  |   itoa((signed long)value, buf, base); | ||
|  |   getBuffer( _length = strlen(buf) ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, buf ); | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const unsigned int value, const int base ) | ||
|  | { | ||
|  |   char buf[33];    | ||
|  |   ultoa((unsigned long)value, buf, base); | ||
|  |   getBuffer( _length = strlen(buf) ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, buf ); | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const long value, const int base ) | ||
|  | { | ||
|  |   char buf[33];    | ||
|  |   ltoa(value, buf, base); | ||
|  |   getBuffer( _length = strlen(buf) ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, buf ); | ||
|  | } | ||
|  | 
 | ||
|  | String::String( const unsigned long value, const int base ) | ||
|  | { | ||
|  |   char buf[33];    | ||
|  |   ultoa(value, buf, 10); | ||
|  |   getBuffer( _length = strlen(buf) ); | ||
|  |   if ( _buffer != NULL ) | ||
|  |     strcpy( _buffer, buf ); | ||
|  | } | ||
|  | 
 | ||
|  | char String::charAt( unsigned int loc ) const | ||
|  | { | ||
|  |   return operator[]( loc ); | ||
|  | } | ||
|  | 
 | ||
|  | void String::setCharAt( unsigned int loc, const char aChar )  | ||
|  | { | ||
|  |   if(_buffer == NULL) return; | ||
|  |   if(_length > loc) { | ||
|  |     _buffer[loc] = aChar; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | int String::compareTo( const String &s2 ) const | ||
|  | { | ||
|  |   return strcmp( _buffer, s2._buffer ); | ||
|  | } | ||
|  | 
 | ||
|  | const String & String::concat( const String &s2 ) | ||
|  | { | ||
|  |   return (*this) += s2; | ||
|  | } | ||
|  | 
 | ||
|  | const String & String::operator=( const String &rhs ) | ||
|  | { | ||
|  |   if ( this == &rhs ) | ||
|  |     return *this; | ||
|  | 
 | ||
|  |   if ( rhs._length > _length ) | ||
|  |   { | ||
|  |     free(_buffer); | ||
|  |     getBuffer( rhs._length ); | ||
|  |   } | ||
|  |    | ||
|  |   if ( _buffer != NULL ) { | ||
|  |     _length = rhs._length; | ||
|  |     strcpy( _buffer, rhs._buffer ); | ||
|  |   } | ||
|  |   return *this; | ||
|  | } | ||
|  | 
 | ||
|  | //const String & String::operator+=( const char aChar )
 | ||
|  | //{
 | ||
|  | //  if ( _length == _capacity )
 | ||
|  | //    doubleBuffer();
 | ||
|  | //
 | ||
|  | //  _buffer[ _length++ ] = aChar;
 | ||
|  | //  _buffer[ _length ] = '\0';
 | ||
|  | //  return *this;
 | ||
|  | //}
 | ||
|  | 
 | ||
|  | const String & String::operator+=( const String &other ) | ||
|  | { | ||
|  |   _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; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | int String::operator==( const String &rhs ) const | ||
|  | { | ||
|  |   return ( _length == rhs._length && strcmp( _buffer, rhs._buffer ) == 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::operator!=( const String &rhs ) const | ||
|  | { | ||
|  |   return ( _length != rhs.length() || strcmp( _buffer, rhs._buffer ) != 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::operator<( const String &rhs ) const | ||
|  | { | ||
|  |   return strcmp( _buffer, rhs._buffer ) < 0; | ||
|  | } | ||
|  | 
 | ||
|  | int String::operator>( const String &rhs ) const | ||
|  | { | ||
|  |   return strcmp( _buffer, rhs._buffer ) > 0; | ||
|  | } | ||
|  | 
 | ||
|  | int String::operator<=( const String &rhs ) const | ||
|  | { | ||
|  |   return strcmp( _buffer, rhs._buffer ) <= 0; | ||
|  | } | ||
|  | 
 | ||
|  | int String::operator>=( const String & rhs ) const | ||
|  | { | ||
|  |   return strcmp( _buffer, rhs._buffer ) >= 0; | ||
|  | } | ||
|  | 
 | ||
|  | char & String::operator[]( unsigned int index ) | ||
|  | { | ||
|  |   static char dummy_writable_char; | ||
|  |   if (index >= _length || !_buffer) { | ||
|  |     dummy_writable_char = 0; | ||
|  |     return dummy_writable_char; | ||
|  |   } | ||
|  |   return _buffer[ index ]; | ||
|  | } | ||
|  | 
 | ||
|  | char String::operator[]( unsigned int index ) const | ||
|  | { | ||
|  |   // need to check for valid index, to do later
 | ||
|  |   return _buffer[ index ]; | ||
|  | } | ||
|  | 
 | ||
|  | boolean String::endsWith( const String &s2 ) const | ||
|  | { | ||
|  |   if ( _length < s2._length ) | ||
|  |     return 0; | ||
|  | 
 | ||
|  |   return strcmp( &_buffer[ _length - s2._length], s2._buffer ) == 0; | ||
|  | } | ||
|  | 
 | ||
|  | boolean String::equals( const String &s2 ) const | ||
|  | { | ||
|  |   return ( _length == s2._length && strcmp( _buffer,s2._buffer ) == 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | boolean String::equalsIgnoreCase( const String &s2 ) const | ||
|  | { | ||
|  |   if ( this == &s2 ) | ||
|  |     return true; //1;
 | ||
|  |   else if ( _length != s2._length ) | ||
|  |     return false; //0;
 | ||
|  | 
 | ||
|  |   return strcmp(toLowerCase()._buffer, s2.toLowerCase()._buffer) == 0; | ||
|  | } | ||
|  | 
 | ||
|  | String String::replace( char findChar, char replaceChar ) | ||
|  | { | ||
|  |   if ( _buffer == NULL ) return *this; | ||
|  |   String theReturn = _buffer; | ||
|  |   char* temp = theReturn._buffer; | ||
|  |   while( (temp = strchr( temp, findChar )) != 0 ) | ||
|  |     *temp = replaceChar; | ||
|  | 
 | ||
|  |   return theReturn; | ||
|  | } | ||
|  | 
 | ||
|  | String String::replace( const String& match, const String& replace ) | ||
|  | { | ||
|  |   if ( _buffer == NULL ) return *this; | ||
|  |   String temp = _buffer, newString; | ||
|  | 
 | ||
|  |   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; | ||
|  | } | ||
|  | 
 | ||
|  | int String::indexOf( char temp ) const | ||
|  | { | ||
|  |   return indexOf( temp, 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::indexOf( char ch, unsigned int fromIndex ) const | ||
|  | { | ||
|  |   if ( fromIndex >= _length ) | ||
|  |     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 ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::indexOf( const String &s2, unsigned int fromIndex ) const | ||
|  | { | ||
|  |   if ( fromIndex >= _length ) | ||
|  |     return -1; | ||
|  | 
 | ||
|  |   const char *theFind = strstr( &_buffer[ fromIndex ], s2._buffer ); | ||
|  | 
 | ||
|  |   if ( theFind == NULL ) | ||
|  |     return -1; | ||
|  | 
 | ||
|  |   return theFind - _buffer; // pointer subtraction
 | ||
|  | } | ||
|  | 
 | ||
|  | int String::lastIndexOf( char theChar ) const | ||
|  | { | ||
|  |   return lastIndexOf( theChar, _length - 1 ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::lastIndexOf( char ch, unsigned int fromIndex ) const | ||
|  | { | ||
|  |   if ( fromIndex >= _length ) | ||
|  |     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; | ||
|  | } | ||
|  | 
 | ||
|  | int String::lastIndexOf( const String &s2 ) const | ||
|  | { | ||
|  |   return lastIndexOf( s2, _length - s2._length ); | ||
|  | } | ||
|  | 
 | ||
|  | int String::lastIndexOf( const String &s2, unsigned int fromIndex ) const | ||
|  | { | ||
|  |   // check for empty strings
 | ||
|  |   if ( s2._length == 0 || s2._length - 1 > fromIndex || fromIndex >= _length ) | ||
|  |     return -1; | ||
|  | 
 | ||
|  |   // matching first character
 | ||
|  |   char temp = s2[ 0 ]; | ||
|  | 
 | ||
|  |   for ( int i = fromIndex; i >= 0; i-- ) | ||
|  |   { | ||
|  |     if ( _buffer[ i ] == temp && (*this).substring( i, i + s2._length ).equals( s2 ) ) | ||
|  |     return i; | ||
|  |   } | ||
|  |   return -1; | ||
|  | } | ||
|  | 
 | ||
|  | boolean String::startsWith( const String &s2 ) const | ||
|  | { | ||
|  |   if ( _length < s2._length ) | ||
|  |     return 0; | ||
|  | 
 | ||
|  |   return startsWith( s2, 0 ); | ||
|  | } | ||
|  | 
 | ||
|  | boolean String::startsWith( const String &s2, unsigned int offset ) const | ||
|  | { | ||
|  |   if ( offset > _length - s2._length ) | ||
|  |     return 0; | ||
|  | 
 | ||
|  |   return strncmp( &_buffer[offset], s2._buffer, s2._length ) == 0; | ||
|  | } | ||
|  | 
 | ||
|  | String String::substring( unsigned int left ) const | ||
|  | { | ||
|  |   return substring( left, _length ); | ||
|  | } | ||
|  | 
 | ||
|  | String String::substring( unsigned int left, unsigned int right ) const | ||
|  | { | ||
|  |   if ( left > right ) | ||
|  |   { | ||
|  |     int temp = right; | ||
|  |     right = left; | ||
|  |     left = temp; | ||
|  |   } | ||
|  | 
 | ||
|  |   if ( right > _length ) | ||
|  |   { | ||
|  |     right = _length; | ||
|  |   }  | ||
|  | 
 | ||
|  |   char temp = _buffer[ right ];  // save the replaced character
 | ||
|  |   _buffer[ right ] = '\0';	 | ||
|  |   String outPut = ( _buffer + left );  // pointer arithmetic
 | ||
|  |   _buffer[ right ] = temp;  //restore character
 | ||
|  |   return outPut; | ||
|  | } | ||
|  | 
 | ||
|  | String String::toLowerCase() const | ||
|  | { | ||
|  |   String temp = _buffer; | ||
|  | 
 | ||
|  |   for ( unsigned int i = 0; i < _length; i++ ) | ||
|  |     temp._buffer[ i ] = (char)tolower( temp._buffer[ i ] ); | ||
|  |   return temp; | ||
|  | } | ||
|  | 
 | ||
|  | String String::toUpperCase() const | ||
|  | { | ||
|  |   String temp = _buffer; | ||
|  | 
 | ||
|  |   for ( unsigned int i = 0; i < _length; i++ ) | ||
|  |     temp._buffer[ i ] = (char)toupper( temp._buffer[ i ] ); | ||
|  |   return temp; | ||
|  | } | ||
|  | 
 | ||
|  | String String::trim() const | ||
|  | { | ||
|  |   if ( _buffer == NULL ) return *this; | ||
|  |   String temp = _buffer; | ||
|  |   unsigned int i,j; | ||
|  | 
 | ||
|  |   for ( i = 0; i < _length; i++ ) | ||
|  |   { | ||
|  |     if ( !isspace(_buffer[i]) ) | ||
|  |       break; | ||
|  |   } | ||
|  | 
 | ||
|  |   for ( j = temp._length - 1; j > i; j-- ) | ||
|  |   { | ||
|  |     if ( !isspace(_buffer[j]) ) | ||
|  |       break; | ||
|  |   } | ||
|  | 
 | ||
|  |   return temp.substring( i, j + 1); | ||
|  | } | ||
|  | 
 | ||
|  | void String::getBytes(unsigned char *buf, unsigned int bufsize) | ||
|  | { | ||
|  |   if (!bufsize || !buf) return; | ||
|  |   unsigned int len = bufsize - 1; | ||
|  |   if (len > _length) len = _length; | ||
|  |   strncpy((char *)buf, _buffer, len); | ||
|  |   buf[len] = 0; | ||
|  | } | ||
|  | 
 | ||
|  | void String::toCharArray(char *buf, unsigned int bufsize) | ||
|  | { | ||
|  |   if (!bufsize || !buf) return; | ||
|  |   unsigned int len = bufsize - 1; | ||
|  |   if (len > _length) len = _length; | ||
|  |   strncpy(buf, _buffer, len); | ||
|  |   buf[len] = 0; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | long String::toInt() { | ||
|  |   return atol(_buffer); | ||
|  | } |