aboutsummaryrefslogtreecommitdiff
path: root/components/fasani__adafruit_gfx/WString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'components/fasani__adafruit_gfx/WString.cpp')
-rw-r--r--components/fasani__adafruit_gfx/WString.cpp864
1 files changed, 864 insertions, 0 deletions
diff --git a/components/fasani__adafruit_gfx/WString.cpp b/components/fasani__adafruit_gfx/WString.cpp
new file mode 100644
index 0000000..278c68e
--- /dev/null
+++ b/components/fasani__adafruit_gfx/WString.cpp
@@ -0,0 +1,864 @@
+/*
+ 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
+ Modified by Ivan Grokhotkov, 2014 - esp8266 support
+ Modified by Michael C. Miller, 2015 - esp8266 progmem support
+
+ 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 "WString.h"
+extern "C" {
+ #include "stdio.h"
+ #include "stdlib_noniso.h"
+}
+
+/*********************************************/
+/* Constructors */
+/*********************************************/
+
+String::String(const char *cstr) {
+ init();
+ if (cstr)
+ copy(cstr, strlen(cstr));
+}
+
+String::String(const String &value) {
+ init();
+ *this = value;
+}
+
+String::String(const __FlashStringHelper *pstr) {
+ init();
+ *this = pstr; // see operator =
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String::String(String &&rval) {
+ init();
+ move(rval);
+}
+
+String::String(StringSumHelper &&rval) {
+ init();
+ move(rval);
+}
+#endif
+
+String::String(char c) {
+ init();
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ *this = buf;
+}
+
+String::String(unsigned char value, unsigned char base) {
+ init();
+ char buf[1 + 8 * sizeof(unsigned char)];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(int value, unsigned char base) {
+ init();
+ char buf[2 + 8 * sizeof(int)];
+ if (base == 10) {
+ sprintf(buf, "%d", value);
+ } else {
+ itoa(value, buf, base);
+ }
+ *this = buf;
+}
+
+String::String(unsigned int value, unsigned char base) {
+ init();
+ char buf[1 + 8 * sizeof(unsigned int)];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(long value, unsigned char base) {
+ init();
+ char buf[2 + 8 * sizeof(long)];
+ if (base==10) {
+ sprintf(buf, "%ld", value);
+ } else {
+ ltoa(value, buf, base);
+ }
+ *this = buf;
+}
+
+String::String(unsigned long value, unsigned char base) {
+ init();
+ char buf[1 + 8 * sizeof(unsigned long)];
+ ultoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(float value, unsigned char decimalPlaces) {
+ init();
+ char buf[33];
+ *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
+}
+
+String::String(double value, unsigned char decimalPlaces) {
+ init();
+ char buf[33];
+ *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
+}
+
+String::~String() {
+ invalidate();
+}
+
+// /*********************************************/
+// /* Memory Management */
+// /*********************************************/
+
+inline void String::init(void) {
+ setSSO(false);
+ setCapacity(0);
+ setLen(0);
+ setBuffer(nullptr);
+}
+
+void String::invalidate(void) {
+ if(!isSSO() && wbuffer())
+ free(wbuffer());
+ init();
+}
+
+unsigned char String::reserve(unsigned int size) {
+ if(buffer() && capacity() >= size)
+ return 1;
+ if(changeBuffer(size)) {
+ if(len() == 0)
+ wbuffer()[0] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+unsigned char String::changeBuffer(unsigned int maxStrLen) {
+ // Can we use SSO here to avoid allocation?
+ if (maxStrLen < sizeof(sso.buff) - 1) {
+ if (isSSO() || !buffer()) {
+ // Already using SSO, nothing to do
+ uint16_t oldLen = len();
+ setSSO(true);
+ setLen(oldLen);
+ return 1;
+ } else { // if bufptr && !isSSO()
+ // Using bufptr, need to shrink into sso.buff
+ char temp[sizeof(sso.buff)];
+ memcpy(temp, buffer(), maxStrLen);
+ free(wbuffer());
+ uint16_t oldLen = len();
+ setSSO(true);
+ setLen(oldLen);
+ 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(isSSO() ? nullptr : wbuffer(), newSize);
+ if (newbuffer) {
+ size_t oldSize = capacity() + 1; // include NULL.
+ if (isSSO()) {
+ // Copy the SSO buffer into allocated space
+ memmove(newbuffer, sso.buff, sizeof(sso.buff));
+ }
+ 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);
+ return 1;
+ }
+ return 0;
+}
+
+// /*********************************************/
+// /* Copy and Move */
+// /*********************************************/
+
+String & String::copy(const char *cstr, unsigned int length) {
+ if(!reserve(length)) {
+ invalidate();
+ return *this;
+ }
+ setLen(length);
+ memmove(wbuffer(), cstr, length + 1);
+ return *this;
+}
+
+String & String::copy(const __FlashStringHelper *pstr, unsigned int length) {
+ if (!reserve(length)) {
+ invalidate();
+ return *this;
+ }
+ setLen(length);
+ memcpy(wbuffer(), pstr, length + 1);
+
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+void String::move(String &rhs) {
+ if(buffer()) {
+ if(capacity() >= rhs.len()) {
+ memmove(wbuffer(), rhs.buffer(), rhs.length() + 1);
+ setLen(rhs.len());
+ rhs.invalidate();
+ return;
+ } else {
+ if (!isSSO()) {
+ free(wbuffer());
+ setBuffer(nullptr);
+ }
+ }
+ }
+ if (rhs.isSSO()) {
+ setSSO(true);
+ memmove(sso.buff, rhs.sso.buff, sizeof(sso.buff));
+ } else {
+ setSSO(false);
+ setBuffer(rhs.wbuffer());
+ }
+ setCapacity(rhs.capacity());
+ setLen(rhs.len());
+ rhs.setSSO(false);
+ rhs.setCapacity(0);
+ rhs.setLen(0);
+ rhs.setBuffer(nullptr);
+}
+#endif
+
+String & String::operator =(const String &rhs) {
+ if(this == &rhs)
+ return *this;
+
+ if(rhs.buffer())
+ copy(rhs.buffer(), rhs.len());
+ else
+ invalidate();
+
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String & String::operator =(String &&rval) {
+ if(this != &rval)
+ move(rval);
+ return *this;
+}
+
+String & String::operator =(StringSumHelper &&rval) {
+ if(this != &rval)
+ move(rval);
+ return *this;
+}
+#endif
+
+String & String::operator =(const char *cstr) {
+ if(cstr)
+ copy(cstr, strlen(cstr));
+ else
+ invalidate();
+
+ return *this;
+}
+
+String & String::operator = (const __FlashStringHelper *pstr)
+{
+ if (pstr) copy(pstr, strlen((const char *)pstr));
+ else invalidate();
+
+ return *this;
+}
+
+// /*********************************************/
+// /* concat */
+// /*********************************************/
+
+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;
+ memmove(wbuffer() + len(), buffer(), len());
+ setLen(newlen);
+ wbuffer()[len()] = 0;
+ return 1;
+ } else {
+ return concat(s.buffer(), s.len());
+ }
+}
+
+unsigned char String::concat(const char *cstr, unsigned int length) {
+ unsigned int newlen = len() + length;
+ if(!cstr)
+ return 0;
+ if(length == 0)
+ return 1;
+ if(!reserve(newlen))
+ return 0;
+ if (cstr >= wbuffer() && cstr < wbuffer() + len())
+ // compatible with SSO in ram #6155 (case "x += x.c_str()")
+ memmove(wbuffer() + len(), cstr, length + 1);
+ else
+ // compatible with source in flash #6367
+ memcpy(wbuffer() + len(), cstr, length + 1);
+ setLen(newlen);
+ return 1;
+}
+
+unsigned char String::concat(const char *cstr) {
+ if(!cstr)
+ return 0;
+ return concat(cstr, strlen(cstr));
+}
+
+unsigned char String::concat(char c) {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ return concat(buf, 1);
+}
+
+unsigned char String::concat(unsigned char num) {
+ char buf[1 + 3 * sizeof(unsigned char)];
+ sprintf(buf, "%d", num);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(int num) {
+ char buf[2 + 3 * sizeof(int)];
+ sprintf(buf, "%d", num);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned int num) {
+ char buf[1 + 3 * sizeof(unsigned int)];
+ utoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(long num) {
+ char buf[2 + 3 * sizeof(long)];
+ sprintf(buf, "%ld", num);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned long num) {
+ char buf[1 + 3 * sizeof(unsigned long)];
+ ultoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(float num) {
+ char buf[20];
+ char* string = dtostrf(num, 4, 2, buf);
+ return concat(string, strlen(string));
+}
+
+unsigned char String::concat(double num) {
+ char buf[20];
+ char* string = dtostrf(num, 4, 2, buf);
+ return concat(string, strlen(string));
+}
+
+unsigned char String::concat(const __FlashStringHelper * str) {
+ if (!str) return 0;
+ int length = strlen((const char *)str);
+ if (length == 0) return 1;
+ unsigned int newlen = len() + length;
+ if (!reserve(newlen)) return 0;
+ memcpy(wbuffer() + len(), str, length + 1);
+ setLen(newlen);
+ return 1;
+}
+
+/*********************************************/
+/* Concatenate */
+/*********************************************/
+
+StringSumHelper & operator +(const StringSumHelper &lhs, const String &rhs) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(rhs.buffer(), rhs.len()))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, const char *cstr) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!cstr || !a.concat(cstr, strlen(cstr)))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, char c) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(c))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, unsigned char num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, int num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, unsigned int num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, long num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, unsigned long num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, float num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator +(const StringSumHelper &lhs, double num) {
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if(!a.concat(num))
+ a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(rhs))
+ a.invalidate();
+ return a;
+}
+
+// /*********************************************/
+// /* Comparison */
+// /*********************************************/
+
+int String::compareTo(const String &s) const {
+ if(!buffer() || !s.buffer()) {
+ if(s.buffer() && s.len() > 0)
+ return 0 - *(unsigned char *) s.buffer();
+ if(buffer() && len() > 0)
+ return *(unsigned char *) buffer();
+ return 0;
+ }
+ return strcmp(buffer(), s.buffer());
+}
+
+unsigned char String::equals(const String &s2) const {
+ return (len() == s2.len() && compareTo(s2) == 0);
+}
+
+unsigned char String::equals(const char *cstr) const {
+ if(len() == 0)
+ return (cstr == NULL || *cstr == 0);
+ if(cstr == NULL)
+ return buffer()[0] == 0;
+ return strcmp(buffer(), cstr) == 0;
+}
+
+unsigned char String::operator<(const String &rhs) const {
+ return compareTo(rhs) < 0;
+}
+
+unsigned char String::operator>(const String &rhs) const {
+ return compareTo(rhs) > 0;
+}
+
+unsigned char String::operator<=(const String &rhs) const {
+ return compareTo(rhs) <= 0;
+}
+
+unsigned char String::operator>=(const String &rhs) const {
+ return compareTo(rhs) >= 0;
+}
+
+unsigned char String::equalsIgnoreCase(const String &s2) const {
+ if(this == &s2)
+ return 1;
+ if(len() != s2.len())
+ return 0;
+ if(len() == 0)
+ return 1;
+ const char *p1 = buffer();
+ const char *p2 = s2.buffer();
+ while(*p1) {
+ if(tolower(*p1++) != tolower(*p2++))
+ return 0;
+ }
+ return 1;
+}
+
+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())
+ return 0;
+ //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;
+ }
+ //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;
+ return startsWith(s2, 0);
+}
+
+unsigned char String::startsWith(const String &s2, unsigned int offset) const {
+ if(offset > (unsigned)(len() - s2.len()) || !buffer() || !s2.buffer())
+ return 0;
+ return strncmp(&buffer()[offset], s2.buffer(), s2.len()) == 0;
+}
+
+unsigned char String::endsWith(const String &s2) const {
+ if(len() < s2.len() || !buffer() || !s2.buffer())
+ return 0;
+ return strcmp(&buffer()[len() - s2.len()], s2.buffer()) == 0;
+}
+
+// /*********************************************/
+// /* Character Access */
+// /*********************************************/
+
+char String::charAt(unsigned int loc) const {
+ return operator[](loc);
+}
+
+void String::setCharAt(unsigned int loc, char c) {
+ if(loc < len())
+ wbuffer()[loc] = c;
+}
+
+char & String::operator[](unsigned int index) {
+ static char dummy_writable_char;
+ if(index >= len() || !buffer()) {
+ dummy_writable_char = 0;
+ return dummy_writable_char;
+ }
+ return wbuffer()[index];
+}
+
+char String::operator[](unsigned int index) const {
+ if(index >= len() || !buffer())
+ return 0;
+ return buffer()[index];
+}
+
+void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const {
+ if(!bufsize || !buf)
+ return;
+ if(index >= len()) {
+ buf[0] = 0;
+ return;
+ }
+ unsigned int n = bufsize - 1;
+ if(n > len() - index)
+ n = len() - index;
+ strncpy((char *) buf, buffer() + index, n);
+ buf[n] = 0;
+}
+
+// /*********************************************/
+// /* Search */
+// /*********************************************/
+
+int String::indexOf(char c) const {
+ return indexOf(c, 0);
+}
+
+int String::indexOf(char ch, unsigned int fromIndex) const {
+ if(fromIndex >= len())
+ return -1;
+ const char* temp = strchr(buffer() + fromIndex, ch);
+ if(temp == NULL)
+ return -1;
+ return temp - buffer();
+}
+
+int String::indexOf(const String &s2) const {
+ return indexOf(s2, 0);
+}
+
+int String::indexOf(const String &s2, unsigned int fromIndex) const {
+ if(fromIndex >= len())
+ return -1;
+ const char *found = strstr(buffer() + fromIndex, s2.buffer());
+ if(found == NULL)
+ return -1;
+ return found - buffer();
+}
+
+int String::lastIndexOf(char theChar) const {
+ return lastIndexOf(theChar, len() - 1);
+}
+
+int String::lastIndexOf(char ch, unsigned int fromIndex) const {
+ if(fromIndex >= len())
+ return -1;
+ char tempchar = buffer()[fromIndex + 1];
+ wbuffer()[fromIndex + 1] = '\0';
+ char* temp = strrchr(wbuffer(), ch);
+ wbuffer()[fromIndex + 1] = tempchar;
+ if(temp == NULL)
+ return -1;
+ return temp - buffer();
+}
+
+int String::lastIndexOf(const String &s2) const {
+ return lastIndexOf(s2, len() - s2.len());
+}
+
+int String::lastIndexOf(const String &s2, unsigned int fromIndex) const {
+ if(s2.len() == 0 || len() == 0 || s2.len() > len())
+ return -1;
+ if(fromIndex >= len())
+ fromIndex = len() - 1;
+ int found = -1;
+ for(char *p = wbuffer(); p <= wbuffer() + fromIndex; p++) {
+ p = strstr(p, s2.buffer());
+ if(!p)
+ break;
+ if((unsigned int) (p - wbuffer()) <= fromIndex)
+ found = p - buffer();
+ }
+ return found;
+}
+
+String String::substring(unsigned int left, unsigned int right) const {
+ if(left > right) {
+ unsigned int temp = right;
+ right = left;
+ left = temp;
+ }
+ String out;
+ if(left >= len())
+ return out;
+ if(right > len())
+ right = len();
+ char temp = buffer()[right]; // save the replaced character
+ wbuffer()[right] = '\0';
+ out = wbuffer() + left; // pointer arithmetic
+ wbuffer()[right] = temp; //restore character
+ return out;
+}
+
+// /*********************************************/
+// /* Modification */
+// /*********************************************/
+
+void String::replace(char find, char replace) {
+ if(!buffer())
+ return;
+ for(char *p = wbuffer(); *p; p++) {
+ if(*p == find)
+ *p = replace;
+ }
+}
+
+void String::replace(const String& find, const String& replace) {
+ if(len() == 0 || find.len() == 0)
+ return;
+ int diff = replace.len() - find.len();
+ char *readFrom = wbuffer();
+ char *foundAt;
+ if(diff == 0) {
+ while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
+ memmove(foundAt, replace.buffer(), replace.len());
+ readFrom = foundAt + replace.len();
+ }
+ } else if(diff < 0) {
+ char *writeTo = wbuffer();
+ while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
+ unsigned int n = foundAt - readFrom;
+ memmove(writeTo, readFrom, n);
+ writeTo += n;
+ memmove(writeTo, replace.buffer(), replace.len());
+ writeTo += replace.len();
+ readFrom = foundAt + find.len();
+ setLen(len() + diff);
+ }
+ memmove(writeTo, readFrom, strlen(readFrom)+1);
+ } else {
+ unsigned int size = len(); // compute size needed for result
+ while((foundAt = strstr(readFrom, find.buffer())) != NULL) {
+ readFrom = foundAt + find.len();
+ size += diff;
+ }
+ if(size == len())
+ return;
+ if(size > capacity() && !changeBuffer(size))
+ return; // XXX: tell user!
+ int index = len() - 1;
+ while(index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
+ 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;
+ index--;
+ }
+ }
+}
+
+void String::remove(unsigned int index) {
+ // 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);
+}
+
+void String::remove(unsigned int index, unsigned int count) {
+ if(index >= len()) {
+ return;
+ }
+ if(count <= 0) {
+ return;
+ }
+ if(count > len() - index) {
+ count = len() - index;
+ }
+ char *writeTo = wbuffer() + index;
+ unsigned int newlen = len() - count;
+ setLen(newlen);
+ memmove(writeTo, wbuffer() + index + count, newlen - index);
+ wbuffer()[newlen] = 0;
+}
+
+void String::toLowerCase(void) {
+ if(!buffer())
+ return;
+ for(char *p = wbuffer(); *p; p++) {
+ *p = tolower(*p);
+ }
+}
+
+void String::toUpperCase(void) {
+ if(!buffer())
+ return;
+ for(char *p = wbuffer(); *p; p++) {
+ *p = toupper(*p);
+ }
+}
+
+void String::trim(void) {
+ if(!buffer() || len() == 0)
+ return;
+ char *begin = wbuffer();
+ while(isspace(*begin))
+ begin++;
+ char *end = wbuffer() + len() - 1;
+ while(isspace(*end) && end >= begin)
+ end--;
+ unsigned int newlen = end + 1 - begin;
+ setLen(newlen);
+ if(begin > buffer())
+ memmove(wbuffer(), begin, newlen);
+ wbuffer()[newlen] = 0;
+}
+
+// /*********************************************/
+// /* Parsing / Conversion */
+// /*********************************************/
+
+long String::toInt(void) const {
+ if (buffer())
+ return atol(buffer());
+ return 0;
+}
+
+float String::toFloat(void) const {
+ if (buffer())
+ return atof(buffer());
+ return 0;
+}
+
+double String::toDouble(void) const
+{
+ if (buffer())
+ return atof(buffer());
+ return 0.0;
+}
+
+// global empty string to allow returning const String& with nothing
+
+const String emptyString;