| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  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 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |  Modified by Ivan Grokhotkov, 2014 - esp8266 support | 
					
						
							|  |  |  |  Modified by Michael C. Miller, 2015 - esp8266 progmem support | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |  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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | #include <Arduino.h>
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | #include "WString.h"
 | 
					
						
							|  |  |  | #include "stdlib_noniso.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************/ | 
					
						
							|  |  |  | /*  Constructors                             */ | 
					
						
							|  |  |  | /*********************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(const char *cstr) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(cstr) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         copy(cstr, strlen(cstr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(const String &value) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     *this = value; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(const __FlashStringHelper *pstr) { | 
					
						
							|  |  |  |     init(); | 
					
						
							|  |  |  |     *this = pstr; // see operator =
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | #ifdef __GXX_EXPERIMENTAL_CXX0X__
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(String &&rval) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     move(rval); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(StringSumHelper &&rval) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     move(rval); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(char c) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[2]; | 
					
						
							|  |  |  |     buf[0] = c; | 
					
						
							|  |  |  |     buf[1] = 0; | 
					
						
							|  |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(unsigned char value, unsigned char base) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[1 + 8 * sizeof(unsigned char)]; | 
					
						
							|  |  |  |     utoa(value, buf, base); | 
					
						
							|  |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(int value, unsigned char base) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[2 + 8 * sizeof(int)]; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if (base == 10) { | 
					
						
							|  |  |  |         sprintf(buf, "%d", value); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         itoa(value, buf, base); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(unsigned int value, unsigned char base) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[1 + 8 * sizeof(unsigned int)]; | 
					
						
							|  |  |  |     utoa(value, buf, base); | 
					
						
							|  |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(long value, unsigned char base) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[2 + 8 * sizeof(long)]; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if (base==10) { | 
					
						
							|  |  |  |         sprintf(buf, "%ld", value); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ltoa(value, buf, base); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(unsigned long value, unsigned char base) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[1 + 8 * sizeof(unsigned long)]; | 
					
						
							|  |  |  |     ultoa(value, buf, base); | 
					
						
							|  |  |  |     *this = buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(float value, unsigned char decimalPlaces) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[33]; | 
					
						
							|  |  |  |     *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::String(double value, unsigned char decimalPlaces) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  |     char buf[33]; | 
					
						
							|  |  |  |     *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String::~String() { | 
					
						
							|  |  |  |     invalidate(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Memory Management                        */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | inline void String::init(void) { | 
					
						
							|  |  |  |     setSSO(false); | 
					
						
							|  |  |  |     setCapacity(0); | 
					
						
							|  |  |  |     setLen(0); | 
					
						
							|  |  |  |     setBuffer(nullptr); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::invalidate(void) { | 
					
						
							|  |  |  |     if(!sso() && wbuffer()) | 
					
						
							|  |  |  |         free(wbuffer()); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     init(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::reserve(unsigned int size) { | 
					
						
							|  |  |  |     if(buffer() && capacity() >= size) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     if(changeBuffer(size)) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if(len() == 0) | 
					
						
							|  |  |  |             wbuffer()[0] = 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::changeBuffer(unsigned int maxStrLen) { | 
					
						
							|  |  |  |     // Can we use SSO here to avoid allocation?
 | 
					
						
							|  |  |  |     if (maxStrLen < sizeof(sso_buf)) { | 
					
						
							|  |  |  |         if (sso() || !buffer()) { | 
					
						
							|  |  |  |             // Already using SSO, nothing to do
 | 
					
						
							|  |  |  |             setSSO(true); | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } else { // if bufptr && !sso()
 | 
					
						
							|  |  |  |             // Using bufptr, need to shrink into sso_buff
 | 
					
						
							|  |  |  |             char temp[sizeof(sso_buf)]; | 
					
						
							|  |  |  |             memcpy(temp, buffer(), maxStrLen); | 
					
						
							|  |  |  |             free(wbuffer()); | 
					
						
							|  |  |  |             setSSO(true); | 
					
						
							|  |  |  |             memcpy(wbuffer(), temp, maxStrLen); | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Fallthrough to normal allocator
 | 
					
						
							|  |  |  |     size_t newSize = (maxStrLen + 16) & (~0xf); | 
					
						
							|  |  |  |     // Make sure we can fit newsize in the buffer
 | 
					
						
							|  |  |  |     if (newSize > CAPACITY_MAX) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     uint16_t oldLen = len(); | 
					
						
							|  |  |  |     char *newbuffer = (char *) realloc(sso() ? nullptr : wbuffer(), newSize); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(newbuffer) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         size_t oldSize = capacity() + 1; // include NULL.
 | 
					
						
							|  |  |  |         if (sso()) { | 
					
						
							|  |  |  |             // Copy the SSO buffer into allocated space
 | 
					
						
							|  |  |  |             memcpy(newbuffer, sso_buf, sizeof(sso_buf)); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if (newSize > oldSize) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             memset(newbuffer + oldSize, 0, newSize - oldSize); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         setSSO(false); | 
					
						
							|  |  |  |         setCapacity(newSize - 1); | 
					
						
							|  |  |  |         setLen(oldLen); // Needed in case of SSO where len() never existed
 | 
					
						
							|  |  |  |         setBuffer(newbuffer); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Copy and Move                            */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::copy(const char *cstr, unsigned int length) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(!reserve(length)) { | 
					
						
							|  |  |  |         invalidate(); | 
					
						
							|  |  |  |         return *this; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     setLen(length); | 
					
						
							|  |  |  |     strcpy(wbuffer(), cstr); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::copy(const __FlashStringHelper *pstr, unsigned int length) { | 
					
						
							|  |  |  |     if (!reserve(length)) { | 
					
						
							|  |  |  |         invalidate(); | 
					
						
							|  |  |  |         return *this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     setLen(length); | 
					
						
							|  |  |  |     strcpy_P(wbuffer(), (PGM_P)pstr); | 
					
						
							|  |  |  |     return *this; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | #ifdef __GXX_EXPERIMENTAL_CXX0X__
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::move(String &rhs) { | 
					
						
							|  |  |  |     if(buffer()) { | 
					
						
							|  |  |  |         if(capacity() >= rhs.len()) { | 
					
						
							|  |  |  |             strcpy(wbuffer(), rhs.buffer()); | 
					
						
							|  |  |  |             setLen(rhs.len()); | 
					
						
							|  |  |  | 	    rhs.invalidate(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |             if (!sso()) { | 
					
						
							|  |  |  |                 free(wbuffer()); | 
					
						
							|  |  |  |                 setBuffer(nullptr); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if (rhs.sso()) { | 
					
						
							|  |  |  |         setSSO(true); | 
					
						
							|  |  |  |         memmove(sso_buf, rhs.sso_buf, sizeof(sso_buf)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         setSSO(false); | 
					
						
							|  |  |  |         setBuffer(rhs.wbuffer()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     setCapacity(rhs.capacity()); | 
					
						
							|  |  |  |     setLen(rhs.len()); | 
					
						
							|  |  |  |     rhs.setSSO(false); | 
					
						
							|  |  |  |     rhs.setCapacity(0); | 
					
						
							|  |  |  |     rhs.setLen(0); | 
					
						
							|  |  |  |     rhs.setBuffer(nullptr); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::operator =(const String &rhs) { | 
					
						
							|  |  |  |     if(this == &rhs) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return *this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(rhs.buffer()) | 
					
						
							|  |  |  |         copy(rhs.buffer(), rhs.len()); | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         invalidate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __GXX_EXPERIMENTAL_CXX0X__
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::operator =(String &&rval) { | 
					
						
							|  |  |  |     if(this != &rval) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         move(rval); | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::operator =(StringSumHelper &&rval) { | 
					
						
							|  |  |  |     if(this != &rval) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         move(rval); | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String & String::operator =(const char *cstr) { | 
					
						
							|  |  |  |     if(cstr) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         copy(cstr, strlen(cstr)); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         invalidate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | String & String::operator = (const __FlashStringHelper *pstr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); | 
					
						
							|  |  |  |     else invalidate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  concat                                   */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(const String &s) { | 
					
						
							|  |  |  |     // Special case if we're concatting ourself (s += s;) since we may end up
 | 
					
						
							|  |  |  |     // realloc'ing the buffer and moving s.buffer in the method called
 | 
					
						
							|  |  |  |     if (&s == this) { | 
					
						
							|  |  |  |         unsigned int newlen = 2 * len(); | 
					
						
							|  |  |  |         if (!s.buffer()) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         if (s.len() == 0) | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         if (!reserve(newlen)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         memcpy(wbuffer() + len(), buffer(), len()); | 
					
						
							|  |  |  |         setLen(newlen); | 
					
						
							|  |  |  |         wbuffer()[len()] = 0; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return concat(s.buffer(), s.len()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(const char *cstr, unsigned int length) { | 
					
						
							|  |  |  |     unsigned int newlen = len() + length; | 
					
						
							|  |  |  |     if(!cstr) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(length == 0) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!reserve(newlen)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     strcpy(wbuffer() + len(), cstr); | 
					
						
							|  |  |  |     setLen(newlen); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(const char *cstr) { | 
					
						
							|  |  |  |     if(!cstr) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     return concat(cstr, strlen(cstr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(char c) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[2]; | 
					
						
							|  |  |  |     buf[0] = c; | 
					
						
							|  |  |  |     buf[1] = 0; | 
					
						
							|  |  |  |     return concat(buf, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(unsigned char num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[1 + 3 * sizeof(unsigned char)]; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     sprintf(buf, "%d", num); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return concat(buf, strlen(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(int num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[2 + 3 * sizeof(int)]; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     sprintf(buf, "%d", num); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return concat(buf, strlen(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(unsigned int num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[1 + 3 * sizeof(unsigned int)]; | 
					
						
							|  |  |  |     utoa(num, buf, 10); | 
					
						
							|  |  |  |     return concat(buf, strlen(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(long num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[2 + 3 * sizeof(long)]; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     sprintf(buf, "%ld", num); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return concat(buf, strlen(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(unsigned long num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[1 + 3 * sizeof(unsigned long)]; | 
					
						
							|  |  |  |     ultoa(num, buf, 10); | 
					
						
							|  |  |  |     return concat(buf, strlen(buf)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(float num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[20]; | 
					
						
							|  |  |  |     char* string = dtostrf(num, 4, 2, buf); | 
					
						
							|  |  |  |     return concat(string, strlen(string)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(double num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char buf[20]; | 
					
						
							|  |  |  |     char* string = dtostrf(num, 4, 2, buf); | 
					
						
							|  |  |  |     return concat(string, strlen(string)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::concat(const __FlashStringHelper * str) { | 
					
						
							|  |  |  |     if (!str) return 0; | 
					
						
							|  |  |  |     int length = strlen_P((PGM_P)str); | 
					
						
							|  |  |  |     if (length == 0) return 1; | 
					
						
							|  |  |  |     unsigned int newlen = len() + length; | 
					
						
							|  |  |  |     if (!reserve(newlen)) return 0; | 
					
						
							|  |  |  |     strcpy_P(wbuffer() + len(), (PGM_P)str); | 
					
						
							|  |  |  |     setLen(newlen); | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | /*********************************************/ | 
					
						
							|  |  |  | /*  Concatenate                              */ | 
					
						
							|  |  |  | /*********************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(rhs.buffer(), rhs.len())) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!cstr || !a.concat(cstr, strlen(cstr))) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, char c) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(c)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, int num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, long num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, float num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | StringSumHelper & operator +(const StringSumHelper &lhs, double num) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(!a.concat(num)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         a.invalidate(); | 
					
						
							|  |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if (!a.concat(rhs)) | 
					
						
							|  |  |  |         a.invalidate(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return a; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-08 18:57:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Comparison                               */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | 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(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return strcmp(buffer(), s.buffer()); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::equals(const String &s2) const { | 
					
						
							|  |  |  |     return (len() == s2.len() && compareTo(s2) == 0); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::equals(const char *cstr) const { | 
					
						
							|  |  |  |     if(len() == 0) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return (cstr == NULL || *cstr == 0); | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(cstr == NULL) | 
					
						
							|  |  |  |         return buffer()[0] == 0; | 
					
						
							|  |  |  |     return strcmp(buffer(), cstr) == 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::operator<(const String &rhs) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return compareTo(rhs) < 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::operator>(const String &rhs) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return compareTo(rhs) > 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::operator<=(const String &rhs) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return compareTo(rhs) <= 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::operator>=(const String &rhs) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return compareTo(rhs) >= 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::equalsIgnoreCase(const String &s2) const { | 
					
						
							|  |  |  |     if(this == &s2) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(len() != s2.len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(len() == 0) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     const char *p1 = buffer(); | 
					
						
							|  |  |  |     const char *p2 = s2.buffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     while(*p1) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if(tolower(*p1++) != tolower(*p2++)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::equalsConstantTime(const String &s2) const { | 
					
						
							|  |  |  |     // To avoid possible time-based attacks present function
 | 
					
						
							|  |  |  |     // compares given strings in a constant time.
 | 
					
						
							|  |  |  |     if(len() != s2.len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     //at this point lengths are the same
 | 
					
						
							|  |  |  |     if(len() == 0) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     //at this point lenghts are the same and non-zero
 | 
					
						
							|  |  |  |     const char *p1 = buffer(); | 
					
						
							|  |  |  |     const char *p2 = s2.buffer(); | 
					
						
							|  |  |  |     unsigned int equalchars = 0; | 
					
						
							|  |  |  |     unsigned int diffchars = 0; | 
					
						
							|  |  |  |     while(*p1) { | 
					
						
							|  |  |  |         if(*p1 == *p2) | 
					
						
							|  |  |  |             ++equalchars; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ++diffchars; | 
					
						
							|  |  |  |         ++p1; | 
					
						
							|  |  |  |         ++p2; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     //the following should force a constant time eval of the condition without a compiler "logical shortcut"
 | 
					
						
							|  |  |  |     unsigned char equalcond = (equalchars == len()); | 
					
						
							|  |  |  |     unsigned char diffcond = (diffchars == 0); | 
					
						
							|  |  |  |     return (equalcond & diffcond); //bitwise AND
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned char String::startsWith(const String &s2) const { | 
					
						
							|  |  |  |     if(len() < s2.len()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return startsWith(s2, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::startsWith(const String &s2, unsigned int offset) const { | 
					
						
							|  |  |  |     if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | unsigned char String::endsWith(const String &s2) const { | 
					
						
							|  |  |  |     if(len() < s2.len() || !buffer() || !s2.buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Character Access                         */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | char String::charAt(unsigned int loc) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return operator[](loc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::setCharAt(unsigned int loc, char c) { | 
					
						
							|  |  |  |     if(loc < len()) | 
					
						
							|  |  |  |         wbuffer()[loc] = c; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | char & String::operator[](unsigned int index) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     static char dummy_writable_char; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(index >= len() || !buffer()) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         dummy_writable_char = 0; | 
					
						
							|  |  |  |         return dummy_writable_char; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return wbuffer()[index]; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | char String::operator[](unsigned int index) const { | 
					
						
							|  |  |  |     if(index >= len() || !buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return buffer()[index]; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { | 
					
						
							|  |  |  |     if(!bufsize || !buf) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(index >= len()) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         buf[0] = 0; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     unsigned int n = bufsize - 1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(n > len() - index) | 
					
						
							|  |  |  |         n = len() - index; | 
					
						
							|  |  |  |     strncpy((char *) buf, buffer() + index, n); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     buf[n] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Search                                   */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::indexOf(char c) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return indexOf(c, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::indexOf(char ch, unsigned int fromIndex) const { | 
					
						
							|  |  |  |     if(fromIndex >= len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     const char* temp = strchr(buffer() + fromIndex, ch); | 
					
						
							|  |  |  |     if(temp == NULL) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return temp - buffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::indexOf(const String &s2) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return indexOf(s2, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::indexOf(const String &s2, unsigned int fromIndex) const { | 
					
						
							|  |  |  |     if(fromIndex >= len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     const char *found = strstr(buffer() + fromIndex, s2.buffer()); | 
					
						
							|  |  |  |     if(found == NULL) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return found - buffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::lastIndexOf(char theChar) const { | 
					
						
							|  |  |  |     return lastIndexOf(theChar, len() - 1); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::lastIndexOf(char ch, unsigned int fromIndex) const { | 
					
						
							|  |  |  |     if(fromIndex >= len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     char tempchar = buffer()[fromIndex + 1]; | 
					
						
							|  |  |  |     wbuffer()[fromIndex + 1] = '\0'; | 
					
						
							|  |  |  |     char* temp = strrchr(wbuffer(), ch); | 
					
						
							|  |  |  |     wbuffer()[fromIndex + 1] = tempchar; | 
					
						
							|  |  |  |     if(temp == NULL) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     return temp - buffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::lastIndexOf(const String &s2) const { | 
					
						
							|  |  |  |     return lastIndexOf(s2, len() - s2.len()); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | int String::lastIndexOf(const String &s2, unsigned int fromIndex) const { | 
					
						
							|  |  |  |     if(s2.len() == 0 || len() == 0 || s2.len() > len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(fromIndex >= len()) | 
					
						
							|  |  |  |         fromIndex = len() - 1; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     int found = -1; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) { | 
					
						
							|  |  |  |         p = strstr(p, s2.buffer()); | 
					
						
							|  |  |  |         if(!p) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if((unsigned int) (p - wbuffer()) <= fromIndex) | 
					
						
							|  |  |  |             found = p - buffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return found; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | String String::substring(unsigned int left, unsigned int right) const { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(left > right) { | 
					
						
							|  |  |  |         unsigned int temp = right; | 
					
						
							|  |  |  |         right = left; | 
					
						
							|  |  |  |         left = temp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     String out; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(left >= len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return out; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(right > len()) | 
					
						
							|  |  |  |         right = len(); | 
					
						
							|  |  |  |     char temp = buffer()[right];  // save the replaced character
 | 
					
						
							|  |  |  |     wbuffer()[right] = '\0'; | 
					
						
							|  |  |  |     out = wbuffer() + left;  // pointer arithmetic
 | 
					
						
							|  |  |  |     wbuffer()[right] = temp;  //restore character
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return out; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Modification                             */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::replace(char find, char replace) { | 
					
						
							|  |  |  |     if(!buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     for(char *p = wbuffer(); *p; p++) { | 
					
						
							|  |  |  |         if(*p == find) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             *p = replace; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::replace(const String& find, const String& replace) { | 
					
						
							|  |  |  |     if(len() == 0 || find.len() == 0) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     int diff = replace.len() - find.len(); | 
					
						
							|  |  |  |     char *readFrom = wbuffer(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     char *foundAt; | 
					
						
							|  |  |  |     if(diff == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         while((foundAt = strstr(readFrom, find.buffer())) != NULL) { | 
					
						
							|  |  |  |             memmove(foundAt, replace.buffer(), replace.len()); | 
					
						
							|  |  |  |             readFrom = foundAt + replace.len(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         } | 
					
						
							|  |  |  |     } else if(diff < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         char *writeTo = wbuffer(); | 
					
						
							|  |  |  |         while((foundAt = strstr(readFrom, find.buffer())) != NULL) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             unsigned int n = foundAt - readFrom; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |             memmove(writeTo, readFrom, n); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             writeTo += n; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |             memmove(writeTo, replace.buffer(), replace.len()); | 
					
						
							|  |  |  |             writeTo += replace.len(); | 
					
						
							|  |  |  |             readFrom = foundAt + find.len(); | 
					
						
							|  |  |  |             setLen(len() + diff); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         memmove(writeTo, readFrom, strlen(readFrom)+1); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         unsigned int size = len(); // compute size needed for result
 | 
					
						
							|  |  |  |         while((foundAt = strstr(readFrom, find.buffer())) != NULL) { | 
					
						
							|  |  |  |             readFrom = foundAt + find.len(); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             size += diff; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if(size == len()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |         if(size > capacity() && !changeBuffer(size)) | 
					
						
							|  |  |  |             return; // XXX: tell user!
 | 
					
						
							|  |  |  |         int index = len() - 1; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) { | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |             readFrom = wbuffer() + index + find.len(); | 
					
						
							|  |  |  |             memmove(readFrom + diff, readFrom, len() - (readFrom - buffer())); | 
					
						
							|  |  |  | 	    int newLen = len() + diff; | 
					
						
							|  |  |  |             memmove(wbuffer() + index, replace.buffer(), replace.len()); | 
					
						
							|  |  |  |             setLen(newLen); | 
					
						
							|  |  |  |             wbuffer()[newLen] = 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             index--; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::remove(unsigned int index) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     // Pass the biggest integer as the count. The remove method
 | 
					
						
							|  |  |  |     // below will take care of truncating it at the end of the
 | 
					
						
							|  |  |  |     // string.
 | 
					
						
							|  |  |  |     remove(index, (unsigned int) -1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::remove(unsigned int index, unsigned int count) { | 
					
						
							|  |  |  |     if(index >= len()) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(count <= 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     if(count > len() - index) { | 
					
						
							|  |  |  |         count = len() - index; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     char *writeTo = wbuffer() + index; | 
					
						
							|  |  |  |     unsigned int newlen = len() - count; | 
					
						
							|  |  |  |     setLen(newlen); | 
					
						
							|  |  |  |     memmove(writeTo, wbuffer() + index + count, newlen - index); | 
					
						
							|  |  |  |     wbuffer()[newlen] = 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::toLowerCase(void) { | 
					
						
							|  |  |  |     if(!buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     for(char *p = wbuffer(); *p; p++) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         *p = tolower(*p); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::toUpperCase(void) { | 
					
						
							|  |  |  |     if(!buffer()) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     for(char *p = wbuffer(); *p; p++) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         *p = toupper(*p); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | void String::trim(void) { | 
					
						
							|  |  |  |     if(!buffer() || len() == 0) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     char *begin = wbuffer(); | 
					
						
							|  |  |  |     while(isspace(*begin)) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         begin++; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     char *end = wbuffer() + len() - 1; | 
					
						
							|  |  |  |     while(isspace(*end) && end >= begin) | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         end--; | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  |     unsigned int newlen = end + 1 - begin; | 
					
						
							|  |  |  |     setLen(newlen); | 
					
						
							|  |  |  |     if(begin > buffer()) | 
					
						
							|  |  |  |         memmove(wbuffer(), begin, newlen); | 
					
						
							|  |  |  |     wbuffer()[newlen] = 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | // /*  Parsing / Conversion                     */
 | 
					
						
							|  |  |  | // /*********************************************/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | long String::toInt(void) const { | 
					
						
							|  |  |  |     if (buffer()) | 
					
						
							|  |  |  |         return atol(buffer()); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | float String::toFloat(void) const { | 
					
						
							|  |  |  |     if (buffer()) | 
					
						
							|  |  |  |         return atof(buffer()); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-27 09:01:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | double String::toDouble(void) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (buffer()) | 
					
						
							|  |  |  |         return atof(buffer()); | 
					
						
							|  |  |  |     return 0.0; | 
					
						
							| 
									
										
										
										
											2018-11-19 10:45:09 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-27 09:01:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 09:41:42 -07:00
										 |  |  | // global empty string to allow returning const String& with nothing
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const String emptyString; |