fork
Fork of cpputest by
Diff: src/CppUTest/SimpleString.cpp
- Revision:
- 1:4769360130ed
- Parent:
- 0:0b799af9d58e
--- a/src/CppUTest/SimpleString.cpp Tue Jan 28 09:27:41 2014 +0000 +++ b/src/CppUTest/SimpleString.cpp Tue Jun 17 15:52:54 2014 +0100 @@ -1,515 +1,538 @@ -/* - * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the <organization> nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "CppUTest/TestHarness.h" -#include "CppUTest/SimpleString.h" -#include "CppUTest/PlatformSpecificFunctions.h" -#include "CppUTest/TestMemoryAllocator.h" - - -TestMemoryAllocator* SimpleString::stringAllocator_ = NULL; - -TestMemoryAllocator* SimpleString::getStringAllocator() -{ - if (stringAllocator_ == NULL) - return defaultNewArrayAllocator(); - return stringAllocator_; -} - -void SimpleString::setStringAllocator(TestMemoryAllocator* allocator) -{ - stringAllocator_ = allocator; -} - -/* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */ -char* SimpleString::allocStringBuffer(size_t _size) -{ - return getStringAllocator()->alloc_memory(_size, __FILE__, __LINE__); -} - -void SimpleString::deallocStringBuffer(char* str) -{ - getStringAllocator()->free_memory(str, __FILE__, __LINE__); -} - -char* SimpleString::getEmptyString() const -{ - char* empty = allocStringBuffer(1); - empty[0] = '\0'; - return empty; -} -SimpleString::SimpleString(const char *otherBuffer) -{ - if (otherBuffer == 0) { - buffer_ = getEmptyString(); - } - else { - size_t len = PlatformSpecificStrLen(otherBuffer) + 1; - buffer_ = allocStringBuffer(len); - PlatformSpecificStrCpy(buffer_, otherBuffer); - } -} - -SimpleString::SimpleString(const char *other, size_t repeatCount) -{ - size_t len = PlatformSpecificStrLen(other) * repeatCount + 1; - buffer_ = allocStringBuffer(len); - char* next = buffer_; - for (size_t i = 0; i < repeatCount; i++) { - PlatformSpecificStrCpy(next, other); - next += PlatformSpecificStrLen(other); - } - *next = 0; - -} -SimpleString::SimpleString(const SimpleString& other) -{ - size_t len = other.size() + 1; - buffer_ = allocStringBuffer(len); - PlatformSpecificStrCpy(buffer_, other.buffer_); -} - -SimpleString& SimpleString::operator=(const SimpleString& other) -{ - if (this != &other) { - deallocStringBuffer(buffer_); - size_t len = other.size() + 1; - buffer_ = allocStringBuffer(len); - PlatformSpecificStrCpy(buffer_, other.buffer_); - } - return *this; -} - -bool SimpleString::contains(const SimpleString& other) const -{ - //strstr on some machines does not handle "" - //the right way. "" should be found in any string - if (PlatformSpecificStrLen(other.buffer_) == 0) return true; - else if (PlatformSpecificStrLen(buffer_) == 0) return false; - else return PlatformSpecificStrStr(buffer_, other.buffer_) != 0; -} - -bool SimpleString::containsNoCase(const SimpleString& other) const -{ - return toLower().contains(other.toLower()); -} - - -bool SimpleString::startsWith(const SimpleString& other) const -{ - if (PlatformSpecificStrLen(other.buffer_) == 0) return true; - else if (PlatformSpecificStrLen(buffer_) == 0) return false; - else return PlatformSpecificStrStr(buffer_, other.buffer_) == buffer_; -} - -bool SimpleString::endsWith(const SimpleString& other) const -{ - size_t buffer_length = PlatformSpecificStrLen(buffer_); - size_t other_buffer_length = PlatformSpecificStrLen(other.buffer_); - if (other_buffer_length == 0) return true; - if (buffer_length == 0) return false; - if (buffer_length < other_buffer_length) return false; - return PlatformSpecificStrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0; -} - -size_t SimpleString::count(const SimpleString& substr) const -{ - size_t num = 0; - char* str = buffer_; - while ((str = PlatformSpecificStrStr(str, substr.buffer_))) { - num++; - str++; - } - return num; -} - -void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const -{ - size_t num = count(delimiter); - size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U; - col.allocate(num + extraEndToken); - - char* str = buffer_; - char* prev; - for (size_t i = 0; i < num; ++i) { - prev = str; - str = PlatformSpecificStrStr(str, delimiter.buffer_) + 1; - size_t len = (size_t) (str - prev); - char* sub = allocStringBuffer(len + 1); - PlatformSpecificStrNCpy(sub, prev, len); - sub[len] = '\0'; - col[i] = sub; - deallocStringBuffer(sub); - } - if (extraEndToken) { - col[num] = str; - } -} - -void SimpleString::replace(char to, char with) -{ - size_t s = size(); - for (size_t i = 0; i < s; i++) { - if (buffer_[i] == to) buffer_[i] = with; - } -} - -void SimpleString::replace(const char* to, const char* with) -{ - size_t c = count(to); - size_t len = size(); - size_t tolen = PlatformSpecificStrLen(to); - size_t withlen = PlatformSpecificStrLen(with); - - size_t newsize = len + (withlen * c) - (tolen * c) + 1; - - if (newsize) { - char* newbuf = allocStringBuffer(newsize); - for (size_t i = 0, j = 0; i < len;) { - if (PlatformSpecificStrNCmp(&buffer_[i], to, tolen) == 0) { - PlatformSpecificStrNCpy(&newbuf[j], with, withlen); - j += withlen; - i += tolen; - } - else { - newbuf[j] = buffer_[i]; - j++; - i++; - } - } - deallocStringBuffer(buffer_); - buffer_ = newbuf; - buffer_[newsize - 1] = '\0'; - } - else { - buffer_ = getEmptyString(); - buffer_[0] = '\0'; - } -} - -SimpleString SimpleString::toLower() const -{ - SimpleString str(*this); - - size_t str_size = str.size(); - for (size_t i = 0; i < str_size; i++) - str.buffer_[i] = PlatformSpecificToLower(str.buffer_[i]); - - return str; -} - -const char *SimpleString::asCharString() const -{ - return buffer_; -} - -size_t SimpleString::size() const -{ - return PlatformSpecificStrLen(buffer_); -} - -bool SimpleString::isEmpty() const -{ - return size() == 0; -} - - - -SimpleString::~SimpleString() -{ - deallocStringBuffer(buffer_); -} - -bool operator==(const SimpleString& left, const SimpleString& right) -{ - return 0 == PlatformSpecificStrCmp(left.asCharString(), right.asCharString()); -} - -bool SimpleString::equalsNoCase(const SimpleString& str) const -{ - return toLower() == str.toLower(); -} - - -bool operator!=(const SimpleString& left, const SimpleString& right) -{ - return !(left == right); -} - -SimpleString SimpleString::operator+(const SimpleString& rhs) -{ - SimpleString t(buffer_); - t += rhs.buffer_; - return t; -} - -SimpleString& SimpleString::operator+=(const SimpleString& rhs) -{ - return operator+=(rhs.buffer_); -} - -SimpleString& SimpleString::operator+=(const char* rhs) -{ - size_t len = this->size() + PlatformSpecificStrLen(rhs) + 1; - char* tbuffer = allocStringBuffer(len); - PlatformSpecificStrCpy(tbuffer, this->buffer_); - PlatformSpecificStrCat(tbuffer, rhs); - deallocStringBuffer(buffer_); - buffer_ = tbuffer; - return *this; -} - -void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter) -{ - if (str1.size() > str2.size()) { - padStringsToSameLength(str2, str1, padCharacter); - return; - } - - char pad[2]; - pad[0] = padCharacter; - pad[1] = 0; - str1 = SimpleString(pad, str2.size() - str1.size()) + str1; -} - -SimpleString SimpleString::subString(size_t beginPos, size_t amount) const -{ - if (beginPos > size()-1) return ""; - - SimpleString newString = buffer_ + beginPos; - - if (newString.size() > amount) - newString.buffer_[amount] = '\0'; - - return newString; -} - -char SimpleString::at(int pos) const -{ - return buffer_[pos]; -} - -int SimpleString::find(char ch) const -{ - return findFrom(0, ch); -} - -int SimpleString::findFrom(size_t starting_position, char ch) const -{ - size_t length = size(); - for (size_t i = starting_position; i < length; i++) - if (buffer_[i] == ch) return (int) i; - return -1; -} - -SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const -{ - int beginPos = find(startChar); - if (beginPos < 0) return ""; - - int endPos = findFrom((size_t)beginPos, lastExcludedChar); - if (endPos == -1) return subString((size_t)beginPos, size()); - - return subString((size_t)beginPos, (size_t) (endPos - beginPos)); -} - - -void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const -{ - if (bufferToCopy == NULL || bufferSize == 0) return; - - size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize-1 : size(); - - PlatformSpecificStrNCpy(bufferToCopy, buffer_, sizeToCopy); - bufferToCopy[sizeToCopy] = '\0'; - -} - -SimpleString StringFrom(bool value) -{ - return SimpleString(StringFromFormat("%s", value ? "true" : "false")); -} - -SimpleString StringFrom(const char *value) -{ - return SimpleString(value); -} - -SimpleString StringFromOrNull(const char * expected) -{ - return (expected) ? StringFrom(expected) : "(null)"; -} - -SimpleString StringFrom(int value) -{ - return StringFromFormat("%d", value); -} - -SimpleString StringFrom(long value) -{ - return StringFromFormat("%ld", value); -} - -SimpleString StringFrom(const void* value) -{ - return SimpleString("0x") + HexStringFrom(value); -} - -SimpleString HexStringFrom(long value) -{ - return StringFromFormat("%lx", value); -} - -static long convertPointerToLongValue(const void* value) -{ - /* - * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating. - * This isn't the right way to convert pointers values and need to change by implementing a - * proper portable way to convert pointers to strings. - */ - long* long_value = (long*) &value; - return *long_value; -} - -SimpleString HexStringFrom(const void* value) -{ - return StringFromFormat("%lx", convertPointerToLongValue(value)); -} - -SimpleString StringFrom(double value, int precision) -{ - return StringFromFormat("%.*g", precision, value); -} - -SimpleString StringFrom(char value) -{ - return StringFromFormat("%c", value); -} - -SimpleString StringFrom(const SimpleString& value) -{ - return SimpleString(value); -} - -SimpleString StringFromFormat(const char* format, ...) -{ - SimpleString resultString; - va_list arguments; - va_start(arguments, format); - - resultString = VStringFromFormat(format, arguments); - va_end(arguments); - return resultString; -} - -SimpleString StringFrom(unsigned int i) -{ - return StringFromFormat("%10u (0x%08x)", i, i); -} - -#if CPPUTEST_USE_STD_CPP_LIB - -#include <string> - -SimpleString StringFrom(const std::string& value) -{ - return SimpleString(value.c_str()); -} - -SimpleString StringFrom(unsigned long i) -{ - return StringFromFormat("%lu (0x%lx)", i, i); -} - -#endif - -//Kludge to get a va_copy in VC++ V6 -#ifndef va_copy -#define va_copy(copy, original) copy = original; -#endif - -SimpleString VStringFromFormat(const char* format, va_list args) -{ - va_list argsCopy; - va_copy(argsCopy, args); - enum - { - sizeOfdefaultBuffer = 100 - }; - char defaultBuffer[sizeOfdefaultBuffer]; - SimpleString resultString; - - size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args); - if (size < sizeOfdefaultBuffer) { - resultString = SimpleString(defaultBuffer); - } - else { - size_t newBufferSize = size + 1; - char* newBuffer = SimpleString::allocStringBuffer(newBufferSize); - PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy); - resultString = SimpleString(newBuffer); - - SimpleString::deallocStringBuffer(newBuffer); - } - va_end(argsCopy); - return resultString; -} - -SimpleStringCollection::SimpleStringCollection() -{ - collection_ = 0; - size_ = 0; -} - -void SimpleStringCollection::allocate(size_t _size) -{ - if (collection_) delete[] collection_; - - size_ = _size; - collection_ = new SimpleString[size_]; -} - -SimpleStringCollection::~SimpleStringCollection() -{ - delete[] (collection_); -} - -size_t SimpleStringCollection::size() const -{ - return size_; -} - -SimpleString& SimpleStringCollection::operator[](size_t index) -{ - if (index >= size_) { - empty_ = ""; - return empty_; - } - - return collection_[index]; -} - +/* + * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the <organization> nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CppUTest/TestHarness.h" +#include "CppUTest/SimpleString.h" +#include "CppUTest/PlatformSpecificFunctions.h" +#include "CppUTest/TestMemoryAllocator.h" + + +TestMemoryAllocator* SimpleString::stringAllocator_ = NULL; + +TestMemoryAllocator* SimpleString::getStringAllocator() +{ + if (stringAllocator_ == NULL) + return defaultNewArrayAllocator(); + return stringAllocator_; +} + +void SimpleString::setStringAllocator(TestMemoryAllocator* allocator) +{ + stringAllocator_ = allocator; +} + +/* Avoid using the memory leak detector INSIDE SimpleString as its used inside the detector */ +char* SimpleString::allocStringBuffer(size_t _size) +{ + return getStringAllocator()->alloc_memory(_size, __FILE__, __LINE__); +} + +void SimpleString::deallocStringBuffer(char* str) +{ + getStringAllocator()->free_memory(str, __FILE__, __LINE__); +} + +char* SimpleString::getEmptyString() const +{ + char* empty = allocStringBuffer(1); + empty[0] = '\0'; + return empty; +} + +char* SimpleString::StrNCpy(char* s1, const char* s2, size_t n) +{ + char* result = s1; + + if((NULL == s1) || (0 == n)) return result; + + while ((*s1++ = *s2++) && --n != 0) + ; + return result; +} + +SimpleString::SimpleString(const char *otherBuffer) +{ + if (otherBuffer == 0) { + buffer_ = getEmptyString(); + } + else { + buffer_ = copyToNewBuffer(otherBuffer); + } +} + +SimpleString::SimpleString(const char *other, size_t repeatCount) +{ + size_t otherStringLength = PlatformSpecificStrLen(other); + size_t len = otherStringLength * repeatCount + 1; + buffer_ = allocStringBuffer(len); + char* next = buffer_; + for (size_t i = 0; i < repeatCount; i++) { + StrNCpy(next, other, otherStringLength + 1); + next += otherStringLength; + } + *next = 0; +} + +SimpleString::SimpleString(const SimpleString& other) +{ + buffer_ = copyToNewBuffer(other.buffer_); +} + +SimpleString& SimpleString::operator=(const SimpleString& other) +{ + if (this != &other) { + deallocStringBuffer(buffer_); + buffer_ = copyToNewBuffer(other.buffer_); + } + return *this; +} + +bool SimpleString::contains(const SimpleString& other) const +{ + //strstr on some machines does not handle "" + //the right way. "" should be found in any string + if (PlatformSpecificStrLen(other.buffer_) == 0) return true; + else if (PlatformSpecificStrLen(buffer_) == 0) return false; + else return PlatformSpecificStrStr(buffer_, other.buffer_) != 0; +} + +bool SimpleString::containsNoCase(const SimpleString& other) const +{ + return toLower().contains(other.toLower()); +} + + +bool SimpleString::startsWith(const SimpleString& other) const +{ + if (PlatformSpecificStrLen(other.buffer_) == 0) return true; + else if (PlatformSpecificStrLen(buffer_) == 0) return false; + else return PlatformSpecificStrStr(buffer_, other.buffer_) == buffer_; +} + +bool SimpleString::endsWith(const SimpleString& other) const +{ + size_t buffer_length = PlatformSpecificStrLen(buffer_); + size_t other_buffer_length = PlatformSpecificStrLen(other.buffer_); + if (other_buffer_length == 0) return true; + if (buffer_length == 0) return false; + if (buffer_length < other_buffer_length) return false; + return PlatformSpecificStrCmp(buffer_ + buffer_length - other_buffer_length, other.buffer_) == 0; +} + +size_t SimpleString::count(const SimpleString& substr) const +{ + size_t num = 0; + char* str = buffer_; + while ((str = PlatformSpecificStrStr(str, substr.buffer_))) { + num++; + str++; + } + return num; +} + +void SimpleString::split(const SimpleString& delimiter, SimpleStringCollection& col) const +{ + size_t num = count(delimiter); + size_t extraEndToken = (endsWith(delimiter)) ? 0 : 1U; + col.allocate(num + extraEndToken); + + char* str = buffer_; + char* prev; + for (size_t i = 0; i < num; ++i) { + prev = str; + str = PlatformSpecificStrStr(str, delimiter.buffer_) + 1; + size_t len = (size_t) (str - prev) + 1; + col[i].buffer_ = copyToNewBuffer(prev, len); + } + if (extraEndToken) { + col[num] = str; + } +} + +void SimpleString::replace(char to, char with) +{ + size_t s = size(); + for (size_t i = 0; i < s; i++) { + if (buffer_[i] == to) buffer_[i] = with; + } +} + +void SimpleString::replace(const char* to, const char* with) +{ + size_t c = count(to); + size_t len = size(); + size_t tolen = PlatformSpecificStrLen(to); + size_t withlen = PlatformSpecificStrLen(with); + + size_t newsize = len + (withlen * c) - (tolen * c) + 1; + + if (newsize) { + char* newbuf = allocStringBuffer(newsize); + for (size_t i = 0, j = 0; i < len;) { + if (PlatformSpecificStrNCmp(&buffer_[i], to, tolen) == 0) { + StrNCpy(&newbuf[j], with, withlen + 1); + j += withlen; + i += tolen; + } + else { + newbuf[j] = buffer_[i]; + j++; + i++; + } + } + deallocStringBuffer(buffer_); + buffer_ = newbuf; + buffer_[newsize - 1] = '\0'; + } + else { + buffer_ = getEmptyString(); + buffer_[0] = '\0'; + } +} + +SimpleString SimpleString::toLower() const +{ + SimpleString str(*this); + + size_t str_size = str.size(); + for (size_t i = 0; i < str_size; i++) + str.buffer_[i] = PlatformSpecificToLower(str.buffer_[i]); + + return str; +} + +const char *SimpleString::asCharString() const +{ + return buffer_; +} + +size_t SimpleString::size() const +{ + return PlatformSpecificStrLen(buffer_); +} + +bool SimpleString::isEmpty() const +{ + return size() == 0; +} + + + +SimpleString::~SimpleString() +{ + deallocStringBuffer(buffer_); +} + +bool operator==(const SimpleString& left, const SimpleString& right) +{ + return 0 == PlatformSpecificStrCmp(left.asCharString(), right.asCharString()); +} + +bool SimpleString::equalsNoCase(const SimpleString& str) const +{ + return toLower() == str.toLower(); +} + + +bool operator!=(const SimpleString& left, const SimpleString& right) +{ + return !(left == right); +} + +SimpleString SimpleString::operator+(const SimpleString& rhs) +{ + SimpleString t(buffer_); + t += rhs.buffer_; + return t; +} + +SimpleString& SimpleString::operator+=(const SimpleString& rhs) +{ + return operator+=(rhs.buffer_); +} + +SimpleString& SimpleString::operator+=(const char* rhs) +{ + size_t originalSize = this->size(); + size_t additionalStringSize = PlatformSpecificStrLen(rhs) + 1; + size_t sizeOfNewString = originalSize + additionalStringSize; + char* tbuffer = copyToNewBuffer(this->buffer_, sizeOfNewString); + StrNCpy(tbuffer + originalSize, rhs, additionalStringSize); + deallocStringBuffer(this->buffer_); + this->buffer_ = tbuffer; + return *this; +} + +void SimpleString::padStringsToSameLength(SimpleString& str1, SimpleString& str2, char padCharacter) +{ + if (str1.size() > str2.size()) { + padStringsToSameLength(str2, str1, padCharacter); + return; + } + + char pad[2]; + pad[0] = padCharacter; + pad[1] = 0; + str1 = SimpleString(pad, str2.size() - str1.size()) + str1; +} + +SimpleString SimpleString::subString(size_t beginPos, size_t amount) const +{ + if (beginPos > size()-1) return ""; + + SimpleString newString = buffer_ + beginPos; + + if (newString.size() > amount) + newString.buffer_[amount] = '\0'; + + return newString; +} + +char SimpleString::at(int pos) const +{ + return buffer_[pos]; +} + +int SimpleString::find(char ch) const +{ + return findFrom(0, ch); +} + +int SimpleString::findFrom(size_t starting_position, char ch) const +{ + size_t length = size(); + for (size_t i = starting_position; i < length; i++) + if (buffer_[i] == ch) return (int) i; + return -1; +} + +SimpleString SimpleString::subStringFromTill(char startChar, char lastExcludedChar) const +{ + int beginPos = find(startChar); + if (beginPos < 0) return ""; + + int endPos = findFrom((size_t)beginPos, lastExcludedChar); + if (endPos == -1) return subString((size_t)beginPos, size()); + + return subString((size_t)beginPos, (size_t) (endPos - beginPos)); +} + +char* SimpleString::copyToNewBuffer(const char* bufferToCopy, size_t bufferSize) +{ + if(bufferSize == 0) bufferSize = PlatformSpecificStrLen(bufferToCopy) + 1; + + char* newBuffer = allocStringBuffer(bufferSize); + StrNCpy(newBuffer, bufferToCopy, bufferSize); + newBuffer[bufferSize-1] = '\0'; + return newBuffer; +} + +void SimpleString::copyToBuffer(char* bufferToCopy, size_t bufferSize) const +{ + if (bufferToCopy == NULL || bufferSize == 0) return; + + size_t sizeToCopy = (bufferSize-1 < size()) ? bufferSize : size(); + + StrNCpy(bufferToCopy, buffer_, sizeToCopy); + bufferToCopy[sizeToCopy] = '\0'; +} + +SimpleString StringFrom(bool value) +{ + return SimpleString(StringFromFormat("%s", value ? "true" : "false")); +} + +SimpleString StringFrom(const char *value) +{ + return SimpleString(value); +} + +SimpleString StringFromOrNull(const char * expected) +{ + return (expected) ? StringFrom(expected) : "(null)"; +} + +SimpleString StringFrom(int value) +{ + return StringFromFormat("%d", value); +} + +SimpleString StringFrom(long value) +{ + return StringFromFormat("%ld", value); +} + +SimpleString StringFrom(const void* value) +{ + return SimpleString("0x") + HexStringFrom(value); +} + +SimpleString HexStringFrom(long value) +{ + return StringFromFormat("%lx", value); +} + +SimpleString HexStringFrom(unsigned long value) +{ + return StringFromFormat("%lx", value); +} + +static long convertPointerToLongValue(const void* value) +{ + /* + * This way of converting also can convert a 64bit pointer in a 32bit integer by truncating. + * This isn't the right way to convert pointers values and need to change by implementing a + * proper portable way to convert pointers to strings. + */ + long* long_value = (long*) &value; + return *long_value; +} + +SimpleString HexStringFrom(const void* value) +{ + return StringFromFormat("%lx", convertPointerToLongValue(value)); +} + +SimpleString StringFrom(double value, int precision) +{ + return StringFromFormat("%.*g", precision, value); +} + +SimpleString StringFrom(char value) +{ + return StringFromFormat("%c", value); +} + +SimpleString StringFrom(const SimpleString& value) +{ + return SimpleString(value); +} + +SimpleString StringFromFormat(const char* format, ...) +{ + SimpleString resultString; + va_list arguments; + va_start(arguments, format); + + resultString = VStringFromFormat(format, arguments); + va_end(arguments); + return resultString; +} + +SimpleString StringFrom(unsigned int i) +{ + return StringFromFormat("%10u (0x%08x)", i, i); +} + +#if CPPUTEST_USE_STD_CPP_LIB + +#include <string> + +SimpleString StringFrom(const std::string& value) +{ + return SimpleString(value.c_str()); +} + +SimpleString StringFrom(unsigned long i) +{ + return StringFromFormat("%lu (0x%lx)", i, i); +} + +#else + +SimpleString StringFrom(unsigned long value) +{ + return StringFromFormat("%lu", value); +} + +#endif + +//Kludge to get a va_copy in VC++ V6 +#ifndef va_copy +#define va_copy(copy, original) copy = original; +#endif + +SimpleString VStringFromFormat(const char* format, va_list args) +{ + va_list argsCopy; + va_copy(argsCopy, args); + enum + { + sizeOfdefaultBuffer = 100 + }; + char defaultBuffer[sizeOfdefaultBuffer]; + SimpleString resultString; + + size_t size = (size_t)PlatformSpecificVSNprintf(defaultBuffer, sizeOfdefaultBuffer, format, args); + if (size < sizeOfdefaultBuffer) { + resultString = SimpleString(defaultBuffer); + } + else { + size_t newBufferSize = size + 1; + char* newBuffer = SimpleString::allocStringBuffer(newBufferSize); + PlatformSpecificVSNprintf(newBuffer, newBufferSize, format, argsCopy); + resultString = SimpleString(newBuffer); + + SimpleString::deallocStringBuffer(newBuffer); + } + va_end(argsCopy); + return resultString; +} + +SimpleStringCollection::SimpleStringCollection() +{ + collection_ = 0; + size_ = 0; +} + +void SimpleStringCollection::allocate(size_t _size) +{ + delete[] collection_; + + size_ = _size; + collection_ = new SimpleString[size_]; +} + +SimpleStringCollection::~SimpleStringCollection() +{ + delete[] (collection_); +} + +size_t SimpleStringCollection::size() const +{ + return size_; +} + +SimpleString& SimpleStringCollection::operator[](size_t index) +{ + if (index >= size_) { + empty_ = ""; + return empty_; + } + + return collection_[index]; +}