fork
Fork of cpputest by
src/CppUTest/SimpleString.cpp
- Committer:
- Kojto
- Date:
- 2015-05-13
- Revision:
- 3:9e8c8907d9ee
- Parent:
- 1:4769360130ed
File content as of revision 3:9e8c8907d9ee:
/* * 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]; }