Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: src/CppUTest/SimpleString.cpp
- Revision:
- 0:0b799af9d58e
- Child:
- 1:4769360130ed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CppUTest/SimpleString.cpp Tue Jan 28 09:27:41 2014 +0000
@@ -0,0 +1,515 @@
+/*
+ * 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];
+}
+